Skip to content

chore: follow upstream with bump branches instead of next - #133

Open
Gkrumbach07 wants to merge 2 commits into
mainfrom
chore/simplify-upstream-following
Open

Gkrumbach07 wants to merge 2 commits into
mainfrom
chore/simplify-upstream-following

Conversation

@Gkrumbach07

@Gkrumbach07 Gkrumbach07 commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Why

Since the move to ai-openshell, the next setup can't work:

  • No admin. main's ruleset asks for a code owner's approval after the last push and dismisses stale ones. next was force-pushed every hour, so its approval never survived.
  • No bot token. The enterprise refuses fine-grained tokens that live longer than 366 days, so UPSTREAM_BOT_TOKEN is rejected and Follow upstream has failed every hour since the move.
  • Auto-merge and the automatic release after a next merge both depended on the above.

What changes

Follow upstream (.github/workflows/follow-upstream.yml, deploy/ci/upstream/)

  • Runs once a day. When OpenShell has a new stable release, it creates bump/openshell-X.Y.Z from main with one signed-off commit (pins, go.mod/go.sum, release line, README block) and opens a PR into main.
  • It makes a bump branch once: if the branch exists, or any PR has ever come from it, it does nothing. It never rebases, moves or force-pushes one; people push fixes to it like any branch.
  • Manual run with version (for example 0.2.0-pre.1) makes a prep branch for a pre-release. Its PR fails pins a stable release until upstream ships.
  • Check A is unchanged. It runs daily against upstream's newest pre-release and keeps the compat-migrate issue, which now says how to start a prep branch.
  • Pushes and opens the PR with the org's bump-bot GitHub App, the same setup as sdk-go. The job runs in a bump-bot environment that only main can use, gets its token from BUMP_BOT_CLIENT_ID and BUMP_BOT_PRIVATE_KEY with contents and pull-requests write only, and hands it to just the two steps that list PRs and publish. Because the App opens the PR, CI runs on it normally. Allow GitHub Actions to create and approve pull requests stays off.
  • Every action in follow-upstream.yml is pinned by commit SHA, and a test enforces it.
  • nextbranch.py is replaced by the much smaller bump.py, and publish.py is rewritten.

CI (ci.yml)

  • No next in the PR triggers.
  • pins a stable release now runs on every PR.

Releases (publish.yml, scripts/release/)

  • Manual only. The workflow_run trigger and next-merge.mjs are gone. Merging a bump releases nothing.
  • Release branches are made by hand before merging a bump that starts a new gateway minor.

Tagged SDK (pinmove.py)

  • Upstream now tags the SDK module itself (sdk/go/v0.1.7), so go get of the release commit resolves to v0.1.7, not a pseudo-version. The pin move accepts the tag only after go list -m -json confirms it points at the release commit.
  • A dry run against 0.1.7 found this. Every bump from now on would have hit it.

Docs: a dated amendment to ADR 0005, a rewrite of deploy/ci/upstream/README.md, and updates to docs/releasing.md, CONTRIBUTING.md, AGENTS.md, .claude/rules and skills.

Testing

  • python3 -m unittest discover -s deploy/ci/upstream: 266 pass
  • node --test "scripts/**/*.test.mjs": 88 pass
  • validate-pins, gateway-range.mjs --check, and a YAML parse of all workflows
  • Dry run against the real repo and upstream. The plan found 0.1.7 (main pins 0.1.6). The bump step made one commit by github-actions[bot] that touches only gateway-pins.json, go.mod, go.sum and README.md, and its pins pass validate-pins. publish --dry-run printed exactly the leased push and gh pr create. Nothing was pushed. (The dry run predates the switch to the App token; the commands are the same.)

Not tested: a live run on GitHub. The first scheduled run after merge should open bump/openshell-0.1.7.

