Skip to content

Commit 164ce9b

Browse files
Merge pull request #194 from adambkaplan/ship-backports-implementable
SHIP-0038: Implementable Version
2 parents 1d276ab + a709efa commit 164ce9b

File tree

1 file changed

+245
-49
lines changed

1 file changed

+245
-49
lines changed

ships/0038-release-branching-backports.md

Lines changed: 245 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ approvers:
1515
- "@qu1queee"
1616
- "@SaschaSchwarze0"
1717
creation-date: 2024-02-20
18-
last-updated: 2024-02-22
18+
last-updated: 2024-03-05
1919
status: provisional
2020
see-also:
2121
- https://github.com/shipwright-io/community/issues/85
@@ -28,15 +28,15 @@ superseded-by: []
2828

2929
## Release Signoff Checklist
3030

31-
- [ ] Enhancement is `implementable`
32-
- [ ] Design details are appropriately documented from clear requirements
33-
- [ ] Test plan is defined
34-
- [ ] Graduation criteria for dev preview, tech preview, GA
35-
- [ ] User-facing documentation is created in [docs](/docs/)
31+
- [x] Enhancement is `implementable`
32+
- [x] Design details are appropriately documented from clear requirements
33+
- [x] Test plan is defined
34+
- [x] Graduation criteria for dev preview, tech preview, GA
35+
- [x] User-facing documentation is created in [docs](/docs/)
3636

3737
## Open Questions [optional]
3838

39-
TBD as we iterate through the enhancement proposal lifecycle.
39+
None.
4040

4141
## Summary
4242

@@ -70,6 +70,8 @@ or other potential breaking changes.
7070
- Apply backport process to older released versions.
7171
- Prescribe a cadence for feature and bugfix releases.
7272
- Establish long term support (LTS) versioning and backport processes.
73+
- Alter our current process for generating release notes.
74+
- Standardize on a single release toolchain.
7375

7476
## Proposal
7577

@@ -127,78 +129,272 @@ such situations.
127129

128130
### Implementation Notes
129131

130-
**Note:** *Section not required until feature is ready to be marked 'implementable'.*
131-
132-
TBD - requires investigation into the following:
133-
134-
- Current release script assumptions with respect to branch names.
135-
- Current CI assumptions with respect to branch names.
136-
- Applying the process "retroactively" to build, cli, and operator repos.
137-
138-
### Test Plan
139-
140-
TBD
141-
142-
**Note:** *Section not required until targeted at a release.*
132+
#### Release Branching Workflow
133+
134+
Shipwright has set up the `.github` repository which - amongst other features -
135+
allows GitHub actions to be shared consistently across the organization. We already
136+
have a standing "add to project" workflow that adds all new issues and pull requests
137+
to the main "Shipwright Overview" GitHub project. [1]
138+
139+
We can create a reusable "release branching" workflow [2] as follows:
140+
141+
- Use `workflow_call` as the trigger, to be run on the main branch. [2]
142+
- Receive a semantic version as input (in `vX.Y` format) to create the release branch
143+
name.
144+
- Create the release branch via standard git commands, ensuring the workflow is
145+
granted write permission to the appropriate repository.
146+
147+
Example (`shipwright-io/.github/.github/workflows/release-branch.yml`):
148+
149+
```yaml
150+
name: Release Brancher
151+
on:
152+
workflow_call:
153+
inputs:
154+
release-version:
155+
required: true
156+
type: string
157+
git-ref:
158+
required: false
159+
type: string
160+
jobs:
161+
release-brancher:
162+
runs-on: ubuntu-latest
163+
steps:
164+
- uses: actions/checkout@v4
165+
with:
166+
ref: ${{ inputs.git-ref }}
167+
- name: Create release branch
168+
env:
169+
RELEASE_VERSION: release-${{ inputs.release-version }}
170+
run: |
171+
git switch -c ${RELEASE_VERSION}
172+
git push --set-upstream origin ${RELEASE_VERSION}
173+
```
143174
175+
Each repository can then be onboarded using a starter workflow that is hosted in the
176+
.github repository (`.github/workflow-templates/release-branch.yml`) [3]:
177+
178+
```yaml
179+
name: Create Release Branch
180+
on:
181+
workflow_dispatch:
182+
inputs:
183+
release-version:
184+
required: true
185+
type: string
186+
description: "Semantic version for the release branch (vX.Y format)"
187+
jobs:
188+
create-release-branch:
189+
runs-on: ubuntu-latest
190+
permissions:
191+
contents: write
192+
uses: shipwright.io/.github/.github/workflows/release-branch.yml@main
193+
with:
194+
release-version: ${{ inputs.release-version }}
144195
```
145-
Consider the following in developing a test plan for this enhancement:
146196

