From 171ea67527354658429309fb2509717242321738 Mon Sep 17 00:00:00 2001 From: abrichr Date: Mon, 27 Jul 2026 22:56:10 -0400 Subject: [PATCH] ci: release on push to main, matching openadapt-privacy The GH006 repair (ADMIN_TOKEN) is kept. The trigger goes back to push. Dispatch-only was adopted on the reasoning that merging would publish a release whose only content was a CI-config change. That is a commit-message choice, not a property of the trigger: this package's [tool.semantic_release.commit_parser_options] sets minor_tags = ["feat"] and patch_tags = ["fix", "perf"], so ci/chore/docs/build/refactor/style/test commits publish nothing and the run exits green reporting no release. openadapt-privacy is the control: four chore/docs commits since v1.0.0, four green push-triggered release runs, PyPI still 1.0.0. Dispatch-only also leaves this repository's release badge stuck on its last failure and makes it behave unlike its siblings, which is the drift that hid the five-month GH006 failure in the first place. This commit is deliberately typed `ci:` so it cannot itself cause a release. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01NyCHrzA1psrKMFfroYbzaM --- .github/workflows/release.yml | 81 +++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8558712..8dfbd6c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,56 +1,63 @@ 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: +# Push-triggered, with ADMIN_TOKEN. This is the same shape as the sibling +# release workflow in openadapt-privacy, which hit the identical failure on the +# same day and was repaired on 2026-07-15. +# +# WHAT BROKE +# ---------- +# This workflow ran on every push to main with the default GITHUB_TOKEN. 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. +# python-semantic-release computes the next version, commits the bump, tags it, +# and pushes to main -- and main 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. +# That push is the step *before* build and publish, and every later step is +# gated on `released == 'true'`, so a failing run published nothing. PyPI, the +# git tag, the GitHub Release, and pyproject.toml all still agree; the release +# lane simply stopped moving, for five months, while the README's release badge +# showed "failing" the whole time. # -# 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.1.2 -# 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. +# THE FIX +# ------- +# secrets.ADMIN_TOKEN is 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. # -# To cut a release: +# WHY `push` AND NOT `workflow_dispatch` +# -------------------------------------- +# An earlier repair made this workflow dispatch-only, on the reasoning that +# merging would publish a release whose only content was a CI-config change. +# Whether a merge releases is not a property of the trigger. Releases here are +# decided by Conventional Commits: `[tool.semantic_release.commit_parser_options]` +# in pyproject.toml sets `minor_tags = ["feat"]` and `patch_tags = ["fix", +# "perf"]`, so a `ci:`, `chore:`, `docs:`, `build:`, `refactor:`, `style:` or +# `test:` commit changes no version and publishes nothing -- the run reports no +# release and exits green. openadapt-privacy demonstrates exactly that: four +# chore/docs commits since v1.0.0, four green push-triggered release runs, and +# PyPI still on 1.0.0. Publishing on merge is a commit-message choice. # -# gh workflow run "Release and PyPI Publish" \ -# --repo OpenAdaptAI/openadapt-grounding --ref main +# openadapt-flow is dispatch-only for a different and specific reason: a +# packaging/licensing incident that requires a human decision before every +# publish. No such gate applies to this library. # -# 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. +# Dispatch-only is not free here. It needs a person to remember to run the +# release by hand, it leaves the release badge stuck on its last failure, and +# it makes this repository behave unlike its siblings. Divergence of that kind +# is why the GH006 failure above went unnoticed for five months. on: - workflow_dispatch: + push: + branches: + - main jobs: release: - if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest concurrency: release permissions: