docs: close out the governance layer and cut 0.3.0 (#245) #1
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| permissions: | |
| contents: write # for GitHub Releases | |
| id-token: write # for npm provenance (if enabled) | |
| jobs: | |
| # ---------------------------------------------------------------------- | |
| # Validate — typecheck + tests + build all packages | |
| # ---------------------------------------------------------------------- | |
| validate: | |
| name: Validate before release | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| channel: ${{ steps.version.outputs.channel }} | |
| is_mandatory: ${{ steps.version.outputs.is_mandatory }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: pnpm/action-setup@v6 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '22' | |
| cache: 'pnpm' | |
| - run: pnpm install --frozen-lockfile | |
| - run: pnpm typecheck | |
| - run: pnpm lint | |
| - run: pnpm format:check | |
| - run: pnpm test | |
| - run: pnpm docs:check | |
| - run: pnpm release:check | |
| - name: Install Chromium | |
| run: pnpm --filter @deepcode/desktop exec playwright install --with-deps chromium | |
| - name: Exercise desktop protocol fixture | |
| run: pnpm --filter @deepcode/desktop test:e2e | |
| - name: Upload validation diagnostics | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: release-validation-diagnostics | |
| path: | | |
| apps/vscode/dist/release-gate-report.json | |
| apps/desktop/playwright-report | |
| apps/desktop/test-results | |
| if-no-files-found: ignore | |
| retention-days: 14 | |
| - id: version | |
| name: Parse version + channel from tag | |
| run: | | |
| TAG="${GITHUB_REF#refs/tags/}" | |
| VERSION="${TAG#v}" | |
| CHANNEL="stable" | |
| IS_MANDATORY="false" | |
| if [[ "$VERSION" == *-nightly.* ]]; then CHANNEL="nightly"; fi | |
| if [[ "$VERSION" == *-beta.* ]]; then CHANNEL="beta"; fi | |
| if [[ "$VERSION" == *+security.* ]]; then IS_MANDATORY="true"; fi | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "channel=$CHANNEL" >> $GITHUB_OUTPUT | |
| echo "is_mandatory=$IS_MANDATORY" >> $GITHUB_OUTPUT | |
| echo "Released as version=$VERSION channel=$CHANNEL mandatory=$IS_MANDATORY" | |
| # ---------------------------------------------------------------------- | |
| # Publish CLI to npm | |
| # ---------------------------------------------------------------------- | |
| publish-cli: | |
| name: Publish deepcode-cli to npm | |
| # Avoid a partial release: do not publish npm until both installable | |
| # desktop/editor artifacts have built successfully. | |
| needs: [validate, build-vscode, build-mac] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: pnpm/action-setup@v6 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '22' | |
| cache: 'pnpm' | |
| registry-url: https://registry.npmjs.org | |
| - run: pnpm install --frozen-lockfile | |
| # Before `pnpm build`: core's VERSION is compiled into dist, and it is what | |
| # `deepcode --version`, `--help`, `/upgrade` and `/bug` print. | |
| - name: Stamp core VERSION from tag | |
| run: | | |
| sed -i.bak -E "s/^export const VERSION = '.*';/export const VERSION = '${{ needs.validate.outputs.version }}';/" packages/core/src/index.ts | |
| rm -f packages/core/src/index.ts.bak | |
| grep -q "export const VERSION = '${{ needs.validate.outputs.version }}';" packages/core/src/index.ts | |
| - name: Set CLI version from tag | |
| run: | | |
| cd apps/cli | |
| npm version "${{ needs.validate.outputs.version }}" --no-git-tag-version | |
| - run: pnpm build | |
| - name: Publish | |
| run: | | |
| cd apps/cli | |
| if [ "${{ needs.validate.outputs.channel }}" = "stable" ]; then | |
| pnpm publish --no-git-checks --access public | |
| else | |
| pnpm publish --no-git-checks --access public --tag ${{ needs.validate.outputs.channel }} | |
| fi | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| # ---------------------------------------------------------------------- | |
| # Build installable VS Code extension | |
| # ---------------------------------------------------------------------- | |
| build-vscode: | |
| name: Build VS Code extension | |
| needs: validate | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: pnpm/action-setup@v6 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '22' | |
| cache: 'pnpm' | |
| - run: pnpm install --frozen-lockfile | |
| # The extension bundles its own app-server, which bundles core. | |
| - name: Stamp core VERSION from tag | |
| run: | | |
| sed -i.bak -E "s/^export const VERSION = '.*';/export const VERSION = '${{ needs.validate.outputs.version }}';/" packages/core/src/index.ts | |
| rm -f packages/core/src/index.ts.bak | |
| - name: Set extension version from tag | |
| run: npm version "${{ needs.validate.outputs.version }}" --no-git-tag-version | |
| working-directory: apps/vscode | |
| - name: Package VSIX | |
| run: | | |
| mkdir -p release-artifacts | |
| pnpm --dir apps/vscode package \ | |
| --out "../../release-artifacts/deepcode-${{ needs.validate.outputs.version }}.vsix" | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: vscode-release | |
| path: release-artifacts/deepcode-*.vsix | |
| # ---------------------------------------------------------------------- | |
| # Build + sign Mac client (.dmg) via Tauri | |
| # ---------------------------------------------------------------------- | |
| build-mac: | |
| name: Build + sign + notarize Mac client (Tauri) | |
| needs: validate | |
| runs-on: macos-14 | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: pnpm/action-setup@v6 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '22' | |
| cache: 'pnpm' | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: aarch64-apple-darwin | |
| - name: Cache Cargo registry | |
| uses: actions/cache@v6 | |
| 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: Prepare pinned Node sidecar runtime | |
| env: | |
| NODE_SIDECAR_VERSION: 22.23.1 | |
| NODE_SIDECAR_SHA256: ef28d8fab2c0e4314522d4bb1b7173270aa3937e93b92cb7de79c112ac1fa953 | |
| run: | | |
| archive="node-v${NODE_SIDECAR_VERSION}-darwin-arm64.tar.xz" | |
| curl --fail --location --retry 3 \ | |
| "https://nodejs.org/dist/v${NODE_SIDECAR_VERSION}/${archive}" \ | |
| --output "$RUNNER_TEMP/$archive" | |
| echo "${NODE_SIDECAR_SHA256} $RUNNER_TEMP/$archive" | shasum -a 256 --check | |
| tar -xJf "$RUNNER_TEMP/$archive" -C "$RUNNER_TEMP" | |
| echo "DEEPCODE_NODE_RUNTIME=$RUNNER_TEMP/node-v${NODE_SIDECAR_VERSION}-darwin-arm64/bin/node" >> "$GITHUB_ENV" | |
| - name: Set version | |
| run: | | |
| # core VERSION first — the sidecar it builds into reports it. | |
| sed -i.bak -E "s/^export const VERSION = '.*';/export const VERSION = '${{ needs.validate.outputs.version }}';/" packages/core/src/index.ts | |
| rm -f packages/core/src/index.ts.bak | |
| cd apps/desktop | |
| npm version "${{ needs.validate.outputs.version }}" --no-git-tag-version | |
| # 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 + the lockfile entry, which must agree or a --locked | |
| # cargo invocation refuses to build. | |
| sed -i.bak -E 's/^version = ".*"/version = "${{ needs.validate.outputs.version }}"/' src-tauri/Cargo.toml | |
| rm -f src-tauri/Cargo.toml.bak | |
| node -e " | |
| const fs=require('fs'); | |
| const p='src-tauri/Cargo.lock'; | |
| const s=fs.readFileSync(p,'utf8'); | |
| fs.writeFileSync(p, s.replace( | |
| /name = \"deepcode_desktop\"\nversion = \"[^\"]+\"/, | |
| 'name = \"deepcode_desktop\"\nversion = \"${{ needs.validate.outputs.version }}\"' | |
| )); | |
| " | |
| - name: Import Developer ID certificate | |
| env: | |
| CSC_LINK: ${{ secrets.CSC_LINK }} | |
| CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} | |
| run: | | |
| # 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 }} | |
| run: | | |
| 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: release-artifacts/DeepCode-*.dmg | |
| # ---------------------------------------------------------------------- | |
| # GitHub Release — runs after Mac build so the DMG can be attached | |
| # ---------------------------------------------------------------------- | |
| github-release: | |
| name: Publish GitHub Release | |
| needs: [validate, publish-cli, build-vscode, build-mac] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: pnpm/action-setup@v6 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '22' | |
| cache: 'pnpm' | |
| - run: pnpm install --frozen-lockfile | |
| - name: Download Mac DMG | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: mac-release | |
| path: release-artifacts/ | |
| - name: Download VS Code extension | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: vscode-release | |
| path: release-artifacts/ | |
| - name: Generate release notes | |
| id: notes | |
| run: | | |
| PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "") | |
| if [ -n "$PREV_TAG" ]; then | |
| FROM="$PREV_TAG" | |
| else | |
| FROM=$(git rev-list --max-parents=0 HEAD) | |
| fi | |
| npx tsx scripts/gen-release-notes.ts "$FROM" HEAD > release-notes.md | |
| cat release-notes.md | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v3 | |
| with: | |
| name: v${{ needs.validate.outputs.version }} | |
| body_path: release-notes.md | |
| prerelease: ${{ needs.validate.outputs.channel != 'stable' }} | |
| generate_release_notes: false | |
| files: | | |
| release-artifacts/*.dmg | |
| release-artifacts/*.vsix |