Skip to content

Latest commit

 

History

History
202 lines (144 loc) · 9.15 KB

File metadata and controls

202 lines (144 loc) · 9.15 KB

Releasing Fluffy Flash

This document describes how to produce an end-to-end release of Fluffy Flash via the GitHub Actions pipeline in .github/workflows/release.yml.

Guardrails CodeQL Security (Semgrep + Trivy)

The pipeline supports two paths:

  1. Manual dry-run (workflow_dispatch) — produces an unsigned .app and the GPL source bundle. Used for verifying the pipeline without publishing a Release.
  2. Tag push (v*) — produces a Release attached to the tag. If the codesign / notarization secrets are present, the .app is signed and notarized automatically.

Prerequisites

Need Where it lives
Apple Developer Program enrolment apple.com
Developer ID Application certificate (.p12 + password) local Keychain export
App-specific password (Apple ID) appleid.apple.com → "App-Specific Passwords"
Apple Team ID appleid.apple.com / Apple Developer portal

GitHub Secrets

Set the following on the repository (Settings → Secrets and variables → Actions):

Secret Description
MACOS_CERTIFICATE_P12_BASE64 base64 -i DeveloperID.p12 | pbcopy of the exported certificate.
MACOS_CERTIFICATE_PASSWORD The password used to export the .p12.
MACOS_KEYCHAIN_PASSWORD Any throwaway string. Used to lock the temporary CI keychain.
MACOS_DEVELOPER_ID_APPLICATION_NAME Identity name, e.g. Developer ID Application: Foo Bar (TEAMID).
APPLE_ID Apple ID email used for notarization.
APPLE_TEAM_ID Apple Team ID (10-char string).
APPLE_APP_SPECIFIC_PASSWORD App-specific password generated for notarization.

If any of these is missing, the pipeline still succeeds but produces an unsigned build (signing/notarization steps log a warning and skip).

0. Pre-release checklist (every version)

Complete before tagging v*. All items should be green on the commit you tag.

Security & CI (free)

Check Workflow Where to look
Secret scan + forbidden paths guardrails.yml Actions → Guardrails
SAST (Swift) security-codeql.yml Actions → Security (CodeQL)
Semgrep + Trivy (repo) security-semgrep-trivy.yml Actions → Security (Semgrep + Trivy)
# After pushing your release branch / PR, confirm workflows are green:
gh run list --workflow=guardrails.yml --limit 3
gh run list --workflow=security-codeql.yml --limit 3
gh run list --workflow=security-semgrep-trivy.yml --limit 3

CodeQL runs on macos-15 and builds Debug (unsigned) — allow ~15–30 minutes on first run.

Build & tests (local)

cd FluffyFlash
WIST_SKIP_TOOL_BUNDLE=1 xcodebuild -project "Fluffy Flash.xcodeproj" -scheme FluffyFlash \
  -configuration Debug -destination 'platform=macOS' build

WIST_SKIP_TOOL_BUNDLE=1 xcodebuild -project "Fluffy Flash.xcodeproj" -scheme FluffyFlash \
  -configuration Debug -destination 'platform=macOS' test -only-testing:"Fluffy FlashTests"

Version bump

In Xcode (target FluffyFlash → Build Settings):

  • MARKETING_VERSION → user-facing version (e.g. 0.3.0)
  • CURRENT_PROJECT_VERSION → integer build (must increase for Sparkle), e.g. 6

Docs (same session as the tag)

Sparkle (after the ZIP is on GitHub)

  1. Upload signed/notarized FluffyFlash-X.Y.Z.zip to the GitHub Release first.
  2. Run Sparkle sign_update on that ZIP (see FluffyFlash/docs/Sparkle.md).
  3. Add a new <item> at the top of FluffyFlash/appcast.xml with sparkle:version = build number, url = release asset URL.
  4. Commit and push appcast.xml only after the ZIP URL returns HTTP 200.
  5. On a test Mac with the previous build: Settings → Check for updates…

