Skip to content

Commit 0c92c67

Browse files
committed
feat(tooling): add minor-rc, patch-rc, major-rc for 0.39.x->0.40.0-rc.1
- ci: provenance and SBOM attestation on GHCR push; cosign for image and chart - release: bump options patch-rc, minor-rc, major-rc
1 parent 92eefa4 commit 0c92c67

File tree

7 files changed

+107
-18
lines changed

7 files changed

+107
-18
lines changed

.github/workflows/ci.yaml

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@
22
# Replaces pr.yaml and the tag-driven parts of release-please.
33
#
44
# On tag (v*): release workflow has already bumped Chart/values/package.json and pushed
5-
# the tag. This workflow builds gitops-server image ( :X.Y.Z and :latest), pushes the
6-
# Helm chart OCI, and runs goreleaser for gitops CLI binaries.
5+
# the tag. This workflow:
6+
# - build-push-gitops-server: builds and pushes gitops-server image (:tag, :latest)
7+
# with provenance (mode=max) and SBOM attestations; keyless cosign signing and verify
8+
# - build-and-push-chart: packages Helm chart, pushes OCI, keyless cosign sign and verify
9+
# - goreleaser: builds gitops CLI binaries (linux/darwin, amd64/arm64), signs with cosign,
10+
# uploads to GitHub Release (mode: keep-existing). For non-prerelease tags, includes
11+
# Homebrew tap publish (.goreleaser.brew.yml).
712
#
813
# Runs on main and feature/re-implement-workflows (for testing). Fork-friendly: image,
914
# chart and goreleaser use github.repository / github.repository_owner (your fork when
@@ -89,6 +94,7 @@ jobs:
8994
permissions:
9095
contents: read
9196
packages: write
97+
id-token: write
9298
steps:
9399
- uses: actions/checkout@v4
94100
with:
@@ -112,6 +118,7 @@ jobs:
112118
password: ${{ secrets.GITHUB_TOKEN }}
113119

114120
- name: Build and push gitops-server
121+
id: build
115122
uses: docker/build-push-action@v5
116123
with:
117124
context: .
@@ -120,13 +127,28 @@ jobs:
120127
LDFLAGS=${{ env.LDFLAGS }}
121128
GIT_COMMIT=${{ github.sha }}
122129
push: true
130+
provenance: "mode=max"
131+
sbom: true
123132
tags: |
124133
ghcr.io/${{ github.repository }}/gitops-server:${{ github.ref_name }}
125134
ghcr.io/${{ github.repository }}/gitops-server:latest
126135
cache-from: type=gha
127136
cache-to: type=gha,mode=max
128137
platforms: linux/amd64,linux/arm64
129138