Before / after merging

  • Infra (Simon): the bump-bot App installed on this repo (Contents and Pull requests read/write), and a bump-bot environment limited to main holding BUMP_BOT_CLIENT_ID and BUMP_BOT_PRIVATE_KEY. If the names differ from these, tell me and I'll change them; they're in one place in the workflow. Until it exists, the bump job fails; plan, check A and the report still run.
  • Delete the UPSTREAM_BOT_TOKEN secret and the UPSTREAM_AUTOMERGE variable.
  • This PR is the base for the CI publishing PR (environments, PR images, SHA pins in ci.yml). Merge this one first, with Rebase and merge so the stacked PR stays clean.

🤖 Generated with Claude Code

Gkrumbach07 and others added 2 commits November 6, 2026 11:56
Since the move to the ai-openshell org, the `next` machinery no longer
works: nobody is an admin, main's ruleset resets approval on every push
(and `next` was force-pushed hourly), and the enterprise refuses the
long-lived UPSTREAM_BOT_TOKEN.

- Follow upstream runs once a day. For a new stable OpenShell release it
  creates bump/openshell-X.Y.Z from main with one signed-off pin-move
  commit, starts CI on it with workflow_dispatch (a PR opened with the
  default token starts none) and opens a PR into main. It makes a bump
  branch once and never rebases, moves or force-pushes it.
- A person can run it with a `version` to make a prep branch for a
  pre-release. Check A still runs nightly against upstream's newest
  pre-release and keeps the compat-migrate issue, which now says how to
  start a prep branch.
- publish.yml is manual only: no release after a merge, and
  next-merge.mjs is gone. Release branches are made by hand.
- ci.yml no longer runs for `next`, can be started by hand (publishing
  nothing), and `pins a stable release` applies to every PR.
- The pin move accepts the SDK's own tag (upstream tags sdk/go/v0.1.7),
  checked with `go list -m -json` to be the release commit. Found by a
  dry run against 0.1.7, which every bump from now on would have hit.
- Only the default token is used; UPSTREAM_BOT_TOKEN and
  UPSTREAM_AUTOMERGE can be deleted.
- ADR 0005 gets a dated amendment; the upstream README, releasing,
  contributing, rules and skills docs follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Gage Krumbach <gkrumbac@redhat.com>
Simon (infra) keeps "Allow GitHub Actions to create and approve pull
requests" off org-wide, and a pull request opened with the default token
runs no CI. So the bump job now takes a token from the organization's
bump-bot GitHub App, the same setup as sdk-go:

- The job runs in the `bump-bot` environment, which only main can deploy
  to, and gets its token with actions/create-github-app-token from
  BUMP_BOT_CLIENT_ID and BUMP_BOT_PRIVATE_KEY, asked for with contents and
  pull requests write only. Its own GITHUB_TOKEN is read-only.
- The App token reaches only the steps that list pull requests and
  publish, as the default token did.
- No more starting CI by hand: ci.yml drops workflow_dispatch and the
  check-* changes that went with it, and publish.py drops the dispatch.
- Every action in follow-upstream.yml is pinned by commit SHA; a test
  holds it to that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Gage Krumbach <gkrumbac@redhat.com>
if: needs.plan.outputs.bump == 'true'
runs-on: ubuntu-latest
# The App's secrets are in this environment, and only main may use it.
environment: bump-bot

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Manual runs from refs other than main are marked as dry runs at line 100, but a ready target still starts this job and requires the bump-bot environment. The PR says this environment is restricted to main, so these runs cannot access the App secrets or produce the promised bump preview. Could the preview run outside the protected environment, with only publishing guarded to main?

`none` means the move changed nothing: main already pins the target.
"""
git = Git(repo)
main = git.out("rev-parse", "--verify", "%s^{commit}" % main_ref)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This uses the workflow run’s checked-out HEAD as its base, which may no longer match current main when the branch is pushed. If the pin on main advances past the planned target during the run, the stale bump can still be published; the stable-release check does not reject backward pin changes, and the workflow will not refresh this branch later. Could it re-check the latest main pin before publishing and reject non-forward pin changes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants