Release: finish the autonomous mode with a workflow, without an agent (phases 4 to 8)

Open
#128 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
15/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
github-actions
Domain
ci-cd, devops, release

Research direction

Start with the phases 4 to 8 steps in recipes/release.md (ct-agents) and the release.jl status output they depend on, then release-tests.yml for the test style. Authorization, GitHub App credentials and the Environment approval are open decisions, so this needs a maintainer's design call before any code. Done means the reusable release-finish.yml, its thin caller and the listed tests exist, and a double wake-up posts nothing twice.

Written by the indexing model from the issue text.

Description

Goal

Finish a release without an agent. An agent (or a human) does the decisions at the start; a reusable workflow does the mechanical rest, robustly and without a long-lived session.

Today, phases 4 to 8 of ct-agents/recipes/release.md are mechanical and idempotent, driven by release.jl status: wait for the checks, release.jl merge, the tag and the GitHub release (ReleaseTag, already a workflow), the registration comment (release.jl register --post), the final comment, the closing of the issue, the deletion of the branch, release.jl audit. An agent waiting on a CI that takes tens of minutes is a session burning context for nothing. The value of the agent is in phases 0 to 3: the version, the changelog, what is breaking, the labels.

Seen on the release of CTModels v0.21.1 (control-toolbox/CTModels.jl#512).

Proposal

Split.

  • Agent or human, phases 0 to 3: preflight, proposal, tracking issue, release PR, local gate. At the end, an explicit opt-in to the autonomous finish (see Authorization).
  • A reusable workflow in CTActions, phases 4 to 8, called by a thin caller in each package like the other callers.
  • supervised mode stays as it is, with the same steps and the human's stops.

Event-driven, never a polling job. The workflow wakes on workflow_run completed (CI, Documentation, Breakage, ReleaseGate) for a release/v* branch, on pull_request events of the release PR, and on workflow_dispatch. At each wake-up it reads release.jl status and does the one next action, or nothing. Every action is "ensure", so a wake-up that fails or comes twice is harmless; the next one resumes from the facts.

Stops. On any stop condition of the recipe (a failed check, main not green, status blocked, an error from the registration, a GPU job without a runner) it comments on the tracking issue with the reason, status and the progress list with ❌, and stops. An agent or a human resumes.

Cases that need a decision, never automatic. main moved past the merge commit (--on-commit asks for the human's go in both modes). A version jump needing [merge approved]: only when the gate says betas explain it, as in the recipe. An error answer from the registration: never post again.

Authorization

Not anyone may start a stable release. The workflow must refuse unless all of these hold:

  1. Who opted in. The autonomous finish starts only from an action of an authorized person: the label (for example release: autonomous) added on the release PR, or the workflow_dispatch, by an actor whose permission on the repository is admin or maintain (GET /repos/{repo}/collaborators/{user}/permission), or who is on an explicit allowlist (an organization team). The check uses github.event.sender of the opting-in event, not the author of the PR or of the issue, which anyone can be.
  2. What it acts on. A pull request from a branch of the same repository (no fork) named release/v<X.Y.Z>, whose changes are the release files only (the gate already checks it), with the tracking issue [RELEASE] v<X.Y.Z> opened by an authorized person.
  3. A deployment approval. The job that holds the App token runs in a GitHub Environment (for example release) with required reviewers, so that the merge and the registration are one click of approval away from a person. This is the strongest guard and costs one click; it can be dropped for the packages where the label is enough.
  4. The merge is the tool's. Only release.jl merge, which checks what ran on the head commit. Never auto-merge, never gh pr merge.

Credentials: a GitHub App

GITHUB_TOKEN is not enough: a merge or a comment made with it does not start other workflows, so ReleaseTag would not run after the merge, and the registration comment of a bot account may not be accepted. A GitHub App of the organization, with a short-lived installation token minted in the job, is cleaner than a personal access token.

  • Check first whether an existing App of the organization fits (permissions below), before creating a new one.
  • Permissions needed: contents: write (merge, delete the branch, dispatch), pull-requests: write, issues: write (comments, close), actions: write (dispatch ReleaseTag / Documentation when needed), checks: read / actions: read for the status.
  • The token is minted only in the job of the Environment above (actions/create-github-app-token), never in a job triggered by a fork.
  • To verify: that a comment posted with the App token is taken into account by the registration step. If it is not, the App cannot post it, and that single step stays with a user token (or the human).

Tasks

  • Decide the authorization (label vs dispatch, team allowlist, Environment with reviewers).
  • Look for a suitable GitHub App in the organization, else create one with the permissions above; store its id and key as organization secrets.
  • Check that a comment posted by the App triggers the registration.
  • Reusable workflow release-finish.yml and its doc in docs/workflows/, with the thin caller ReleaseFinish.yml for the packages.
  • release.jl: make sure every phase 4 to 8 action is runnable from status alone, and that a run prints a machine-readable next action (it may exist already).
  • Tests in the style of release-tests.yml: a fork PR is refused, an unauthorized sender is refused, a wake-up on a done release does nothing, a double wake-up does not post twice.
  • Update recipes/release.md in ct-agents: the autonomous mode hands phases 4 to 8 to the workflow when the package has the caller; the agent only opts in and then watches the issue.
  • Try it on the next release of one package, in supervised approval first (Environment reviewers on), then without.
Dominant language
Julia
Stars
1
Forks
0
Avg merge
1h 39m
Merged PRs (30d)
45

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from control-toolbox/CTActions

All issues in control-toolbox/CTActions

Similar issues

More Julia issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.