139+
- name: Install cosign
140+
uses: sigstore/cosign-installer@v4
141+
142+
- name: Keyless signing of image
143+
run: |
144+
cosign sign --yes ghcr.io/${{ github.repository }}/gitops-server@${{ steps.build.outputs.digest }}
145+
146+
- name: Verify the image signing
147+
run: |
148+
cosign verify ghcr.io/${{ github.repository }}/gitops-server@${{ steps.build.outputs.digest }} \
149+
--certificate-identity "https://github.com/${{ github.workflow_ref }}" \
150+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" | jq .
151+
130152
build-and-push-chart:
131153
name: Build and push Helm chart
132154
needs: [build-and-test]
@@ -135,6 +157,7 @@ jobs:
135157
permissions:
136158
contents: read
137159
packages: write
160+
id-token: write
138161
steps:
139162
- uses: actions/checkout@v4
140163
with:
@@ -149,10 +172,27 @@ jobs:
149172
echo ${{ secrets.GITHUB_TOKEN }} | helm registry login ghcr.io -u ${{ github.actor }} --password-stdin
150173
151174
- name: Package and push chart
175+
id: push-chart
152176
run: |
153177
helm package charts/gitops-server -d /tmp
154178
CHART=$(ls /tmp/weave-gitops-*.tgz)
155-
helm push "$CHART" oci://ghcr.io/${{ github.repository_owner }}
179+
helm push "$CHART" oci://ghcr.io/${{ github.repository_owner }} 2>&1 | tee /tmp/push.log
180+
CHART_DIGEST=$(awk '/Digest: /{print $2}' /tmp/push.log)
181+
[ -n "$CHART_DIGEST" ] || { echo "Could not parse digest from helm push"; cat /tmp/push.log; exit 1; }
182+
echo "digest=$CHART_DIGEST" >> $GITHUB_OUTPUT
183+
184+
- name: Install cosign
185+
uses: sigstore/cosign-installer@v4
186+
187+
- name: Keyless signing of chart
188+
run: |
189+
cosign sign --yes ghcr.io/${{ github.repository_owner }}/weave-gitops@${{ steps.push-chart.outputs.digest }}
190+
191+
- name: Verify the chart signing
192+
run: |
193+
cosign verify ghcr.io/${{ github.repository_owner }}/weave-gitops@${{ steps.push-chart.outputs.digest }} \
194+
--certificate-identity "https://github.com/${{ github.workflow_ref }}" \
195+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" | jq .
156196
157197
goreleaser:
158198
name: Goreleaser (gitops CLI)
@@ -161,6 +201,7 @@ jobs:
161201
runs-on: ubuntu-latest
162202
permissions:
163203
contents: write
204+
id-token: write
164205
env:
165206
FLUX_VERSION: "2.7.2"
166207
steps:
@@ -178,6 +219,13 @@ jobs:
178219
- name: Set CHART_VERSION from tag
179220
run: echo "CHART_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
180221

222+
- name: Include brew publishing
223+
if: "!contains(github.ref_name, '-')"
224+
run: cat .goreleaser.brew.yml >> .goreleaser.yml
225+
226+
- name: Install cosign
227+
uses: sigstore/cosign-installer@v4
228+
181229
- uses: goreleaser/goreleaser-action@v6
182230
with:
183231
distribution: goreleaser

.github/workflows/release.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ on:
1515
workflow_dispatch:
1616
inputs:
1717
bump:
18-
description: "Bump type (default: patch). rc = 0.39.0-rc.2 -> 0.39.0-rc.3"
18+
description: "Bump type. minor-rc: 0.39.x -> 0.40.0-rc.1; rc: 0.39.0-rc.2 -> 0.39.0-rc.3"
1919
required: false
2020
default: patch
2121
type: choice
@@ -24,6 +24,9 @@ on:
2424
- minor
2525
- major
2626
- rc
27+
- patch-rc
28+
- minor-rc
29+
- major-rc
2730
branch:
2831
description: "Branch to release from (e.g. main or feature/re-implement-workflows)"
2932
required: false

tooling/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ Release and build tooling for Weave GitOps.
44

55
## Commands
66

7-
- **weavegitops release bump** [patch|minor|major|rc]
8-
Bump version from `charts/gitops-server/Chart.yaml`; update Chart.yaml (version, appVersion), `charts/gitops-server/values.yaml` (image.tag), `package.json` (version). Use **rc** for release candidates: `0.39.0-rc.2``0.39.0-rc.3` (or `0.39.0``0.39.0-rc.1`). Writes `version` to `GITHUB_OUTPUT` when set.
7+
- **weavegitops release bump** [patch|minor|major|rc|patch-rc|minor-rc|major-rc]
8+
Bump from `charts/gitops-server/Chart.yaml`; updates Chart, values, package.json. **rc**: `0.39.0-rc.2``0.39.0-rc.3` or `0.39.0``0.39.0-rc.1`. **minor-rc**: `0.39.x``0.40.0-rc.1` (start RC for next minor). Also **patch-rc**, **major-rc**. Writes `version` to `GITHUB_OUTPUT` when set.
99

1010
- **weavegitops release generate-notes** --version X.Y.Z [--output PATH] [--template PATH] [--since-tag TAG] [--provider openai|anthropic]
1111
Generate release notes from commits since the previous tag via OpenAI or Anthropic.

