gate release publish to tags, dry-run on branch #596
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 PostHog Code | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| branches: | |
| # Temporary: full pre-merge dry run of the release pipeline on this branch. | |
| # Builds, signs and verifies every platform but does NOT create or publish a | |
| # GitHub release (all release steps are gated to tags below). Remove this | |
| # entry before merging. | |
| - refactor/electron-vite | |
| workflow_dispatch: | |
| concurrency: | |
| # Per-ref so a branch dry run never serializes behind or cancels a tag release. | |
| group: code-release-${{ github.ref }} | |
| cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/v') }} | |
| jobs: | |
| prepare-release: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Get app token | |
| id: app-token | |
| uses: getsentry/action-github-app-token@d4b5da6c5e37703f8c3b3e43abb5705b46e159cc # v3.0.0 | |
| with: | |
| app_id: ${{ secrets.GH_APP_ARRAY_RELEASER_APP_ID }} | |
| private_key: ${{ secrets.GH_APP_ARRAY_RELEASER_PRIVATE_KEY }} | |
| - name: Extract version from tag | |
| id: version | |
| run: | | |
| TAG_VERSION="${GITHUB_REF#refs/tags/v}" | |
| echo "version=$TAG_VERSION" >> "$GITHUB_OUTPUT" | |
| - name: Create draft release if absent | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | |
| APP_VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| # Pre-create a single draft release so every parallel publish job uploads | |
| # into the same release. Without this, parallel jobs each create-if-missing | |
| # at once, producing multiple releases for one tag and scattering assets | |
| # (the orphans get left as drafts). | |
| if gh release view "v$APP_VERSION" --repo PostHog/code >/dev/null 2>&1; then | |
| echo "Release v$APP_VERSION already exists — reusing it" | |
| else | |
| gh release create "v$APP_VERSION" --repo PostHog/code --draft \ | |
| --title "v$APP_VERSION" --notes "Release v$APP_VERSION (build in progress)" | |
| fi | |
| publish-macos: | |
| needs: [prepare-release] | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - arch: arm64 | |
| runner: macos-15 | |
| - arch: x64 | |
| runner: macos-15-intel | |
| runs-on: ${{ matrix.runner }} | |
| permissions: | |
| id-token: write | |
| contents: write | |
| env: | |
| NODE_OPTIONS: "--max-old-space-size=8192" | |
| NODE_ENV: production | |
| npm_config_arch: ${{ matrix.arch }} | |
| npm_config_platform: darwin | |
| VITE_POSTHOG_API_KEY: ${{ secrets.VITE_POSTHOG_API_KEY }} | |
| VITE_POSTHOG_API_HOST: ${{ secrets.VITE_POSTHOG_API_HOST }} | |
| POSTHOG_SOURCEMAP_API_KEY: ${{ secrets.POSTHOG_SOURCEMAP_API_KEY }} | |
| POSTHOG_ENV_ID: ${{ secrets.POSTHOG_ENV_ID }} | |
| POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }} | |
| CSC_LINK: ${{ secrets.APPLE_CODESIGN_CERT_BASE64 }} | |
| CSC_KEY_PASSWORD: ${{ secrets.APPLE_CODESIGN_CERT_PASSWORD }} | |
| APPLE_ID: ${{ secrets.APPLE_ID }} | |
| APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} | |
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
| steps: | |
| - name: Get app token | |
| id: app-token | |
| uses: getsentry/action-github-app-token@d4b5da6c5e37703f8c3b3e43abb5705b46e159cc # v3.0.0 | |
| with: | |
| app_id: ${{ secrets.GH_APP_ARRAY_RELEASER_APP_ID }} | |
| private_key: ${{ secrets.GH_APP_ARRAY_RELEASER_PRIVATE_KEY }} | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ steps.app-token.outputs.token }} | |
| persist-credentials: false | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 | |
| with: | |
| node-version: 22 | |
| cache: "pnpm" | |
| - name: Resolve version | |
| id: version | |
| run: | | |
| if [[ "$GITHUB_REF" == refs/tags/v* ]]; then | |
| VERSION="${GITHUB_REF#refs/tags/v}" | |
| else | |
| VERSION="$(jq -r .version apps/code/package.json)" | |
| fi | |
| echo "Version: $VERSION" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| - name: Set version in package.json | |
| env: | |
| APP_VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| jq --arg v "$APP_VERSION" '.version = $v' apps/code/package.json > tmp.json && mv tmp.json apps/code/package.json | |
| echo "Set apps/code/package.json version to $APP_VERSION" | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1 | |
| with: | |
| role-to-assume: ${{ secrets.AWS_TWIG_APP_ASSETS_ROLE_ARN }} | |
| aws-region: ${{ secrets.AWS_TWIG_APP_ASSETS_REGION }} | |
| mask-aws-account-id: true | |
| unset-current-credentials: true | |
| - name: Download BerkeleyMono fonts from S3 | |
| run: aws s3 cp s3://${{ secrets.AWS_TWIG_APP_ASSETS_BUCKET }}/fonts/BerkeleyMono/ apps/code/assets/fonts/BerkeleyMono/ --recursive | |
| - name: Build electron-trpc package | |
| run: pnpm --filter @posthog/electron-trpc run build | |
| - name: Build platform package | |
| run: pnpm --filter @posthog/platform run build | |
| - name: Build shared package | |
| run: pnpm --filter @posthog/shared run build | |
| - name: Build git package | |
| run: pnpm --filter @posthog/git run build | |
| - name: Build enricher package | |
| run: pnpm --filter @posthog/enricher run build | |
| - name: Build agent package | |
| run: pnpm --filter @posthog/agent run build | |
| - name: Build release artifacts | |
| env: | |
| APP_VERSION: ${{ steps.version.outputs.version }} | |
| working-directory: apps/code | |
| run: | | |
| pnpm exec electron-vite build | |
| if [[ "${{ matrix.arch }}" == "arm64" ]]; then | |
| pnpm exec electron-builder build --mac --arm64 --publish never --config electron-builder.ts | |
| else | |
| pnpm exec electron-builder build --mac --x64 --publish never --config electron-builder.ts | |
| fi | |
| - name: Verify package | |
| run: | | |
| if [[ "${{ matrix.arch }}" == "arm64" ]]; then | |
| APP_BUNDLE="apps/code/out/mac-arm64/PostHog Code.app" | |
| else | |
| APP_BUNDLE="apps/code/out/mac/PostHog Code.app" | |
| fi | |
| RESOURCES="$APP_BUNDLE/Contents/Resources" | |
| UNPACKED="$RESOURCES/app.asar.unpacked/node_modules" | |
| if [[ ! -f "$RESOURCES/app-update.yml" ]]; then | |
| echo "FAIL: app-update.yml missing at $RESOURCES/app-update.yml" | |
| exit 1 | |
| fi | |
| echo "OK: app-update.yml" | |
| for mod in node-pty better-sqlite3 "@parcel/watcher"; do | |
| if [[ ! -d "$UNPACKED/$mod" ]]; then | |
| echo "FAIL: $mod missing in app.asar.unpacked/node_modules" | |
| exit 1 | |
| fi | |
| echo "OK: $mod" | |
| done | |
| for bin in claude-cli codex-acp; do | |
| if [[ ! -d "$RESOURCES/app.asar.unpacked/.vite/build/$bin" ]]; then | |
| echo "FAIL: $bin missing in bundled binaries" | |
| exit 1 | |
| fi | |
| echo "OK: $bin" | |
| done | |
| - name: Install Playwright | |
| run: pnpm --filter code exec playwright install | |
| - name: Smoke test packaged app | |
| env: | |
| CI: true | |
| E2E_APP_ARCH: ${{ matrix.arch }} | |
| run: pnpm --filter code exec playwright test --config=tests/e2e/playwright.config.ts tests/e2e/tests/smoke.spec.ts | |
| - name: Upload Playwright report | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| if: failure() | |
| with: | |
| name: release-playwright-report-macos-${{ matrix.arch }} | |
| path: apps/code/playwright-report/ | |
| retention-days: 7 | |
| - name: Upload release artifacts | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | |
| APP_VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| gh release upload "v$APP_VERSION" --repo PostHog/code --clobber \ | |
| apps/code/out/*.dmg \ | |
| apps/code/out/*-mac.zip \ | |
| apps/code/out/*.blockmap | |
| - name: Upload build artifacts (dry run) | |
| if: ${{ !startsWith(github.ref, 'refs/tags/v') }} | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: code-macos-${{ matrix.arch }} | |
| path: | | |
| apps/code/out/*.dmg | |
| apps/code/out/*-mac.zip | |
| apps/code/out/*.blockmap | |
| apps/code/out/latest-mac.yml | |
| retention-days: 7 | |
| - name: Upload mac manifest artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: mac-manifest-${{ matrix.arch }} | |
| path: apps/code/out/latest-mac.yml | |
| retention-days: 1 | |
| publish-windows: | |
| needs: [prepare-release] | |
| runs-on: windows-2022 | |
| permissions: | |
| id-token: write | |
| contents: write | |
| env: | |
| NODE_OPTIONS: "--max-old-space-size=8192" | |
| NODE_ENV: production | |
| VITE_POSTHOG_API_KEY: ${{ secrets.VITE_POSTHOG_API_KEY }} | |
| VITE_POSTHOG_API_HOST: ${{ secrets.VITE_POSTHOG_API_HOST }} | |
| steps: | |
| - name: Get app token | |
| id: app-token | |
| uses: getsentry/action-github-app-token@d4b5da6c5e37703f8c3b3e43abb5705b46e159cc # v3.0.0 | |
| with: | |
| app_id: ${{ secrets.GH_APP_ARRAY_RELEASER_APP_ID }} | |
| private_key: ${{ secrets.GH_APP_ARRAY_RELEASER_PRIVATE_KEY }} | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ steps.app-token.outputs.token }} | |
| persist-credentials: false | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 | |
| with: | |
| node-version: 22 | |
| cache: "pnpm" | |
| - name: Resolve version | |
| id: version | |
| shell: pwsh | |
| env: | |
| GITHUB_REF: ${{ github.ref }} | |
| run: | | |
| if ("$env:GITHUB_REF" -like "refs/tags/v*") { | |
| $version = "$env:GITHUB_REF" -replace "refs/tags/v", "" | |
| } else { | |
| $version = (Get-Content apps/code/package.json -Raw | ConvertFrom-Json).version | |
| } | |
| echo "Version: $version" | |
| echo "version=$version" >> $env:GITHUB_OUTPUT | |
| - name: Set version in package.json | |
| shell: pwsh | |
| env: | |
| APP_VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| $pkg = Get-Content apps/code/package.json -Raw | ConvertFrom-Json | |
| $pkg.version = "$env:APP_VERSION" | |
| $pkg | ConvertTo-Json -Depth 10 | Set-Content apps/code/package.json | |
| echo "Set apps/code/package.json version to $env:APP_VERSION" | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Build electron-trpc package | |
| run: pnpm --filter @posthog/electron-trpc run build | |
| - name: Build platform package | |
| run: pnpm --filter @posthog/platform run build | |
| - name: Build shared package | |
| run: pnpm --filter @posthog/shared run build | |
| - name: Build git package | |
| run: pnpm --filter @posthog/git run build | |
| - name: Build enricher package | |
| run: pnpm --filter @posthog/enricher run build | |
| - name: Build agent package | |
| run: pnpm --filter @posthog/agent run build | |
| - name: Build release artifacts | |
| env: | |
| APP_VERSION: ${{ steps.version.outputs.version }} | |
| working-directory: apps/code | |
| run: | | |
| pnpm exec electron-vite build | |
| pnpm exec electron-builder build --win --x64 --publish never --config electron-builder.ts | |
| - name: Upload release artifacts | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| shell: pwsh | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | |
| APP_VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| $out = "apps/code/out" | |
| $sq = Join-Path $out "squirrel-windows" | |
| $items = @() | |
| # NSIS installer + electron-updater metadata live in the output root. | |
| $items += Get-ChildItem $out -File -Filter "*.exe" | |
| $items += Get-ChildItem $out -File -Filter "latest.yml" | |
| $items += Get-ChildItem $out -File -Filter "*.blockmap" | |
| # Squirrel.Windows artifacts (nupkg + RELEASES + Setup) land in out/squirrel-windows. | |
| if (Test-Path $sq) { | |
| $items += Get-ChildItem $sq -File -Filter "*.nupkg" | |
| $items += Get-ChildItem $sq -File -Filter "RELEASES" | |
| $items += Get-ChildItem $sq -File -Filter "*.exe" | |
| } | |
| $files = $items | Select-Object -ExpandProperty FullName | |
| gh release upload "v$env:APP_VERSION" --repo PostHog/code --clobber @files | |
| - name: Upload build artifacts (dry run) | |
| if: ${{ !startsWith(github.ref, 'refs/tags/v') }} | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: code-windows | |
| path: | | |
| apps/code/out/*.exe | |
| apps/code/out/latest.yml | |
| apps/code/out/*.blockmap | |
| apps/code/out/squirrel-windows/** | |
| retention-days: 7 | |
| if-no-files-found: ignore | |
| publish-linux: | |
| needs: [prepare-release] | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - runner: ubuntu-24.04 | |
| arch: x64 | |
| - runner: ubuntu-24.04-arm | |
| arch: arm64 | |
| runs-on: ${{ matrix.runner }} | |
| permissions: | |
| id-token: write | |
| contents: write | |
| env: | |
| NODE_OPTIONS: "--max-old-space-size=8192" | |
| NODE_ENV: production | |
| VITE_POSTHOG_API_KEY: ${{ secrets.VITE_POSTHOG_API_KEY }} | |
| VITE_POSTHOG_API_HOST: ${{ secrets.VITE_POSTHOG_API_HOST }} | |
| steps: | |
| - name: Get app token | |
| id: app-token | |
| uses: getsentry/action-github-app-token@d4b5da6c5e37703f8c3b3e43abb5705b46e159cc # v3 | |
| with: | |
| app_id: ${{ secrets.GH_APP_ARRAY_RELEASER_APP_ID }} | |
| private_key: ${{ secrets.GH_APP_ARRAY_RELEASER_PRIVATE_KEY }} | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ steps.app-token.outputs.token }} | |
| persist-credentials: false | |
| - name: Install Linux packaging tooling | |
| # squashfs-tools/zsync/libfuse2t64: AppImage. fakeroot: maker-deb. | |
| # rpm: maker-rpm (provides rpmbuild). | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| squashfs-tools zsync libfuse2t64 fakeroot rpm | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 22 | |
| cache: "pnpm" | |
| - name: Resolve version | |
| id: version | |
| run: | | |
| if [[ "$GITHUB_REF" == refs/tags/v* ]]; then | |
| VERSION="${GITHUB_REF#refs/tags/v}" | |
| else | |
| VERSION="$(jq -r .version apps/code/package.json)" | |
| fi | |
| echo "Version: $VERSION" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| - name: Set version in package.json | |
| env: | |
| APP_VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| jq --arg v "$APP_VERSION" '.version = $v' apps/code/package.json > tmp.json && mv tmp.json apps/code/package.json | |
| echo "Set apps/code/package.json version to $APP_VERSION" | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Build electron-trpc package | |
| run: pnpm --filter @posthog/electron-trpc run build | |
| - name: Build platform package | |
| run: pnpm --filter @posthog/platform run build | |
| - name: Build shared package | |
| run: pnpm --filter @posthog/shared run build | |
| - name: Build git package | |
| run: pnpm --filter @posthog/git run build | |
| - name: Build enricher package | |
| run: pnpm --filter @posthog/enricher run build | |
| - name: Build agent package | |
| run: pnpm --filter @posthog/agent run build | |
| - name: Build release artifacts | |
| env: | |
| APP_VERSION: ${{ steps.version.outputs.version }} | |
| working-directory: apps/code | |
| run: | | |
| pnpm exec electron-vite build | |
| if [[ "${{ matrix.arch }}" == "arm64" ]]; then | |
| pnpm exec electron-builder build --linux --arm64 --publish never --config electron-builder.ts | |
| else | |
| pnpm exec electron-builder build --linux --x64 --publish never --config electron-builder.ts | |
| fi | |
| - name: Upload release artifacts | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | |
| APP_VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| gh release upload "v$APP_VERSION" --repo PostHog/code --clobber \ | |
| apps/code/out/*.AppImage \ | |
| apps/code/out/*.deb \ | |
| apps/code/out/*.rpm | |
| - name: Upload build artifacts (dry run) | |
| if: ${{ !startsWith(github.ref, 'refs/tags/v') }} | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: code-linux-${{ matrix.arch }} | |
| path: | | |
| apps/code/out/*.AppImage | |
| apps/code/out/*.deb | |
| apps/code/out/*.rpm | |
| retention-days: 7 | |
| finalize-release: | |
| needs: [publish-macos, publish-windows, publish-linux] | |
| # macOS is the primary platform: publish the release as long as macOS built | |
| # successfully, even if Windows or Linux failed. always() is required so this | |
| # job isn't skipped when a non-macOS publish job fails. | |
| if: always() && needs.publish-macos.result == 'success' && startsWith(github.ref, 'refs/tags/v') | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Get app token | |
| id: app-token | |
| uses: getsentry/action-github-app-token@d4b5da6c5e37703f8c3b3e43abb5705b46e159cc # v3.0.0 | |
| with: | |
| app_id: ${{ secrets.GH_APP_ARRAY_RELEASER_APP_ID }} | |
| private_key: ${{ secrets.GH_APP_ARRAY_RELEASER_PRIVATE_KEY }} | |
| - name: Extract version from tag | |
| id: version | |
| run: | | |
| TAG_VERSION="${GITHUB_REF#refs/tags/v}" | |
| echo "version=$TAG_VERSION" >> "$GITHUB_OUTPUT" | |
| - name: Checkout merge script | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| sparse-checkout: | | |
| apps/code/scripts/merge-mac-manifests.mjs | |
| sparse-checkout-cone-mode: false | |
| - name: Setup Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 | |
| with: | |
| node-version: 22 | |
| - name: Install yaml dependency | |
| run: npm install --prefix apps/code yaml | |
| - name: Download arm64 mac manifest | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| name: mac-manifest-arm64 | |
| path: /tmp/mac-manifests/arm64 | |
| - name: Download x64 mac manifest | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| name: mac-manifest-x64 | |
| path: /tmp/mac-manifests/x64 | |
| - name: Merge mac manifests | |
| run: | | |
| node apps/code/scripts/merge-mac-manifests.mjs \ | |
| /tmp/mac-manifests/arm64/latest-mac.yml \ | |
| /tmp/mac-manifests/x64/latest-mac.yml \ | |
| /tmp/latest-mac.yml | |
| - name: Upload merged mac manifest | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | |
| APP_VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| gh release upload "v$APP_VERSION" --repo PostHog/code --clobber /tmp/latest-mac.yml | |
| - name: Publish GitHub release | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | |
| APP_VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| gh api repos/PostHog/code/releases/generate-notes -f tag_name="v$APP_VERSION" --jq '.body' > /tmp/release-notes.md | |
| gh release edit "v$APP_VERSION" --repo PostHog/code --draft=false --notes-file /tmp/release-notes.md |