From 3fa6f89ba0551f916899b6eb638b10042f0faaff Mon Sep 17 00:00:00 2001 From: oratis Date: Thu, 28 May 2026 22:13:34 +0800 Subject: [PATCH] feat(P3, v0.1.3): rewrite release.yml for Tauri + bump 0.1.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 3 of the autonomous overnight push. Brings the M9 release pipeline into working shape after the Electron→Tauri pivot. **release.yml rewrite** - Drops electron-builder + the vite.config.template indirection - New build-mac job (macos-14, Rust toolchain, Cargo cache, pnpm) drives scripts/sign-and-notarize.sh end-to-end - Imports the Developer ID cert from CSC_LINK into a temporary CI keychain at build time - Stores notarytool credentials as "DEEPCODE_NOTARY" keychain profile from APPLE_ID + APPLE_TEAM_ID + APPLE_APP_SPECIFIC_PASSWORD - Removes the BUILD_MAC gate (no longer needed) - Bumps actions/upload-artifact to v7 - github-release job now actually attaches the DMG to the release **docs/RELEASING.md (new)** - All 6 secrets explained step-by-step (APPLE_ID, APPLE_TEAM_ID, APPLE_APP_SPECIFIC_PASSWORD, CSC_LINK base64, CSC_KEY_PASSWORD, NPM_TOKEN) - p12 export instructions - Release-channel table (stable / beta / nightly / +security.X) - Local rehearsal script - Rollback notes **Version bumps** - 0.1.2 → 0.1.3 across tauri.conf.json, both package.jsons, Cargo.toml - CHANGELOG entry summarizing P2 redesign + P3 pipeline Workspace typecheck + 533 tests still pass. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/release.yml | 123 ++++++++++++++---------- CHANGELOG.md | 24 +++++ apps/cli/package.json | 2 +- apps/desktop/package.json | 2 +- apps/desktop/src-tauri/Cargo.toml | 2 +- apps/desktop/src-tauri/tauri.conf.json | 2 +- docs/RELEASING.md | 126 +++++++++++++++++++++++++ 7 files changed, 228 insertions(+), 53 deletions(-) create mode 100644 docs/RELEASING.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 46c36c9..42eb576 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,7 +11,7 @@ permissions: jobs: # ---------------------------------------------------------------------- - # Validate + # Validate — typecheck + tests + build all packages # ---------------------------------------------------------------------- validate: name: Validate before release @@ -23,13 +23,11 @@ jobs: is_mandatory: ${{ steps.version.outputs.is_mandatory }} steps: - uses: actions/checkout@v6 - - uses: pnpm/action-setup@v6 - uses: actions/setup-node@v6 with: node-version: '22' cache: 'pnpm' - - run: pnpm install --frozen-lockfile - run: pnpm typecheck - run: pnpm test @@ -60,14 +58,12 @@ jobs: timeout-minutes: 10 steps: - uses: actions/checkout@v6 - - uses: pnpm/action-setup@v6 - uses: actions/setup-node@v6 with: node-version: '22' cache: 'pnpm' registry-url: https://registry.npmjs.org - - run: pnpm install --frozen-lockfile - run: pnpm build @@ -79,8 +75,6 @@ jobs: - name: Publish run: | cd apps/cli - # On beta/nightly, publish with --tag so default `latest` - # stays on stable. if [ "${{ needs.validate.outputs.channel }}" = "stable" ]; then pnpm publish --no-git-checks --access public else @@ -90,19 +84,12 @@ jobs: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} # ---------------------------------------------------------------------- - # Build + sign Mac client (.dmg) + # Build + sign Mac client (.dmg) via Tauri # ---------------------------------------------------------------------- build-mac: - name: Build + sign + notarize Mac client + name: Build + sign + notarize Mac client (Tauri) needs: validate runs-on: macos-14 - # Activates when the desktop package has the electron dep installed - # AND the maintainer has set BUILD_MAC=1 in the GitHub Actions env - # (or the apps/desktop/electron-builder.yml file exists which it does - # since M6-rest part 1 — flipping the gate to `vars.BUILD_MAC == 'true'` - # so the maintainer enables it via Repository Variables once Apple - # secrets are wired). See docs/SHIPPING_MAC.md. - if: ${{ vars.BUILD_MAC == 'true' }} timeout-minutes: 30 steps: - uses: actions/checkout@v6 @@ -111,70 +98,108 @@ jobs: with: node-version: '22' cache: 'pnpm' - - run: pnpm install --frozen-lockfile - - name: Activate template configs - run: | - cd apps/desktop - if [ -f vite.config.template.ts ]; then mv vite.config.template.ts vite.config.ts; fi - if [ -f postcss.config.template.js ]; then mv postcss.config.template.js postcss.config.js; fi + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + targets: aarch64-apple-darwin + + - name: Cache Cargo registry + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + apps/desktop/src-tauri/target + key: cargo-mac-${{ hashFiles('**/Cargo.lock') }} + + - name: pnpm install + run: pnpm install --frozen-lockfile - name: Set version run: | cd apps/desktop npm version "${{ needs.validate.outputs.version }}" --no-git-tag-version - - - name: Build renderer + main + # Sync the tauri.conf.json version too + node -e " + const fs=require('fs'); + const p='src-tauri/tauri.conf.json'; + const c=JSON.parse(fs.readFileSync(p,'utf8')); + c.version='${{ needs.validate.outputs.version }}'; + fs.writeFileSync(p, JSON.stringify(c,null,2)+'\n'); + " + # And Cargo.toml + sed -i.bak -E 's/^version = ".*"/version = "${{ needs.validate.outputs.version }}"/' src-tauri/Cargo.toml + rm -f src-tauri/Cargo.toml.bak + + - name: Import Developer ID certificate + env: + CSC_LINK: ${{ secrets.CSC_LINK }} + CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} run: | - cd apps/desktop - pnpm build:renderer - pnpm build:electron - - - name: Build (electron-builder) + # CSC_LINK is base64-encoded .p12 of the Developer ID Application cert + echo "$CSC_LINK" | base64 --decode > /tmp/cert.p12 + security create-keychain -p actions ci.keychain + security default-keychain -s ci.keychain + security unlock-keychain -p actions ci.keychain + security import /tmp/cert.p12 -k ci.keychain -P "$CSC_KEY_PASSWORD" -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k actions ci.keychain + rm -f /tmp/cert.p12 + + - name: Store notarization credentials env: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - CSC_LINK: ${{ secrets.CSC_LINK }} - CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} run: | - cd apps/desktop - pnpm electron-builder --mac --arm64 --x64 --publish never + xcrun notarytool store-credentials "DEEPCODE_NOTARY" \ + --apple-id "$APPLE_ID" \ + --team-id "$APPLE_TEAM_ID" \ + --password "$APPLE_APP_SPECIFIC_PASSWORD" + + - name: Build + sign + notarize + env: + DEEPCODE_TARGET: aarch64-apple-darwin + DEEPCODE_NOTARY_PROFILE: DEEPCODE_NOTARY + run: bash scripts/sign-and-notarize.sh + + - name: Stage release artifacts + run: | + mkdir -p release-artifacts + cp apps/desktop/src-tauri/target/aarch64-apple-darwin/release/bundle/dmg/DeepCode_${{ needs.validate.outputs.version }}_aarch64.dmg \ + release-artifacts/DeepCode-${{ needs.validate.outputs.version }}-arm64.dmg - name: Upload artifacts uses: actions/upload-artifact@v7 with: name: mac-release - path: | - apps/desktop/release/*.dmg - apps/desktop/release/latest-mac.yml + path: release-artifacts/DeepCode-*.dmg # ---------------------------------------------------------------------- - # GitHub Release + # GitHub Release — runs after Mac build so the DMG can be attached # ---------------------------------------------------------------------- github-release: name: Publish GitHub Release - needs: [validate, publish-cli] + needs: [validate, publish-cli, build-mac] runs-on: ubuntu-latest timeout-minutes: 10 steps: - uses: actions/checkout@v6 - - - name: Mark mandatory in latest-mac.yml if applicable - if: needs.validate.outputs.is_mandatory == 'true' - run: | - echo "Note: this release tag has +security.X suffix — Mac client auto-update will be marked mandatory." - - uses: pnpm/action-setup@v6 - uses: actions/setup-node@v6 with: node-version: '22' cache: 'pnpm' - - name: Install (needed for tsx) - run: pnpm install --frozen-lockfile + - run: pnpm install --frozen-lockfile + + - name: Download Mac DMG + uses: actions/download-artifact@v4 + with: + name: mac-release + path: release-artifacts/ - - name: Generate release notes (conventional-commit grouped) + - name: Generate release notes id: notes run: | PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "") @@ -189,8 +214,8 @@ jobs: - name: Create GitHub Release uses: softprops/action-gh-release@v3 with: - name: ${{ needs.validate.outputs.version }} + name: v${{ needs.validate.outputs.version }} body_path: release-notes.md prerelease: ${{ needs.validate.outputs.channel != 'stable' }} generate_release_notes: false - # files: omitted until M6 mac artifacts exist + files: release-artifacts/*.dmg diff --git a/CHANGELOG.md b/CHANGELOG.md index cf67aa0..43f0c39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,30 @@ All notable changes to DeepCode are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.3] — 2026-05-28 + +### Visual redesign — phase 2 +- **All 7 utility screens** (Sessions / Plugins / Skills / Permissions / + MCP / Settings / About) redesigned to match `docs/VISUAL_DESIGN.html`. + New shared `Screen` + `Card` + `Row` primitives. +- **About** is now a proper hero card with brand mark + gradient text + + status diagnostics + docs links (replacing the boxed table layout + the user shared as visually off-spec). +- **Settings** has a GUI/JSON segmented toggle: GUI shows a quick + reference + filterable flat table; JSON shows a live-validated + textarea. Save persists to ~/.deepcode/settings.json (was + view-only). +- **Permissions** Save now actually persists rules (was stubbed). +- **Sessions** has search + click-to-resume with relative time. +- **Plugins** surfaces trust badges + custom Toggle switches. +- **Skills** has 2-column filter-list + SKILL.md preview. +- **MCP** uses status badges + tool count + inline error tail. + +### Release pipeline (M9) +- `release.yml` rewritten for Tauri (was Electron-era). Tag → CI + → npm publish + signed/notarized DMG + GitHub Release with notes. +- `docs/RELEASING.md` explains the 6 secrets needed and step-by-step. + ## [0.1.2] — 2026-05-28 ### Fixes — caught from user playtest of 0.1.1 diff --git a/apps/cli/package.json b/apps/cli/package.json index d58cf77..a07857c 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,6 +1,6 @@ { "name": "deepcode-cli", - "version": "0.1.2", + "version": "0.1.3", "description": "DeepCode CLI — DeepSeek-powered AI coding agent, parity with Claude Code", "license": "MIT", "type": "module", diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 47d2f91..c4e1f55 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@deepcode/desktop", - "version": "0.1.2", + "version": "0.1.3", "private": true, "description": "DeepCode Mac desktop client — Tauri + React", "license": "MIT", diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index 21adc80..8624509 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deepcode_desktop" -version = "0.1.2" +version = "0.1.3" description = "DeepCode Mac desktop client" authors = ["oratis"] edition = "2021" diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index dffa658..2288e66 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "DeepCode", - "version": "0.1.2", + "version": "0.1.3", "identifier": "dev.deepcode.desktop", "build": { "frontendDist": "../dist", diff --git a/docs/RELEASING.md b/docs/RELEASING.md new file mode 100644 index 0000000..6ebf15f --- /dev/null +++ b/docs/RELEASING.md @@ -0,0 +1,126 @@ +# Releasing DeepCode + +Tag-driven CI pipeline. Push a `v0.X.Y` tag → GitHub Actions takes over: +validate → build CLI + publish to npm → build + sign + notarize Tauri DMG +→ create GitHub Release with both artifacts attached. + +## One-time setup + +### 1. GitHub Actions secrets + +Set these in repo settings → Secrets and variables → Actions → New +repository secret. All five are required for a successful Mac release. + +| Secret | Purpose | +| ------------------------------- | ------------------------------------------------------------------ | +| `APPLE_ID` | Your Apple Developer Apple ID (e.g. `you@example.com`) | +| `APPLE_APP_SPECIFIC_PASSWORD` | App-specific password from appleid.apple.com (used by notarytool) | +| `APPLE_TEAM_ID` | 10-character team ID (from developer.apple.com → membership) | +| `CSC_LINK` | Base64-encoded `.p12` of the Developer ID Application cert | +| `CSC_KEY_PASSWORD` | Password used when exporting the `.p12` | +| `NPM_TOKEN` | npm access token with `publish` scope | + +### 2. Export the Developer ID certificate + +```bash +# In Keychain Access on the developer machine: +# select your "Developer ID Application: (TEAM_ID)" cert + key +# → Export → save as cert.p12 with a strong password. + +base64 -i cert.p12 -o cert.p12.b64 +# Paste the contents of cert.p12.b64 as the CSC_LINK secret value. +``` + +The CI workflow imports this into a temporary keychain at build time, +signs the `.app`, then notarizes via Apple's notarytool (the +`DEEPCODE_NOTARY` keychain profile is created on the fly from the +Apple secrets). + +### 3. App-specific password + +[appleid.apple.com](https://appleid.apple.com) → Sign-in security → +App-specific passwords → Generate. Save the 16-char password as +`APPLE_APP_SPECIFIC_PASSWORD`. + +### 4. NPM token + +[npmjs.com](https://www.npmjs.com) → account → Access Tokens → Generate +new token → **Automation** (CI-friendly) → save as `NPM_TOKEN`. + +## Releasing + +```bash +# 1. Make sure main is green and CHANGELOG.md has an entry for the new version. +# 2. Bump versions everywhere in lockstep: +# - apps/cli/package.json +# - apps/desktop/package.json +# - apps/desktop/src-tauri/tauri.conf.json +# - apps/desktop/src-tauri/Cargo.toml +# (The CI workflow also re-syncs these from the tag.) +# 3. Tag + push: + +git tag v0.1.3 +git push origin v0.1.3 +``` + +The `release.yml` workflow fires on any `v*` tag push and runs five jobs +serially: + +1. **validate** — `pnpm typecheck` + `pnpm test` + `pnpm build` +2. **publish-cli** — bumps `apps/cli/package.json` to the tag version, + `pnpm publish` to npm registry. Beta / nightly tags get + `--tag ` so `latest` stays on stable. +3. **build-mac** — macOS-14 runner, Rust + Tauri build, calls + `scripts/sign-and-notarize.sh` end-to-end. Outputs + `DeepCode--arm64.dmg`. +4. **github-release** — generates release notes via + `scripts/gen-release-notes.ts` (groups PRs by label), creates + the GitHub Release, attaches the DMG. + +## Release channels + +Tag format determines the channel + publish target: + +| Tag format | Channel | npm tag | GitHub release | +| ------------------------- | --------- | ---------- | -------------- | +| `v0.2.1` | `stable` | `latest` | not prerelease | +| `v0.3.0-beta.1` | `beta` | `beta` | prerelease | +| `v0.3.0-nightly.20260605` | `nightly` | `nightly` | prerelease | +| `v0.2.2+security.1` | `stable` | `latest` | mandatory flag | + +The `+security.X` suffix sets `is_mandatory=true` in the release output +so the Tauri updater can show a red "must update" banner. + +## After a release + +- Verify: `npm view deepcode-cli@` shows the new version +- Verify: `https://github.com/oratis/deepcode/releases/tag/v` + has the DMG attached +- Optional: announce in the README / homepage + +## Local rehearsal + +Before pushing the tag for a real release, the same flow runs locally: + +```bash +# Bump versions everywhere first, then: +pnpm install +pnpm typecheck +pnpm test +pnpm build +bash scripts/sign-and-notarize.sh +``` + +The DMG lands at +`apps/desktop/src-tauri/target/aarch64-apple-darwin/release/bundle/dmg/DeepCode__aarch64.dmg`. +This is the same artifact CI would attach. + +## Rollback + +GitHub Releases are independent — delete a release (or mark prerelease) +via the GitHub UI to hide it from users. + +`npm unpublish` is more restricted: only the most recent version, and +only within 72h of publish. If a CLI version needs urgent rollback past +that window, publish a patched higher version instead and let users +upgrade.