diff --git a/.github/MONTHLY_PATCH.md b/.github/MONTHLY_PATCH.md new file mode 100644 index 00000000..dc70bc40 --- /dev/null +++ b/.github/MONTHLY_PATCH.md @@ -0,0 +1,160 @@ +# Monthly patch setup + +The monthly patch controller and full proposal live in the companion +[notation CLI repository](https://github.com/notaryproject/notation). This +repository installs only a dispatch workflow that calls the CLI's reusable +worker at a full commit SHA. The CLI owns the shared scripts, regression tests, +assessment schedule, and controller. Go does not require a Copilot token. + +## Merge-time state + +Maintainers must leave the Actions variable `MONTHLY_PATCH_ENABLED` unset or +`false` when merging the setup. Merging this change is not authorization to +activate automation, change repository settings, or publish a release. The +companion CLI controller and this repository's caller must both be installed +before activation. The draft's reusable-workflow pin must be rebound to the final +upstream CLI commit after the companion PR merges, before Go merges or activates. +Squash merging can change that commit SHA. +The current review pin is `953678d7760d177da9e3f4f61e928df8427eee24`. +Maintainers must update both the caller's `uses` reference and `worker_sha` +input to the same final upstream commit. + +## Repository settings + +| Setting | Required setup | +| --- | --- | +| Repository features | Enable GitHub Actions and Issues. | +| Actions policy | Allow the reusable workflow `notaryproject/notation/.github/workflows/monthly-patch-worker.yml` and its required actions. The caller uses a full commit SHA, and the central worker checks out its helper code at the corresponding immutable pin. | +| Dependabot | Keep Go modules and GitHub Actions updates enabled on `main`. The existing `.github/dependabot.yml` configures both weekly and does not override the default target branch. | +| Release branch | Maintain the current latest stable `release-X.Y` branch with required CI checks and reviews. Determine the branch from the current stable release, not from the version on `main`. | +| Merge methods | Enable **Allow merge commits**. Preserve the required normal merge method for release voting PRs. | +| Stable baseline | Ensure the current stable baseline tag is signed and its signature/provenance can be verified by the worker. An unverifiable baseline blocks execution. | +| Actions secret `MONTHLY_PATCH_TOKEN` | Provide an authenticated-user token whose `GET /user` identity matches `MONTHLY_PATCH_ACTOR` across Core, Go, and CLI. Scope it to the three repositories with contents, pull requests, issues, and Actions write permissions, plus workflow write permission if workflow updates are in scope. GitHub App installation tokens are unsupported. Do not grant branch-rule bypass. | +| Actions secret `MONTHLY_PATCH_SIGNING_KEY` | Store the private release-signing key as a secret, never as a repository file, variable, issue, or PR attachment. | +| Actions variable `MONTHLY_PATCH_ACTOR` | Set the same automation actor login used by the companion Core and CLI changes. | +| Signer identity variables | Set `MONTHLY_PATCH_SIGNER_LOGIN` and `MONTHLY_PATCH_SIGNER_EMAIL`. Optionally set `MONTHLY_PATCH_SIGNER_NAME`. Ensure the identity matches the signing key. | +| Signing-key registration | Register only the public signing key on the designated signer's GitHub account. | +| Actions variable `MONTHLY_PATCH_ENABLED` | Leave unset or `false` until maintainers explicitly authorize activation after companion setup and validation. | + +Maintainers must verify the configured token can perform the required operations +without bypassing required checks or reviews. The caller passes only the two +declared secrets, and passes empty values during `dry-run`; it does not inherit +all repository secrets. + +## Coordination and release approvals + +Go has its own third-party dependency updates. A Go cycle waits for Core only +when Core publishes a release in the same coordinated cycle. In that case, the +exact planned canonical `github.com/notaryproject/notation-core-go` version must +pass the checked producer PR before release. Core must first pass public release +verification. The controller must then reassess Go with that exact producer +version; an earlier assessment with no Go updates is not a final skip decision. +Fork `replace` directives are not an acceptable substitute. + +The CLI controller owns cycle assessment and coordination. Each repository has +one release issue with its month, current/proposed versions, own changes, +dependency issue links, status, and maintainer action. Go links Core's issue +without repeating Core's change list. The CLI issue provides overall status +and links to both library issues. + +A maintainer must review and approve the overall plan before execution starts. The approval +must bind the reviewed plan and cannot be inferred from setup approval, a timer, +or a manual dispatch. A current active CLI repo-level maintainer must post the +exact, unedited comment `/approve` on the CLI release +issue showing the immutable plan. The controller checks the issue body, plan +reference, policy, roster, and comment on approval and subsequent writes. +The controller polls every six hours or on manual dispatch. Editing or deleting +the approval comment revokes remaining execution. +Closing the issue, using a manual approval input, or setting an old automatic +approval flag cannot bypass this gate. A changed plan requires a new approval +comment. + +Assessment also reviews new `main` commits for evidence-backed bug fixes +applicable to the stable release line. It lists candidates separately for +maintainer review and does not automatically backport them. Features are +excluded, and adding a fix to an approved scope requires a new approval. + +Worker execution must preserve the release approval points in +[Release Checklist](../RELEASE_CHECKLIST.md), including a majority of repo-level +maintainer approvals on the release voting PR, the required merge-commit method, +and a signed release tag. Setup approval does not replace release voting. + +The majority-maintainer vote and merge-commit requirement apply to the separate +release voting PR that updates `signingAgent`, not to the preceding dependency +bump PR. Dependency PRs still require the configured CI and reviews. The release +voting PR description must link the change logs and repo-level maintainer list. +Automation must not waive these governance gates. + +The signed release tag targets the single signed commit recorded by the voting +PR. The release branch retains the normal merge commit, whose tree must match +the voted commit. The worker must recheck the exact candidate, current-head +maintainer majority, and merge provenance before publication. +The controller pins the active repo-level roster from the default branch at +assessment time. Roster changes require reassessment; a historical stable tag +does not supply the voting roster. +The worker validates the metadata delta against the exact qualified dependency +candidate. A release voting PR can include those recorded backports plus the +required metadata update without granting permission for other source changes. + +## Draft review and manual publication + +After qualification, the worker creates an actual GitHub draft release. Once +native draft checks pass, it posts the review request to Go's existing release +issue instead of opening another review issue. +Maintainers review the draft, qualification evidence, and recorded asset bytes. +This review is separate from both the shared plan +approval and Go's required release voting PR. +Draft-native checks use only the target repository's read-only `github.token` +with Contents read permission. Denied draft access blocks review issue creation; +the checks do not fall back to the release-writing credential. + +A maintainer initially publishes the reviewed draft using GitHub's **Publish +release** action. Automation does not change the draft to a published release. +Automatic publishing would require a separate future opt-in and is not +implemented by this flow. + +The current worker creates the signed tag before draft review. A GitHub draft +does not hide that tag or prevent Go module downloads. The required maintainer +approval before final stable-tag creation is not implemented; official stable +releases must remain disabled until that separate gate is implemented and +validated. + +After manual publication, +the worker must observe the same release ID, tag, asset IDs, hashes, and sizes, +then run anonymous native public checks. Only successful verification allows +downstream consumers to advance. An absent publication or mismatched release remains +blocked; the worker must not substitute another release. + +## Failure notifications + +The controller reports errors and blockers in the affected repository's release +issue, mentions its maintainers, and links the failed stage/run and evidence. +Dependent issues receive only a concise blocker and a link to the affected issue. +The same issue receives the draft-ready review request. Routine progress does not +generate comments. Reconciliation deduplicates alerts; a new failed retry can +produce a new alert without rewriting approved scope or waiving checks. + +Subscribe to Go's release issue and configure GitHub notifications; email +delivery is not guaranteed. If no trusted issue exists, Actions logs and +failed-workflow notifications are the fallback. + +## Activation + +1. Maintainers review and merge the companion CLI controller and the + Go caller, with automation still disabled. Before merging Go, rebind its + provisional draft pin to the final upstream CLI commit and review the + central helper checkout pin. +2. Administrators configure the settings above and confirm the required CI and + review rules apply to the selected stable release branch. +3. Maintainers review the CLI's centralized tests and the Go caller's workflow + lint and contract checks, and approve setup and activation. These approvals + do not replace each cycle's plan approval or release reviews. +4. Administrators keep official stable releases disabled until the pre-tag + approval gap above is resolved. They set `MONTHLY_PATCH_ENABLED` to `true` + only after that gate is validated and the required approvals are obtained. + They can return it to `false` to disable future worker execution. + +The worker defaults to a no-write `dry-run`. Canonical execution requires a +maintainer-approved shared plan, controller-authorized cycle, plan digest, and +attempt from the CLI, along with the enabled setting and configured actor. +A manual dispatch alone does not authorize execution or publication. diff --git a/.github/workflows/monthly-patch-release.yml b/.github/workflows/monthly-patch-release.yml new file mode 100644 index 00000000..907c6057 --- /dev/null +++ b/.github/workflows/monthly-patch-release.yml @@ -0,0 +1,64 @@ +# Copyright The Notary Project Authors. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This draft pin cannot authorize execution. Replace both SHA values with the +# final upstream merged CLI implementation SHA before merging this caller or +# enabling monthly writes. +name: Monthly dependency patch release +run-name: 'Monthly patch ${{ inputs.month }} ${{ inputs.plan_id }} #${{ inputs.controller_issue }} attempt ${{ inputs.attempt }}' + +on: + workflow_dispatch: + inputs: + mode: + description: No-write plan, or coordinator-authorized canonical execution + type: choice + options: [dry-run, execute] + default: dry-run + required: true + month: + description: Optional YYYY-MM cycle to inspect or resume (UTC month by default) + type: string + required: false + controller_issue: + description: Trusted cycle issue in notaryproject/notation, required for execution + type: string + required: false + plan_id: + description: Approved assessment digest, required for execution + type: string + required: false + attempt: + description: Dispatched worker attempt, required for execution + type: string + required: false + +permissions: + actions: read + contents: read + issues: read + pull-requests: read + +jobs: + release: + uses: notaryproject/notation/.github/workflows/monthly-patch-worker.yml@953678d7760d177da9e3f4f61e928df8427eee24 + with: + mode: ${{ inputs.mode }} + month: ${{ inputs.month }} + controller_issue: ${{ inputs.controller_issue }} + plan_id: ${{ inputs.plan_id }} + attempt: ${{ inputs.attempt }} + worker_sha: 953678d7760d177da9e3f4f61e928df8427eee24 + secrets: + MONTHLY_PATCH_TOKEN: ${{ inputs.mode == 'execute' && secrets.MONTHLY_PATCH_TOKEN || '' }} + MONTHLY_PATCH_SIGNING_KEY: ${{ inputs.mode == 'execute' && secrets.MONTHLY_PATCH_SIGNING_KEY || '' }}