1. Manual dry-run (no release published)

Use this on every meaningful workflow change before tagging.

gh workflow run "Release artifacts" --ref main \
  -f sign_and_notarize=false
gh run watch

Artifacts (downloadable from the run page):

  • FluffyFlash-<branch-or-dev>.zip
  • FluffyFlash-<branch-or-dev>.zip.sha256
  • THIRD_PARTY_NOTICES.txt
  • third-party-sources.tar.gz
  • tool-versions.txt
  • third-party-manifest.json

If sign_and_notarize=true is passed, the same workflow also runs codesign + notarytool submit --wait + stapler staple — provided secrets are configured.

2. Tag-driven release (publishes a GitHub Release)

Merge your feature branch to main first, then:

git switch main
git pull --rebase
# Confirm security workflows are green on this commit (see §0).

git tag v0.3.0
git push origin v0.3.0
gh run watch --workflow="Release artifacts"

The workflow auto-creates a GitHub Release named after the tag and attaches:

  • FluffyFlash-v0.3.0.zip (+ .sha256)
  • THIRD_PARTY_NOTICES.txt, third-party-sources.tar.gz, tool-versions.txt, third-party-manifest.json

If GitHub Secrets are configured, the .app inside the ZIP is codesigned + notarized. Then complete Sparkle steps in §0 (appcast + sign_update).

Typical ChromeOS / feature release flow:

git switch feature/chromeos-mode
git add -A && git commit -m "Release 0.3.0: ChromeOS mode, security CI, download fixes"
git push -u origin feature/chromeos-mode
# Open PR → wait for Guardrails + CodeQL + Semgrep/Trivy
gh pr merge --merge   # or squash per your convention

git switch main && git pull
git tag v0.3.0 && git push origin v0.3.0
gh run watch --workflow="Release artifacts"
# After release assets exist → sign_update → update appcast.xml → push

To delete a test release and tag:

gh release delete v0.0.0-rc1 --yes --cleanup-tag

3. Local verification of a downloaded build

unzip FluffyFlash-v0.0.0-rc1.zip
codesign --verify --deep --strict --verbose=2 FluffyFlash.app
spctl -a -vv -t install FluffyFlash.app
xcrun stapler validate FluffyFlash.app

Expected: accepted, source=Notarized Developer ID.

4. Common failure modes

Symptom Likely cause Fix
xcodebuild step fails during Bundle Embedded CLI Tools Homebrew not yet primed on runner The workflow now runs bundle-mac-cli-tools.sh explicitly before xcodebuild. Make sure brew is reachable.
notarytool submit rejects with Invalid Missing hardened runtime, expired cert, embedded binary unsigned Inspect notarization log: xcrun notarytool log <submission-id> --apple-id ... --team-id .... Sign every Mach-O inside Resources/Tools/bin and EmbeddedCLI/lib.
spctl reports unsigned Pipeline ran without secrets Configure all secrets above and rerun.
Tag-driven build does not pick up new files The new files are not committed The workflow checks out the tagged commit; ensure all changes are committed before tagging.

5. Public README (required for every versioned release)

When you publish a GitHub Release / Sparkle update, update user-facing README in the same work session (see .cursor/rules/github-release-readme.mdc):

File Purpose
README.md GitHub landing page (English)
README.ru.md Russian mirror
FluffyFlash/README.md Xcode folder: version pointer + build commands

Minimum content per release:

  • What's new (or «Что нового») with the new tag link and 2–5 bullets.
  • Features / requirements if the release changed user-visible scope (e.g. new Linux mode).
  • Link to FluffyFlash/docs/RELEASE-NOTES-X.Y.Z.md for full notes.
  • Remind existing users: Settings → Check for updates… (Sparkle).

The release badge in README uses releases/latest and updates automatically on GitHub.

6. Updating third-party tooling

Whenever a bundled CLI tool is added/replaced, follow .cursor/rules/legal-third-party-intake.mdc and update: