diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c94380b..c8570b4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,23 +1,68 @@ name: Release and PyPI Publish +# WHY THIS IS DISPATCH-ONLY AND USES ADMIN_TOKEN +# ---------------------------------------------- +# This workflow ran on every push to main with the default GITHUB_TOKEN. Since +# branch protection was enabled on main (some time after the last successful +# release on 2026-01-29; the first rejection is the run of 2026-02-18), it could +# not succeed. python-semantic-release computes the next version, commits the +# bump, tags it, and pushes to main -- and main now requires a pull request: +# +# remote: error: GH006: Protected branch update failed for refs/heads/main. +# remote: - Changes must be made through a pull request. +# ##[error] Failed to push branch (main) to remote +# +# The push is the step *before* build and publish, so nothing was ever +# published from a failing run. PyPI, the git tag, the GitHub Release, and +# pyproject.toml all still agree; the release simply stopped moving. +# openadapt-privacy hit the identical failure on the same day and was repaired +# on 2026-07-15 by adding ADMIN_TOKEN; this applies the same repair here. +# +# Two changes: +# +# 1. secrets.ADMIN_TOKEN -- the organization-scoped release credential +# (visibility "all") already used by openadapt-flow and openadapt-privacy. +# Branch protection here sets enforce_admins=false, so an admin credential +# can push the generated version commit and tag; GITHUB_TOKEN cannot. +# +# 2. workflow_dispatch instead of push -- releasing becomes an explicit act +# rather than a side effect of merging a README edit. This matches the +# canonical openadapt-flow release workflow and keeps release minutes off +# every push (AGENTS.md 5.1, build-speed and hosted-CI cost discipline). +# It also matters here specifically: the commits accumulated since v0.2.0 +# are CI config, .gitignore, and docs only -- no library code has changed, +# so an automatic release would publish a version whose sole content is a +# version bump. +# +# To cut a release: +# +# gh workflow run "Release and PyPI Publish" \ +# --repo OpenAdaptAI/openadapt-viewer --ref main +# +# python-semantic-release then coalesces the Conventional Commits since the last +# tag, picks the next version, tags it, and publishes to PyPI and GitHub +# Releases. Prerequisites are repository/organization settings, not code: +# secrets.ADMIN_TOKEN with visibility "all", and PyPI Trusted Publishing for +# this package. + on: - push: - branches: - - main + workflow_dispatch: jobs: release: + if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest concurrency: release permissions: - id-token: write - contents: write + id-token: write # PyPI Trusted Publishing (OIDC) + contents: write # push the version bump commit + tag, create the Release steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 + token: ${{ secrets.ADMIN_TOKEN }} - name: Set up Python uses: actions/setup-python@v5 @@ -31,7 +76,7 @@ jobs: id: release uses: python-semantic-release/python-semantic-release@v9.15.2 with: - github_token: ${{ secrets.GITHUB_TOKEN }} + github_token: ${{ secrets.ADMIN_TOKEN }} - name: Build package if: steps.release.outputs.released == 'true' @@ -45,4 +90,4 @@ jobs: if: steps.release.outputs.released == 'true' uses: python-semantic-release/publish-action@v9.15.2 with: - github_token: ${{ secrets.GITHUB_TOKEN }} + github_token: ${{ secrets.ADMIN_TOKEN }} diff --git a/README.md b/README.md index fe459f3..e92ae46 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # openadapt-viewer -[![Build Status](https://github.com/OpenAdaptAI/openadapt-viewer/actions/workflows/publish.yml/badge.svg)](https://github.com/OpenAdaptAI/openadapt-viewer/actions/workflows/publish.yml) +[![Release](https://github.com/OpenAdaptAI/openadapt-viewer/actions/workflows/release.yml/badge.svg)](https://github.com/OpenAdaptAI/openadapt-viewer/actions/workflows/release.yml) [![PyPI version](https://img.shields.io/pypi/v/openadapt-viewer.svg)](https://pypi.org/project/openadapt-viewer/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/downloads/)