diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..098aa9d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +name: CI + +on: + pull_request: + push: + branches: + - main + +jobs: + release-check: + name: Release readiness + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 9.0.0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run release readiness checks + run: pnpm release:check diff --git a/README.md b/README.md index 50a4805..6b3cd07 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0-3178C6.svg)](https://www.typescriptlang.org/) [![React](https://img.shields.io/badge/React-18-61DAFB.svg)](https://reactjs.org/) -[Features](#-key-features) • [Installation](#-installation--development) • [Building](#building-for-production) • [DRM Support](#-drm-content-playback) +[Features](#-key-features) • [Installation](#-installation--development) • [Building](#building-for-production) • [DRM Support](#-drm-content-playback) • [Release Readiness](docs/RELEASE_READINESS.md) diff --git a/docs/RELEASE_READINESS.md b/docs/RELEASE_READINESS.md new file mode 100644 index 0000000..b6c3578 --- /dev/null +++ b/docs/RELEASE_READINESS.md @@ -0,0 +1,90 @@ +# Stage 2 Release Readiness + +Stage 2 prepares aka-browser for repeatable public releases after the Stage 0 beta +and Stage 1 i18n work. The goal is not to add large product features. The goal is +to make every release build verifiable, reproducible, and safe to publish. + +## Scope + +- Keep the repository buildable with a single release-readiness command. +- Document the manual gates that cannot be verified without private credentials + or paid streaming accounts. +- Require the same quality gate in GitHub Actions before release work is merged. +- Keep DRM-specific release checks explicit because aka-browser depends on + Castlabs Electron and Widevine behavior. + +## Local Release Gate + +Run this from the repository root before creating a release candidate: + +```bash +pnpm release:check +``` + +The command verifies: + +- TypeScript checks for every workspace task. +- The repository lint task. +- Production build output. +- `pnpm audit --prod=false`. +- The `apps/browser/src` 450-line source file policy. +- `git diff --check`. + +If this command fails, do not package or publish a release. + +## Manual Release Gates + +These gates require credentials, hardware, or third-party accounts and must be +recorded in the release notes or release checklist. + +| Gate | Required Evidence | +| --- | --- | +| EVS account | `pnpm --filter @aka-browser/browser evs:verify` succeeds. | +| Apple signing certificate | `security find-identity -v -p codesigning` shows a valid Developer ID Application identity. | +| Notarized macOS app | `spctl -a -vv -t install release/mac-*/aka-browser.app` reports `accepted`. | +| Widevine CDM available | The packaged app logs a Widevine CDM version at startup. | +| DRM playback | Netflix, Disney+, or another Widevine service starts playback in the packaged app. | +| Release assets | GitHub Release contains the expected DMG artifacts and checksums. | + +## Current Local Gate Status + +Last checked: 2026-05-19 KST. + +| Gate | Status | Evidence | +| --- | --- | --- | +| Local release gate | Passing | `pnpm release:check` completed successfully. | +| Apple signing certificate | Present | `security find-identity -v -p codesigning` found `Developer ID Application: Hamin Lee (5Z9KNW282F)`. | +| EVS account | Blocked | `pnpm --filter @aka-browser/browser evs:verify` failed because `castlabs-evs` is not installed. | +| Notarization | Not checked | Requires a packaged app built after EVS setup. | +| DRM playback | Not checked | Requires an EVS-signed packaged app and a Widevine streaming account. | + +## Release Candidate Checklist + +1. Start from a clean `main` branch. +2. Run `pnpm install --frozen-lockfile`. +3. Run `pnpm release:check`. +4. Run `pnpm --filter @aka-browser/browser evs:verify`. +5. Build the app with `pnpm --filter @aka-browser/browser package`. +6. Verify notarization with `spctl`. +7. Launch the packaged app. +8. Confirm a blank tab opens and Settings is reachable. +9. Confirm Settings > Language shows System Default, English, and Korean. +10. Confirm Widevine CDM is present in startup logs. +11. Confirm at least one Widevine-protected streaming service starts playback. +12. Upload release assets and checksums to GitHub Releases. +13. Publish release notes with any skipped manual gates called out explicitly. + +## Blocking Rules + +- Do not release if `pnpm release:check` fails. +- Do not advertise DRM playback if EVS signing or DRM playback was not verified + on the packaged app. +- Do not publish macOS downloads as stable if notarization was skipped or failed. +- Do not replace Castlabs Electron with standard Electron during release + maintenance. + +## Stage 2 Project Items + +Stage 2 project items should stay focused on release readiness. Good items are +small, verifiable, and either close with repository evidence or remain open with +a clear external gate. diff --git a/package.json b/package.json index 398119c..ab89da5 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "dev": "turbo run dev", "lint": "turbo run lint", "format": "prettier --write \"**/*.{ts,tsx,md}\"", - "check-types": "turbo run check-types" + "check-types": "turbo run check-types", + "release:check": "bash scripts/release-check.sh" }, "devDependencies": { "prettier": "^3.8.3", diff --git a/scripts/release-check.sh b/scripts/release-check.sh new file mode 100755 index 0000000..f92dae3 --- /dev/null +++ b/scripts/release-check.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT_DIR" + +echo "== TypeScript, lint, and build ==" +pnpm exec turbo run check-types lint build --force + +echo +echo "== Dependency audit ==" +pnpm audit --prod=false + +echo +echo "== Source file size policy ==" +find apps/browser/src -type f \( -name '*.ts' -o -name '*.tsx' \) -print0 \ + | xargs -0 wc -l \ + | awk '$2 != "total" && $1 > 450 {print; bad=1} END {exit bad}' + +echo +echo "== Whitespace check ==" +git diff --check + +echo +echo "Release readiness checks passed."