147-
- Will there be e2e and integration tests, in addition to unit tests?
148-
- How will it be tested in isolation vs with other components?
197+
[1] https://github.com/shipwright-io/.github/blob/main/.github/workflows/issues.yml
198+
199+
[2] https://docs.github.com/en/actions/using-workflows/reusing-workflows
200+
201+
[3] https://docs.github.com/en/actions/using-workflows/creating-starter-workflows-for-your-organization
202+
203+
#### Release Workflows
204+
205+
Component repositories will retain the core of their existing release workflows.
206+
However, each will need to be modified so the release workflow runs against the
207+
appropriate `release-vX.Y` branch:
208+
209+
- `build`: The `release.yml` workflow will receive a new required parameter,
210+
`release-branch`. This will be passed to the standard git checkout action. The
211+
current release workflow creates a follow-up PR to update the README with the
212+
latest release version/tag. This will be opened against the `release-branch` (not)
213+
`main`
214+
- `operator`: The `release.yml` workflow will receive a new required parameter,
215+
`release-branch`. This will be passed to the standard git checkout action.
216+
- `cli`: The `cli` repository will add a new workflow, `release-tag.yml`, which will
217+
create the tag for the upcoming release. This will accept `release-branch` as
218+
required parameter, to be passed to the standard git checkout action:
219+
220+
```yaml
221+
name: Create Release Tag
222+
on:
223+
workflow_dispatch:
224+
inputs:
225+
release-branch:
226+
required: true
227+
type: string
228+
description: "Branch to use for creating the release tag"
229+
version-tag:
230+
required: true
231+
type: string
232+
description: "Full semantic version of the release (in vX.Y.Z format)"
233+
jobs:
234+
create-release-tag:
235+
... # permissions, check out ${{ inputs.release-branch }}
236+
- name: Tag release
237+
env:
238+
- VERSION_TAG: ${{ inputs.version-tag }}
239+
run: |
240+
git tag ${VERSION_TAG}
241+
git push --tags
242+
```
243+
244+
Once the tag is created, the `cli` release workflow should work as-is.
245+
246+
#### GitHub Branch Protection
247+
248+
Each repository will need to create a new branch protection rule that applies to
249+
`release-v*` branches. Branch protection settings from the `main` branch will need to
250+
be manually copied over to the release branch rule.
251+
This is due to simplifying limitations in how GitHub does pattern matching for
252+
[branch protection rules](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule#about-branch-protection-rules).
253+
254+
The branch protection policy needs to allow GitHub actions to push branches and tags.
255+
256+
#### Backport Process
257+
258+
Backporting can be done in one of three ways:
259+
260+
1. "Manually": this would involve a contributor running `git cherry-pick` on their
261+
local machine against a release branch, resolving any merge conflicts, then
262+
opening a pull request.
263+
2. Prow `cherrypick` bot: our existing configuration for OpenShift CI will be
264+
updated to enable the Prow cherrypick plugin. The bot can automatically create
265+
cherrypick pull requests by adding a `/cherrypick <branch-name>` comment to an
266+
existing pull request, either when it is open or after merge. See the Prow
267+
docs [1] for more details.
268+
3. Standard pull request - typically reserved for the following:
269+
1. Dependency updates, where changes to `go.mod` and `go.sum` would likely lead
270+
to merge conflicts across release branches.
271+
2. Bug fixes for code that was refactored in a subsequent release.
272+
273+
[1] https://docs.prow.k8s.io/docs/components/external-plugins/cherrypicker/
149274

150-
No need to outline all of the test cases, just the general strategy. Anything that would count as
151-
tricky in the implementation and anything particularly challenging to test should be called out.
275+
### Test Plan
152276

153-
All code is expected to have adequate tests (eventually with coverage expectations).
154-
```
277+
CI jobs for each component repository will need to support execution from a branch
278+
that matches the release branch pattern. This is done by updating the `on.pull_request` stanza of
279+
the GitHub action to match `release-v*` branch names (same as branch protection
280+
rules). This should be updated for both push events as well as pull requests that
281+
target the release branch.
155282

156283
### Release Criteria
157284

158-
TBD - ideally this is introduced to release `v0.13.0` and applied retroactively to
159-
`v0.12.z`.
285+
This process will apply to the `v0.13.0` release moving forward. It will also be
286+
applied retroactively to `v0.12.0` by running the release branch workflow,
287+
referencing an appropriate release tag.
160288

161289
#### Removing a deprecated feature [if necessary]
162290

163291
Not Applicable
164292

165293
#### Upgrade Strategy [if necessary]
166294

167-
TBD
295+
Not directly applicable.
296+
297+
Care must be taken when introducing "breaking" changes to the release brancher
298+
workflow. The workflow parameters should be treated like an API.
168299

169300
### Risks and Mitigations
170301

171-
TBD once the proposal is flushed out.
302+
**Risk**: Unreviewed code merges in release branches.
172303

173-
```
174-
What are the risks of this proposal and how do we mitigate? Think broadly. For example, consider
175-
both security and how this will impact the larger Shipwright ecosystem.
304+
_Mitigation:_ Branch protection rules for `main` will be copied over to release
305+
branches. Checks that ensure unreviewed code is blocked from merge will be applied
306+
to release candidates and bugfix releases. At present, no workflow requires code to
307+
be modified during the release process.
176308

177-
How will security be reviewed and by whom? How will UX be reviewed and by whom?
178-
```
179309

180-
## Drawbacks
310+
**Risk**: Code will be released untested.
181311

182-
TBD once the implementation details are documented.
312+
_Mitigation_: CI workflows will be updated to run on the release branch for push
313+
events as well as pull requests.
183314

184-
```
185-
The idea is to find the best form of an argument why this enhancement should _not_ be implemented.
186-
```
315+
**Risk**: Unauthorized releases.
187316

188-
## Alternatives
317+
_Mitigation_: Manually triggered workflows require the "write" permission to a
318+
repository. These are individuals who typically have been promoted to the "Reviewer"
319+
role in the project and have established some level of trust within the community.
320+
Membership and contributor status should be reviewed regularly (at least annually) to
321+
reduce risk.
189322

190-
TBD as the enhancement proposal progresses through its lifecycle.
323+
## Drawbacks
191324

192-
```
193-
Similar to the `Drawbacks` section the `Alternatives` section is used to highlight and record other
194-
possible approaches to delivering the value proposed by an enhancement.
195-
```
325+
- The "release brancher" workflow needs to be copied to individual repositories via
326+
the [GitHub starter worflows](https://docs.github.com/en/actions/learn-github-actions/using-starter-workflows)
327+
process. This makes it easier to check out code and create a relase branch via git
328+
commands.
329+
- Branch protection rules will need to be copied over by hand, due to limitations in
330+
the pattern matching behavior in GitHub. To simplify matching rules, GitHub does
331+
not have full RegEx support for branch protection matching. They instead support
332+
syntax that is closer to "glob" matching on a Unix system.
333+
- The release branching workflow itself is "copied" to each repository via a starter
334+
workflow. Defining a reusable workflow mitigates this drawback - the bulk of the
335+
logic to set up a release branch is centralized.
336+
- CI jobs will need to be updated by hand to run against the release branch.
337+
- The release workflow for `build` will by default open the README update pull
338+
requests against the release branch. This means that updates to `main` may have to
339+
be done manually, or the README in `main` will need to reference a floating
340+
"latest" release tag.
341+
342+
## Alternatives
343+
344+
### Single Release Brancher Workflow
345+
346+
Instead of using a starter workflow for release branching, we could have set up a
347+
single workflow in `.github` that applied to _all_ Shipwright repositories. Doing
348+
this would require some extra logic to tell the checkout action which repository to
349+
check out and push the release branch to. It also removes flexibility in case a
350+
repository needs to run other workflows as pre/post branching "hooks." For example,
351+
after branching the `operator` repository may want to update the `VERSION` variable
352+
in its Makefile and regenerate the operator bundle manifest.
353+
354+
### Standardize on a release toochain (GoReleaser)
355+
356+
Since most projects in Shipwright are go-based, we could choose a single toolchain
357+
like GoReleaser to build our release artifacts [1]. This would require substantially
358+
more effort, requiring re-writes to how the `build` and `operator` repositories
359+
release code. The current proposal takes advantage of existing project release
360+
workflows, only requiring small modifications in specific spots.
361+
362+
### Status Quo
363+
364+
Keeping the status quo (_no release branching_) means that the community cannot
365+
provide sanctioned bugfix/security patch releases. Downstream distributions remain
366+
free to build this infrastructure on their own. Lack of process for backports/
367+
release branching could impact our evaluations for maturity status (ex: "Graduated"
368+
in CNCF or CDF).
369+
370+
### Release .0 from `main`
371+
372+
Instead of branching first, then releasing, we could release the "dot zero" release
373+
from `main`. This simplifies the initial release process and makes it easier to use
374+
our current release tooling "as is." The short-term savings are negated by long-term
375+
costs/tech debt with this approach:
376+
377+
- Bugfix releases will use a slightly skewed set of release scripts compared to "dot
378+
zero."
379+
- Release branches for z-streams will need to be created after the fact, at the will
380+
of the project maintainers. This is a potential "open loop" that is not critical
381+
to the initial release process, putting it at risk of being skipped or forgotten.
382+
- Release branching makes it easier for "experimental" features to merge earlier.
383+
Often this work will start in a "feature" branch, then merge into the `main`
384+
branch early in a release cycle so bugs can be identified and patched before
385+
end-users consume it.
196386

197387
## Infrastructure Needed [optional]
198388

199-
TBD - this will likely require new GitHub actions, changes to existing GitHub
200-
Actions, or enabling features in Prow (currently provided by OpenShift CI).
389+
New workflows in the `.github` repository:
390+
391+
- Reusable workflow for release branching
392+
- Starter workflow for release branching (to be copied over)
393+
394+
Also needs a new workflow in the `cli` repository to create release tags. This was
395+
a pre-existing need.
201396

202397
## Implementation History
203398

204399
- 2024-02-20: Initial proposal (`provisional`)
400+
- 2024-03-05: Implementable version

0 commit comments

Comments
 (0)