[RSI, security] Refuse force-pushes to protected branches in kernel bash #2251
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 Prime Agent | |
| on: | |
| pull_request: | |
| branches: [main] | |
| push: | |
| branches: | |
| - main | |
| tags: | |
| - 'v*' | |
| workflow_dispatch: | |
| inputs: | |
| release_tag: | |
| description: 'Production release tag to create or update (e.g., v0.0.1)' | |
| required: true | |
| type: string | |
| concurrency: | |
| group: ${{ github.event_name == 'pull_request' && format('release-validation-pr-{0}', github.event.pull_request.number) || 'release-prime-agent' }} | |
| cancel-in-progress: false | |
| queue: max | |
| permissions: | |
| contents: read | |
| jobs: | |
| trust: | |
| name: Contributor trust | |
| runs-on: ubuntu-latest | |
| outputs: | |
| allowed: ${{ github.event_name != 'pull_request' || steps.vouch.outputs.vouched == 'true' }} | |
| steps: | |
| - name: Check pull request author | |
| id: vouch | |
| if: github.event_name == 'pull_request' | |
| uses: mitchellh/vouch/action/check-user@d66fa29a64600490892131ad87597c30c91fcac4 # v1 | |
| with: | |
| user: ${{ github.event.pull_request.user.login }} | |
| allow-fail: true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| release-context: | |
| needs: trust | |
| if: needs.trust.outputs.allowed == 'true' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| beta_version: ${{ steps.context.outputs.beta_version }} | |
| build_ref: ${{ steps.context.outputs.build_ref }} | |
| production_version: ${{ steps.context.outputs.production_version }} | |
| publish_beta: ${{ steps.context.outputs.publish_beta }} | |
| publish_production: ${{ steps.context.outputs.publish_production }} | |
| stale: ${{ steps.staleness.outputs.stale }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| persist-credentials: false | |
| - name: Resolve release context | |
| id: context | |
| env: | |
| BEFORE_SHA: ${{ github.event.before || '' }} | |
| DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| GITHUB_SHA_VALUE: ${{ github.sha }} | |
| INPUT_RELEASE_TAG: ${{ github.event.inputs.release_tag || '' }} | |
| REF_NAME: ${{ github.ref_name }} | |
| REF_TYPE: ${{ github.ref_type }} | |
| RUN_ATTEMPT: ${{ github.run_attempt }} | |
| RUN_NUMBER: ${{ github.run_number }} | |
| run: | | |
| beta_version= | |
| build_ref= | |
| production_version= | |
| publish_beta=false | |
| publish_production=false | |
| if [ "$EVENT_NAME" = pull_request ]; then | |
| # Exercise both real packer paths without release credentials or publication. | |
| production_version=$(node -p "require('./package.json').version") | |
| build_ref="$GITHUB_SHA_VALUE" | |
| beta_version="${production_version}-beta.${RUN_NUMBER}.${RUN_ATTEMPT}.${GITHUB_SHA_VALUE::7}" | |
| publish_beta=true | |
| publish_production=true | |
| elif [ "$EVENT_NAME" = workflow_dispatch ]; then | |
| if [ "$REF_NAME" != "$DEFAULT_BRANCH" ]; then | |
| echo "Manual releases must run from the default branch (${DEFAULT_BRANCH}), not ${REF_NAME}." >&2 | |
| exit 1 | |
| fi | |
| production_version="${INPUT_RELEASE_TAG#v}" | |
| build_ref="$GITHUB_SHA_VALUE" | |
| publish_production=true | |
| elif [ "$REF_TYPE" = tag ]; then | |
| production_version="${REF_NAME#v}" | |
| build_ref="$REF_NAME" | |
| publish_production=true | |
| else | |
| production_version=$(node -p "require('./package.json').version") | |
| build_ref="$GITHUB_SHA_VALUE" | |
| beta_version="${production_version}-beta.${RUN_NUMBER}.${RUN_ATTEMPT}.${GITHUB_SHA_VALUE::7}" | |
| publish_beta=true | |
| previous_version= | |
| if [ -n "$BEFORE_SHA" ] && ! printf '%s\n' "$BEFORE_SHA" | grep -Eq '^0+$' && git cat-file -e "${BEFORE_SHA}:package.json"; then | |
| git show "${BEFORE_SHA}:package.json" > /tmp/previous-package.json | |
| previous_version=$(node -p "require('/tmp/previous-package.json').version") | |
| fi | |
| if [ -z "$previous_version" ] || [ "$production_version" != "$previous_version" ]; then | |
| if git show-ref --verify --quiet "refs/tags/v${production_version}"; then | |
| tagged_commit=$(git rev-list -n 1 "v${production_version}") | |
| if [ "$tagged_commit" != "$GITHUB_SHA_VALUE" ]; then | |
| echo "Production v${production_version} already points to ${tagged_commit}, not ${GITHUB_SHA_VALUE}." >&2 | |
| exit 1 | |
| fi | |
| echo "Retrying production v${production_version} for ${GITHUB_SHA_VALUE}." | |
| fi | |
| publish_production=true | |
| elif ! git show-ref --verify --quiet "refs/tags/v${production_version}"; then | |
| echo "Production v${production_version} has no tag; retrying the failed release." | |
| publish_production=true | |
| else | |
| echo "Package version is unchanged at ${production_version}; only beta will advance." | |
| fi | |
| fi | |
| if [ "$publish_production" = true ] && ! printf '%s\n' "$production_version" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then | |
| echo "Production version must be plain semver like 0.0.1: ${production_version}" >&2 | |
| exit 1 | |
| fi | |
| echo "beta_version=$beta_version" >> "$GITHUB_OUTPUT" | |
| echo "build_ref=$build_ref" >> "$GITHUB_OUTPUT" | |
| echo "production_version=$production_version" >> "$GITHUB_OUTPUT" | |
| echo "publish_beta=$publish_beta" >> "$GITHUB_OUTPUT" | |
| echo "publish_production=$publish_production" >> "$GITHUB_OUTPUT" | |
| echo "Build ref: $build_ref" | |
| echo "Production: $publish_production ${production_version:+v${production_version}}" | |
| echo "Beta: $publish_beta ${beta_version:+v${beta_version}}" | |
| - name: Skip superseded push builds | |
| id: staleness | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PUBLISH_PRODUCTION: ${{ steps.context.outputs.publish_production }} | |
| run: | | |
| if [ "${GITHUB_EVENT_NAME}" != "push" ] || [ "${GITHUB_REF_TYPE}" = "tag" ]; then | |
| echo "Event is ${GITHUB_EVENT_NAME} on ${GITHUB_REF_TYPE} ${GITHUB_REF_NAME}; building as usual." | |
| echo "stale=false" >> "${GITHUB_OUTPUT}" | |
| exit 0 | |
| fi | |
| if [ "${PUBLISH_PRODUCTION}" = "true" ]; then | |
| echo "This run can publish production; building even though a newer commit may exist." | |
| echo "stale=false" >> "${GITHUB_OUTPUT}" | |
| exit 0 | |
| fi | |
| # Fail open: a tip-check hiccup must never skip a real release build. | |
| latest_sha="$(gh api "repos/${GITHUB_REPOSITORY}/commits/${GITHUB_REF_NAME}" --jq .sha 2>/dev/null || echo "${GITHUB_SHA}")" | |
| if [ "${latest_sha}" = "${GITHUB_SHA}" ]; then | |
| echo "This commit is the tip of ${GITHUB_REF_NAME}; building." | |
| echo "stale=false" >> "${GITHUB_OUTPUT}" | |
| else | |
| echo "${GITHUB_SHA} is superseded by ${latest_sha} on ${GITHUB_REF_NAME}; skipping the superseded beta build." | |
| echo "stale=true" >> "${GITHUB_OUTPUT}" | |
| fi | |
| standalone: | |
| needs: release-context | |
| if: needs.release-context.result == 'success' && needs.release-context.outputs.stale != 'true' | |
| uses: ./.github/workflows/standalone-binaries.yml | |
| with: | |
| build_ref: ${{ needs.release-context.outputs.build_ref }} | |
| secrets: inherit | |
| build: | |
| runs-on: ubuntu-latest | |
| needs: [release-context, standalone] | |
| if: needs.release-context.result == 'success' && needs.release-context.outputs.stale != 'true' | |
| permissions: | |
| contents: read | |
| env: | |
| BETA_VERSION: ${{ needs.release-context.outputs.beta_version }} | |
| BUILD_REF: ${{ needs.release-context.outputs.build_ref }} | |
| PRODUCTION_VERSION: ${{ needs.release-context.outputs.production_version }} | |
| PUBLISH_BETA: ${{ needs.release-context.outputs.publish_beta }} | |
| PUBLISH_PRODUCTION: ${{ needs.release-context.outputs.publish_production }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| ref: ${{ env.BUILD_REF }} | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: '22' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Checkout catalog assets | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| repository: PrimeIntellect-ai/prime-agent-catalog | |
| ref: main | |
| token: ${{ secrets.PRIME_CATALOG_REPO_TOKEN || github.token }} | |
| path: prime-agent-catalog | |
| persist-credentials: false | |
| - name: Generate catalog assets | |
| run: npm run catalog:assets -- --catalog-dir prime-agent-catalog | |
| - name: Build | |
| run: npm run build | |
| - name: Check | |
| run: npm run check | |
| - name: Download tested standalone archives | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| pattern: standalone-* | |
| path: standalone-artifacts | |
| - name: Verify and stage standalone binaries | |
| run: | | |
| for platform in $(node scripts/release-platforms.mjs); do | |
| source_dir="standalone-artifacts/standalone-$platform" | |
| (cd "$source_dir" && sha256sum --check SHA256SUMS) | |
| destination="packages/coding-agent/binaries/$platform" | |
| mkdir -p "$destination" | |
| tar -xzf "$source_dir"/*.tar.gz -C "$destination" | |
| done | |
| - name: Pack production release | |
| if: env.PUBLISH_PRODUCTION == 'true' | |
| env: | |
| PRIME_AGENT_DOWNLOAD_BASE_URL: ${{ github.event_name == 'pull_request' && 'https://example.invalid/prime-agent-validation' || vars.R2_PUBLIC_BASE_URL }} | |
| run: | | |
| test -n "$PRIME_AGENT_DOWNLOAD_BASE_URL" | |
| npm run release:pack -- \ | |
| --channel stable \ | |
| --version "$PRODUCTION_VERSION" \ | |
| --base-url "$PRIME_AGENT_DOWNLOAD_BASE_URL" \ | |
| --binary-dir packages/coding-agent/binaries \ | |
| --out-dir packages/coding-agent/release/production | |
| - name: Pack beta release | |
| if: env.PUBLISH_BETA == 'true' | |
| env: | |
| PRIME_AGENT_DOWNLOAD_BASE_URL: ${{ github.event_name == 'pull_request' && 'https://example.invalid/prime-agent-validation' || vars.R2_PUBLIC_BASE_URL }} | |
| run: | | |
| test -n "$PRIME_AGENT_DOWNLOAD_BASE_URL" | |
| npm run release:pack -- \ | |
| --channel beta \ | |
| --version "$BETA_VERSION" \ | |
| --base-url "$PRIME_AGENT_DOWNLOAD_BASE_URL" \ | |
| --binary-dir packages/coding-agent/binaries \ | |
| --out-dir packages/coding-agent/release/beta | |
| - name: Smoke test installer with npm 12 | |
| run: | | |
| npm install --global npm@12.0.2 | |
| npm --version | grep -Eq '^12\.' | |
| SMOKE_VERSION=0.0.0-installer-smoke | |
| SMOKE_BASE_URL=http://127.0.0.1:18188 | |
| SMOKE_OUT=packages/coding-agent/release/npm12-smoke | |
| SMOKE_ROOT=$(mktemp -d) | |
| npm run release:pack -- \ | |
| --channel stable \ | |
| --version "$SMOKE_VERSION" \ | |
| --base-url "$SMOKE_BASE_URL" \ | |
| --out-dir "$SMOKE_OUT" | |
| mkdir -p "$SMOKE_ROOT/releases/v$SMOKE_VERSION" | |
| cp "$SMOKE_OUT/artifacts/"* "$SMOKE_ROOT/releases/v$SMOKE_VERSION/" | |
| sed \ | |
| -e "s|__PRIME_AGENT_DOWNLOAD_BASE_URL__|$SMOKE_BASE_URL|g" \ | |
| -e 's|__PRIME_AGENT_DEFAULT_RELEASE_CHANNEL__|stable|g' \ | |
| install.sh > /tmp/prime-agent-npm12-install.sh | |
| python3 -m http.server 18188 --bind 127.0.0.1 --directory "$SMOKE_ROOT" >/tmp/prime-agent-npm12-http.log 2>&1 & | |
| server_pid=$! | |
| trap 'kill "$server_pid" 2>/dev/null || true; rm -rf "$SMOKE_ROOT" "$SMOKE_OUT"' EXIT | |
| curl -fsS --retry 5 --retry-connrefused "$SMOKE_BASE_URL/releases/v$SMOKE_VERSION/SHA256SUMS" | |
| export NPM_CONFIG_PREFIX="$SMOKE_ROOT/npm-prefix" | |
| PATH="$NPM_CONFIG_PREFIX/bin:$PATH" \ | |
| PRIME_AGENT_ALLOW_INSECURE_HTTP_FOR_TESTS=1 \ | |
| PRIME_AGENT_BOOTSTRAP_KERNEL_ON_INSTALL=0 \ | |
| PRIME_AGENT_INSTALL_METHOD=node \ | |
| PRIME_AGENT_INSTALLER_PLAIN=1 \ | |
| sh /tmp/prime-agent-npm12-install.sh "$SMOKE_VERSION" | |
| test -x "$NPM_CONFIG_PREFIX/bin/prime-agent" | |
| - name: Upload production artifacts | |
| if: env.PUBLISH_PRODUCTION == 'true' | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: prime-agent-production | |
| path: packages/coding-agent/release/production/artifacts/* | |
| if-no-files-found: error | |
| - name: Upload beta artifacts | |
| if: env.PUBLISH_BETA == 'true' | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: prime-agent-beta | |
| path: packages/coding-agent/release/beta/artifacts/* | |
| if-no-files-found: error | |
| validate-macos: | |
| name: Final release (${{ matrix.platform }}) | |
| needs: [release-context, build] | |
| if: needs.release-context.result == 'success' && needs.release-context.outputs.stale != 'true' | |
| runs-on: ${{ matrix.runner }} | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: darwin-arm64 | |
| runner: macos-15 | |
| - platform: darwin-x64 | |
| runner: macos-15-intel | |
| env: | |
| BUILD_REF: ${{ needs.release-context.outputs.build_ref }} | |
| PUBLISH_PRODUCTION: ${{ needs.release-context.outputs.publish_production }} | |
| PUBLISH_BETA: ${{ needs.release-context.outputs.publish_beta }} | |
| steps: | |
| - name: Checkout validation source | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| ref: ${{ env.BUILD_REF }} | |
| persist-credentials: false | |
| path: source | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: '22' | |
| package-manager-cache: false | |
| - uses: astral-sh/setup-uv@94527f2e458b27549849d47d273a16bec83a01e9 # v7 | |
| with: | |
| version: '0.11.7' | |
| enable-cache: false | |
| - name: Install validation dependencies | |
| working-directory: source | |
| run: npm ci | |
| - name: Download exact final production artifacts | |
| if: env.PUBLISH_PRODUCTION == 'true' | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| name: prime-agent-production | |
| path: ${{ runner.temp }}/final-artifacts/prime-agent-production | |
| - name: Download exact final beta artifacts | |
| if: env.PUBLISH_BETA == 'true' | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| name: prime-agent-beta | |
| path: ${{ runner.temp }}/final-artifacts/prime-agent-beta | |
| - name: Download tested executable identity | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| name: standalone-${{ matrix.platform }} | |
| path: ${{ runner.temp }}/standalone-reference | |
| - name: Remove the build paths from the test machine | |
| run: mv "$GITHUB_WORKSPACE/source" "$RUNNER_TEMP/validation-source" | |
| - name: Verify and exercise exact final Mac archives | |
| working-directory: ${{ runner.temp }}/validation-source | |
| env: | |
| TARGET_PLATFORM: ${{ matrix.platform }} | |
| run: | | |
| export PRIME_AGENT_TEST_UV=$(command -v uv) | |
| for channel in production beta; do | |
| if [ "$channel" = production ] && [ "$PUBLISH_PRODUCTION" != true ]; then continue; fi | |
| if [ "$channel" = beta ] && [ "$PUBLISH_BETA" != true ]; then continue; fi | |
| artifacts="$RUNNER_TEMP/final-artifacts/prime-agent-$channel" | |
| node scripts/validate-macos-release.mjs "$artifacts" "$TARGET_PLATFORM" \ | |
| "$RUNNER_TEMP/standalone-reference/binaries.json" \ | |
| "$RUNNER_TEMP/macos-validation/$channel-$TARGET_PLATFORM.json" | |
| export PRIME_AGENT_TEST_ARCHIVE=$(find "$artifacts" -maxdepth 1 -name "*-$TARGET_PLATFORM.tar.gz") | |
| test -n "$PRIME_AGENT_TEST_ARCHIVE" | |
| (cd packages/coding-agent && npx tsx ../../node_modules/vitest/dist/cli.js --run test/compiled-artifact.test.ts test/native-installer.test.ts) | |
| done | |
| - name: Upload native validation receipts | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: macos-validation-${{ matrix.platform }} | |
| path: ${{ runner.temp }}/macos-validation/*.json | |
| if-no-files-found: error | |
| publish: | |
| if: github.event_name != 'pull_request' && needs.release-context.result == 'success' && needs.release-context.outputs.stale != 'true' | |
| runs-on: ubuntu-latest | |
| needs: [release-context, build, validate-macos] | |
| permissions: | |
| contents: write | |
| env: | |
| AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} | |
| AWS_DEFAULT_REGION: auto | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} | |
| BETA_VERSION: ${{ needs.release-context.outputs.beta_version }} | |
| BUILD_REF: ${{ needs.release-context.outputs.build_ref }} | |
| PRODUCTION_VERSION: ${{ needs.release-context.outputs.production_version }} | |
| PUBLISH_BETA: ${{ needs.release-context.outputs.publish_beta }} | |
| PUBLISH_PRODUCTION: ${{ needs.release-context.outputs.publish_production }} | |
| R2_BUCKET: ${{ secrets.R2_BUCKET }} | |
| R2_ENDPOINT_URL: ${{ secrets.R2_ENDPOINT_URL }} | |
| R2_PUBLIC_BASE_URL: ${{ vars.R2_PUBLIC_BASE_URL }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| ref: ${{ env.BUILD_REF }} | |
| persist-credentials: false | |
| - name: Download production artifacts | |
| if: env.PUBLISH_PRODUCTION == 'true' | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| name: prime-agent-production | |
| path: release-artifacts/production | |
| - name: Download beta artifacts | |
| if: env.PUBLISH_BETA == 'true' | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| name: prime-agent-beta | |
| path: release-artifacts/beta | |
| - name: Download native validation receipts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| pattern: macos-validation-* | |
| path: macos-validation | |
| merge-multiple: true | |
| - name: Match native validation to publication artifacts | |
| run: | | |
| if [ "$PUBLISH_PRODUCTION" = true ]; then | |
| node scripts/verify-macos-validation-receipts.mjs release-artifacts/production macos-validation production | |
| fi | |
| if [ "$PUBLISH_BETA" = true ]; then | |
| node scripts/verify-macos-validation-receipts.mjs release-artifacts/beta macos-validation beta | |
| fi | |
| - name: Prepare installer | |
| run: | | |
| INSTALL_BASE_URL="${R2_PUBLIC_BASE_URL%/}" | |
| export INSTALL_BASE_URL | |
| test -n "$INSTALL_BASE_URL" | |
| node - <<'NODE' | |
| const fs = require("node:fs"); | |
| const baseUrl = process.env.INSTALL_BASE_URL; | |
| if (!baseUrl) throw new Error("INSTALL_BASE_URL is required"); | |
| const installer = fs.readFileSync("install.sh", "utf8"); | |
| const renderInstaller = (channel) => installer | |
| .replaceAll("__PRIME_AGENT_DOWNLOAD_BASE_URL__", baseUrl) | |
| .replaceAll("__PRIME_AGENT_DEFAULT_RELEASE_CHANNEL__", channel); | |
| fs.writeFileSync("/tmp/prime-agent-install.sh", renderInstaller("stable")); | |
| fs.writeFileSync("/tmp/prime-agent-install-beta.sh", renderInstaller("beta")); | |
| NODE | |
| - name: Extract production release notes | |
| if: env.PUBLISH_PRODUCTION == 'true' | |
| run: | | |
| awk "/^## \[${PRODUCTION_VERSION}\]/{flag=1; next} /^## \[/{flag=0} flag" packages/coding-agent/CHANGELOG.md > /tmp/release-notes.md | |
| if [ ! -s /tmp/release-notes.md ]; then | |
| echo "Release v${PRODUCTION_VERSION}" > /tmp/release-notes.md | |
| fi | |
| - name: Publish production channel to R2 | |
| if: env.PUBLISH_PRODUCTION == 'true' | |
| run: | | |
| PRODUCTION_DIR=release-artifacts/production | |
| RELEASE_PREFIX="releases/v${PRODUCTION_VERSION}" | |
| TARBALL="$PRODUCTION_DIR/prime-agent-${PRODUCTION_VERSION}.tgz" | |
| test -f "$TARBALL" | |
| test -f "$PRODUCTION_DIR/SHA256SUMS" | |
| test -f "$PRODUCTION_DIR/stable" | |
| test -f "$PRODUCTION_DIR/latest.json" | |
| test -n "$R2_BUCKET" | |
| test -n "$R2_ENDPOINT_URL" | |
| (cd "$PRODUCTION_DIR" && sha256sum --check SHA256SUMS) | |
| for artifact in "$PRODUCTION_DIR"/*.tgz "$PRODUCTION_DIR"/*.tar.gz; do | |
| aws s3 cp "$artifact" "s3://${R2_BUCKET}/${RELEASE_PREFIX}/$(basename "$artifact")" \ | |
| --endpoint-url "$R2_ENDPOINT_URL" \ | |
| --content-type application/gzip \ | |
| --cache-control 'public, max-age=31536000, immutable' | |
| done | |
| aws s3 cp "$PRODUCTION_DIR/SHA256SUMS" "s3://${R2_BUCKET}/${RELEASE_PREFIX}/SHA256SUMS" \ | |
| --endpoint-url "$R2_ENDPOINT_URL" \ | |
| --content-type text/plain \ | |
| --cache-control 'public, max-age=31536000, immutable' | |
| aws s3 cp "$PRODUCTION_DIR/latest.json" "s3://${R2_BUCKET}/latest.json" \ | |
| --endpoint-url "$R2_ENDPOINT_URL" \ | |
| --content-type application/json \ | |
| --cache-control no-cache | |
| aws s3 cp "$PRODUCTION_DIR/stable" "s3://${R2_BUCKET}/stable" \ | |
| --endpoint-url "$R2_ENDPOINT_URL" \ | |
| --content-type text/plain \ | |
| --cache-control no-cache | |
| aws s3 cp /tmp/prime-agent-install.sh "s3://${R2_BUCKET}/install.sh" \ | |
| --endpoint-url "$R2_ENDPOINT_URL" \ | |
| --content-type text/x-shellscript \ | |
| --cache-control no-cache | |
| aws s3 cp /tmp/prime-agent-install-beta.sh "s3://${R2_BUCKET}/install-beta.sh" \ | |
| --endpoint-url "$R2_ENDPOINT_URL" \ | |
| --content-type text/x-shellscript \ | |
| --cache-control no-cache | |
| - name: Create production GitHub release | |
| if: env.PUBLISH_PRODUCTION == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| RELEASE_TAG="v${PRODUCTION_VERSION}" | |
| PRODUCTION_DIR=release-artifacts/production | |
| target_args=() | |
| if [ "$BUILD_REF" != "$RELEASE_TAG" ]; then | |
| target_args=(--target "$BUILD_REF") | |
| fi | |
| if gh release view "$RELEASE_TAG" >/dev/null 2>&1; then | |
| gh release upload "$RELEASE_TAG" "$PRODUCTION_DIR"/* --clobber | |
| else | |
| gh release create "$RELEASE_TAG" \ | |
| --title "$RELEASE_TAG" \ | |
| "${target_args[@]}" \ | |
| --notes-file /tmp/release-notes.md \ | |
| "$PRODUCTION_DIR"/* | |
| fi | |
| - name: Publish immutable beta artifacts to R2 | |
| if: env.PUBLISH_BETA == 'true' | |
| run: | | |
| BETA_DIR=release-artifacts/beta | |
| RELEASE_PREFIX="releases/v${BETA_VERSION}" | |
| TARBALL="$BETA_DIR/prime-agent-${BETA_VERSION}.tgz" | |
| test -f "$TARBALL" | |
| test -f "$BETA_DIR/SHA256SUMS" | |
| test -f "$BETA_DIR/beta" | |
| test -f "$BETA_DIR/beta.json" | |
| test -n "$R2_BUCKET" | |
| test -n "$R2_ENDPOINT_URL" | |
| (cd "$BETA_DIR" && sha256sum --check SHA256SUMS) | |
| for artifact in "$BETA_DIR"/*.tgz "$BETA_DIR"/*.tar.gz; do | |
| aws s3 cp "$artifact" "s3://${R2_BUCKET}/${RELEASE_PREFIX}/$(basename "$artifact")" \ | |
| --endpoint-url "$R2_ENDPOINT_URL" \ | |
| --content-type application/gzip \ | |
| --cache-control 'public, max-age=31536000, immutable' | |
| done | |
| aws s3 cp "$BETA_DIR/SHA256SUMS" "s3://${R2_BUCKET}/${RELEASE_PREFIX}/SHA256SUMS" \ | |
| --endpoint-url "$R2_ENDPOINT_URL" \ | |
| --content-type text/plain \ | |
| --cache-control 'public, max-age=31536000, immutable' | |
| - name: Advance beta release | |
| if: env.PUBLISH_BETA == 'true' | |
| env: | |
| DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| latest_main_sha=$(gh api "repos/${GITHUB_REPOSITORY}/commits/${DEFAULT_BRANCH}" --jq .sha) | |
| if [ "$latest_main_sha" != "$BUILD_REF" ]; then | |
| echo "A newer main commit exists; keeping its beta pointers in place." | |
| exit 0 | |
| fi | |
| BETA_DIR=release-artifacts/beta | |
| aws s3 cp "$BETA_DIR/beta.json" "s3://${R2_BUCKET}/beta.json" \ | |
| --endpoint-url "$R2_ENDPOINT_URL" \ | |
| --content-type application/json \ | |
| --cache-control no-cache | |
| aws s3 cp "$BETA_DIR/beta" "s3://${R2_BUCKET}/beta" \ | |
| --endpoint-url "$R2_ENDPOINT_URL" \ | |
| --content-type text/plain \ | |
| --cache-control no-cache | |
| aws s3 cp /tmp/prime-agent-install.sh "s3://${R2_BUCKET}/install.sh" \ | |
| --endpoint-url "$R2_ENDPOINT_URL" \ | |
| --content-type text/x-shellscript \ | |
| --cache-control no-cache | |
| aws s3 cp /tmp/prime-agent-install-beta.sh "s3://${R2_BUCKET}/install-beta.sh" \ | |
| --endpoint-url "$R2_ENDPOINT_URL" \ | |
| --content-type text/x-shellscript \ | |
| --cache-control no-cache | |
| printf 'Automated beta build from `%s` (`%s`).\n' "$DEFAULT_BRANCH" "$BUILD_REF" > /tmp/beta-release-notes.md | |
| if gh api "repos/${GITHUB_REPOSITORY}/git/ref/tags/beta" >/dev/null 2>&1; then | |
| gh api --method PATCH "repos/${GITHUB_REPOSITORY}/git/refs/tags/beta" \ | |
| -F sha="$BUILD_REF" \ | |
| -F force=true >/dev/null | |
| else | |
| gh api --method POST "repos/${GITHUB_REPOSITORY}/git/refs" \ | |
| -f ref=refs/tags/beta \ | |
| -f sha="$BUILD_REF" >/dev/null | |
| fi | |
| if release_id=$(gh api "repos/${GITHUB_REPOSITORY}/releases/tags/beta" --jq .id 2>/dev/null); then | |
| gh api "repos/${GITHUB_REPOSITORY}/releases/${release_id}/assets" --jq '.[].id' | while read -r asset_id; do | |
| gh api --method DELETE "repos/${GITHUB_REPOSITORY}/releases/assets/${asset_id}" | |
| done | |
| gh release edit beta \ | |
| --title "Beta (v${BETA_VERSION})" \ | |
| --target "$BUILD_REF" \ | |
| --notes-file /tmp/beta-release-notes.md \ | |
| --prerelease | |
| else | |
| gh release create beta \ | |
| --title "Beta (v${BETA_VERSION})" \ | |
| --target "$BUILD_REF" \ | |
| --notes-file /tmp/beta-release-notes.md \ | |
| --prerelease | |
| fi | |
| gh release upload beta "$BETA_DIR"/* --clobber | |
| echo "Beta installer: ${R2_PUBLIC_BASE_URL%/}/install-beta.sh" |