tooling/src/weave_gitops_tooling/cli/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ def _build_parser():
5959
"bump",
6060
nargs="?",
6161
default="patch",
62-
choices=["patch", "minor", "major", "rc"],
63-
help="Bump type: patch|minor|major|rc (default: patch). rc: 0.39.0-rc.2 -> 0.39.0-rc.3",
62+
choices=["patch", "minor", "major", "rc", "patch-rc", "minor-rc", "major-rc"],
63+
help="Bump: patch|minor|major|rc|patch-rc|minor-rc|major-rc. minor-rc: 0.39.x -> 0.40.0-rc.1",
6464
)
6565
prlgn = prl_sub.add_parser(
6666
"generate-notes",

tooling/src/weave_gitops_tooling/cli/release.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def run_release(args, project_root: Path) -> None:
3131
)
3232
sys.exit(rc)
3333
print("weavegitops release: use subcommand 'bump' or 'generate-notes'")
34-
print(" weavegitops release bump [patch|minor|major|rc]")
34+
print(" weavegitops release bump [patch|minor|major|rc|patch-rc|minor-rc|major-rc]")
3535
print(
3636
" weavegitops release generate-notes --version X.Y.Z [--output PATH] [--template PATH] [--since-tag TAG] [--provider openai|anthropic]"
3737
)

tooling/src/weave_gitops_tooling/release/bump.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
"""Bump version from charts/gitops-server/Chart.yaml; update Chart, values, package.json.
22
3-
Source of truth: charts/gitops-server/Chart.yaml `version`. For bump=rc: parses -rc.N
4-
and produces X.Y.Z-rc.(N+1); if no -rc, produces X.Y.Z-rc.1. For patch|minor|major:
5-
strips -rc.N (or similar) to get base X.Y.Z and bumps that. Writes: Chart.yaml
6-
(version, appVersion), values.yaml (image.tag), package.json (version). Tags use v
7-
prefix (workflow adds 'v' when creating the git tag). Appends version=... to
8-
GITHUB_OUTPUT when set.
3+
Source of truth: charts/gitops-server/Chart.yaml `version`.
4+
5+
Bump types:
6+
- patch|minor|major: strip -rc.N, bump X.Y.Z (e.g. 0.39.0-rc.2 --minor--> 0.40.0).
7+
- rc: keep base, X.Y.Z-rc.(N+1) or X.Y.Z-rc.1 (e.g. 0.39.0-rc.2 -> 0.39.0-rc.3).
8+
- patch-rc|minor-rc|major-rc: bump base then add -rc.1 (e.g. 0.39.x --minor-rc--> 0.40.0-rc.1).
9+
10+
Writes: Chart.yaml (version, appVersion), values.yaml (image.tag), package.json (version).
11+
Tags use v prefix (workflow adds 'v'). Appends version=... to GITHUB_OUTPUT when set.
912
"""
1013

1114
from __future__ import annotations
@@ -30,8 +33,8 @@ def _read_current(chart_yaml: Path) -> tuple[str, int | None]:
3033

3134

