Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions .github/MONTHLY_PATCH.md
Original file line number Diff line number Diff line change
@@ -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.
64 changes: 64 additions & 0 deletions .github/workflows/monthly-patch-release.yml
Original file line number Diff line number Diff line change
@@ -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 || '' }}
Loading