3235
def _next_version(old: str, bump: str, *, rc_num: int | None = None) -> str:
33-
"""Compute next version. old is X.Y.Z or vX.Y.Z. bump: patch|minor|major|rc.
34-
For rc: keeps base, yields X.Y.Z-rc.(N+1) or X.Y.Z-rc.1 if no prior -rc. Otherwise returns X.Y.Z."""
36+
"""Compute next version. old is X.Y.Z or vX.Y.Z. bump: patch|minor|major|rc|patch-rc|minor-rc|major-rc.
37+
For rc: keeps base, X.Y.Z-rc.(N+1) or X.Y.Z-rc.1. For *-rc: bump base then -rc.1."""
3538
b = (bump or "patch").lower()
3639
if b == "rc":
3740
old = old.lstrip("v")
@@ -41,6 +44,11 @@ def _next_version(old: str, bump: str, *, rc_num: int | None = None) -> str:
4144
raise SystemExit(msg)
4245
n = (rc_num + 1) if rc_num is not None else 1
4346
return f"{old}-rc.{n}"
47+
# patch-rc, minor-rc, major-rc: bump base then append -rc.1 (ignore rc_num)
48+
if b in ("patch-rc", "minor-rc", "major-rc"):
49+
base = old.lstrip("v").split("-")[0] # 0.39.0 or 0.39.0 from 0.39.0-rc.2
50+
base = _next_version(base, b.replace("-rc", ""), rc_num=None)
51+
return f"{base}-rc.1"
4452
# patch, minor, major: ignore rc_num
4553
old = old.lstrip("v")
4654
parts = old.split(".")
@@ -57,7 +65,7 @@ def _next_version(old: str, bump: str, *, rc_num: int | None = None) -> str:
5765
x += 1
5866
y = z = 0
5967
else:
60-
msg = f"Unknown bump: {bump}. Use patch, minor, major, or rc."
68+
msg = f"Unknown bump: {bump}. Use patch, minor, major, rc, patch-rc, minor-rc, or major-rc."
6169
raise SystemExit(msg)
6270
return f"{x}.{y}.{z}"
6371

tooling/tests/test_release_bump.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,19 @@ def test_rc_from_clean_version(self) -> None:
7373
assert _next_version("0.39.0", "rc", rc_num=None) == "0.39.0-rc.1"
7474
assert _next_version("1.2.3", "rc") == "1.2.3-rc.1"
7575

76+
def test_minor_rc_from_039x(self) -> None:
77+
assert _next_version("0.39.0", "minor-rc") == "0.40.0-rc.1"
78+
assert _next_version("0.39.1", "minor-rc") == "0.40.0-rc.1"
79+
assert _next_version("0.39.0-rc.2", "minor-rc") == "0.40.0-rc.1"
80+
81+
def test_patch_rc(self) -> None:
82+
assert _next_version("0.39.0", "patch-rc") == "0.39.1-rc.1"
83+
assert _next_version("0.39.0-rc.2", "patch-rc") == "0.39.1-rc.1"
84+
85+
def test_major_rc(self) -> None:
86+
assert _next_version("0.39.0", "major-rc") == "1.0.0-rc.1"
87+
assert _next_version("1.2.3", "major-rc") == "2.0.0-rc.1"
88+
7689

7790
class TestUpdateChartYaml:
7891
def test_updates_version_and_appversion(self, tmp_path: Path) -> None:
@@ -196,3 +209,20 @@ def test_rc_bump_writes_github_output(self, tmp_path: Path) -> None:
196209
rc = run(tmp_path, "rc")
197210
assert rc == 0
198211
assert "version=0.39.0-rc.3\n" in gh_out.read_text()
212+
213+
def test_minor_rc_from_039x_produces_0400_rc1(self, tmp_path: Path) -> None:
214+
chart_dir = tmp_path / "charts" / "gitops-server"
215+
chart_dir.mkdir(parents=True)
216+
(chart_dir / "Chart.yaml").write_text(
217+
'version: 0.39.0-rc.2 # x\nappVersion: "v0.39.0-rc.2"\n'
218+
)
219+
(chart_dir / "values.yaml").write_text('image:\n tag: "v0.39.0-rc.2"\n')
220+
(tmp_path / "package.json").write_text('{"version": "0.39.0-rc.2"}\n')
221+
222+
rc = run(tmp_path, "minor-rc")
223+
224+
assert rc == 0
225+
assert "version: 0.40.0-rc.1" in (chart_dir / "Chart.yaml").read_text()
226+
assert 'appVersion: "v0.40.0-rc.1"' in (chart_dir / "Chart.yaml").read_text()
227+
assert 'tag: "v0.40.0-rc.1"' in (chart_dir / "values.yaml").read_text()
228+
assert '"version": "0.40.0-rc.1"' in (tmp_path / "package.json").read_text()

0 commit comments

Comments
 (0)