Skip to content

Commit 8907591

Browse files
authored
feat: Add rc workflow file (#156)
* feat: Add rc workflow file * fix: Remove commented code * chore: Test changing version * chore: Fix documentation * fix: Netlify toml * chore: Add release wf doc * fix: Comment out status reporting temporarily
1 parent 1e5002b commit 8907591

File tree

22 files changed

+840
-152
lines changed

22 files changed

+840
-152
lines changed

.github/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# CI/CD Release Workflow
2+
3+
---
4+
5+
## Workflows
6+
7+
- To trigger a release, use [rc.yml](workflows/rc.yml) workflow.
8+
- It will need specific commit SHA in long format to start the workflow.
9+
- All the commits until that specific commit sha will be included in the release.
10+
- Checks version from `Cargo.toml` and validates if it needs to creates a new release branch. If there is a release branch that already exists for the same version in `Cargo.toml` the workflow will fail.
11+
- Release branch is created in this pattern `release-v<version>`.
12+
13+
- Second workflow [release-please.yml](workflows/release-please.yml) will get triggered on push to release branch automatically.
14+
- This workflow checks if there is any "higher versioned" branches than the current one since this workflow will be triggered for any pushes ( eg. hotfixes ).
15+
- We use [release-please](https://github.com/googleapis/release-please) for managing releases. If there are no "higher versioned" branches release-please step will be triggered.
16+
- Release please automatically creates a PR with Changelog notes to release branch which keeps track of all commits in that release branch and adds a label `autorelease: pending`. It uses [config](release-please/.config.json) & [manifest](release-please/manifest.json) files to generate changelog and track versions. If there are any changes to `Cargo.lock` that commit is pushed to the PR.
17+
- Once approved merge the PR. On merging `release-please` automatically creates a github release with changelog notes & tags the release with that version.
18+
- Workflow has a step to unlock conversation in the now closed PR so that release-please can post a comment and update the label `autorelease: tagged`.
19+
- SBOM generation, Binaries creation for different arch & Docker build and push jobs are triggered.
20+
21+
- If everything looks good post release, raise a PR and merge the `release-v<version>` branch to main (manual step for now).

.github/actions/prepare/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ runs:
99
using: composite
1010
steps:
1111
- name: setup rust tool chain
12-
uses: dtolnay/rust-toolchain@stable
12+
uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable
1313
with:
1414
toolchain: stable
1515
components: rustfmt, clippy
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
3+
"packages": {
4+
".": {}
5+
},
6+
"release-type": "rust",
7+
"include-component-in-tag": false,
8+
"pull-request-title-pattern": "chore: Release version ${version}",
9+
"pull-request-header": "🤖 Created a Release ⚡ ⚡",
10+
"pull-request-footer": "Merge this pull request to trigger the next release.",
11+
"changelog-sections": [
12+
{
13+
"type": "feat",
14+
"section": "🚀 Features"
15+
},
16+
{
17+
"type": "fix",
18+
"section": "🐛 Bug Fixes"
19+
},
20+
{
21+
"type": "revert",
22+
"section": "◀️ Reverts"
23+
},
24+
{
25+
"type": "docs",
26+
"section": "📚 Documentation",
27+
"hidden": false
28+
},
29+
{
30+
"type": "refactor",
31+
"section": "🚜 Code Refactoring",
32+
"hidden": true
33+
},
34+
{
35+
"type": "style",
36+
"section": "🎨 Styles",
37+
"hidden": true
38+
},
39+
{
40+
"type": "chore",
41+
"section": "⚙️ Miscellaneous Chores",
42+
"hidden": true
43+
},
44+
{
45+
"type": "refactor",
46+
"section": "🚜 Code Refactoring",
47+
"hidden": true
48+
},
49+
{
50+
"type": "test",
51+
"section": "🧪 Tests",
52+
"hidden": true
53+
},
54+
{
55+
"type": "build",
56+
"section": "🛠️ Build System",
57+
"hidden": true
58+
},
59+
{
60+
"type": "ci",
61+
"section": "🥏 Continuous Integration",
62+
"hidden": true
63+
}
64+
]
65+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{".":"0.0.0"}

.github/workflows/ci.yaml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,11 @@ jobs:
186186
path: clippy-results.sarif
187187
retention-days: 1
188188

189-
# TODO: enable this when the repo is made public.
190-
# - name: Upload
191-
# uses: github/codeql-action/upload-sarif@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3
192-
# with:
193-
# sarif_file: clippy-results.sarif
194-
# wait-for-processing: true
189+
- name: Upload
190+
uses: github/codeql-action/upload-sarif@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3
191+
with:
192+
sarif_file: clippy-results.sarif
193+
wait-for-processing: true
195194

196195
# - name: Report status
197196
# run: cargo clippy --all-features --all-targets -- -D warnings --allow deprecated

.github/workflows/cla.yml

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,24 @@ on:
44
issue_comment:
55
types: [created]
66
pull_request_target:
7-
types: [opened, closed, synchronize]
7+
types: [opened, closed, synchronize, labeled]
88

99
permissions:
1010
actions: write
1111
contents: write
1212
pull-requests: write
1313
statuses: write
14+
checks: write
15+
issues: write
1416

1517
jobs:
1618
CLAAssistant:
1719
runs-on: ubuntu-latest
1820
steps:
19-
# TODO: enable when repo is public
20-
# - name: Harden the runner (Audit all outbound calls)
21-
# uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
22-
# with:
23-
# egress-policy: audit
21+
- name: Harden the runner (Audit all outbound calls)
22+
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
23+
with:
24+
egress-policy: audit
2425

2526
- name: Checkout Private Repo for Allowlist
2627
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
@@ -35,7 +36,18 @@ jobs:
3536
run: |
3637
ALLOWLIST=$(cat allowlist.txt)
3738
echo "allowlist=$ALLOWLIST" >> $GITHUB_OUTPUT
39+
- name: Check if user is in allowlist
40+
id: check_allowlist
41+
run: |
42+
PR_USER=${{ github.event.pull_request.user.login }}
43+
if [[ "${{ steps.read_allowlist.outputs.allowlist }}" == *"$PR_USER"* ]]; then
44+
echo "is_allowed=true" >> $GITHUB_OUTPUT
45+
else
46+
echo "is_allowed=false" >> $GITHUB_OUTPUT
47+
fi
3848
- name: CLA Assistant
49+
continue-on-error: true
50+
id: cla_assistant
3951
if: (github.event.comment.body == 'recheck' || github.event.comment.body ==
4052
'I confirm that I have read and hereby agree to the OpenZeppelin Contributor
4153
License Agreement') || github.event_name == 'pull_request_target'
@@ -59,3 +71,73 @@ jobs:
5971
below. Thanks.
6072
custom-pr-sign-comment: I confirm that I have read and hereby agree to the
6173
OpenZeppelin Contributor License Agreement
74+
75+
- name: Label PR as CLA Unsigned
76+
if: ${{ steps.cla_assistant.outcome != 'success' }}
77+
run: |
78+
if [[ "${{ github.event_name }}" == "pull_request_target" ]]; then
79+
PR_NUMBER="${{ github.event.pull_request.number }}"
80+
elif [[ "${{ github.event_name }}" == "issue_comment" ]]; then
81+
PR_NUMBER="${{ github.event.issue.number }}"
82+
fi
83+
ENDPOINT="https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/labels"
84+
curl -L -X POST \
85+
-H "Accept: application/vnd.github+json" \
86+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
87+
-H "X-GitHub-Api-Version: 2022-11-28" \
88+
-d '{"labels":["cla: unsigned"]}' \
89+
$ENDPOINT
90+
exit 1
91+
92+
- name: Label PR as CLA Signed
93+
if: ${{ steps.cla_assistant.outcome == 'success' && steps.check_allowlist.outputs.is_allowed
94+
== 'false' }}
95+
run: |-
96+
if [[ "${{ github.event_name }}" == "pull_request_target" ]]; then
97+
PR_NUMBER="${{ github.event.pull_request.number }}"
98+
elif [[ "${{ github.event_name }}" == "issue_comment" ]]; then
99+
PR_NUMBER="${{ github.event.issue.number }}"
100+
fi
101+
ENDPOINT="https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/labels"
102+
# Remove 'cla: unsigned' label if present
103+
curl -L -X DELETE \
104+
-H "Accept: application/vnd.github+json" \
105+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
106+
-H "X-GitHub-Api-Version: 2022-11-28" \
107+
"$ENDPOINT/cla:%20unsigned" || true
108+
# Add 'cla: signed' label
109+
curl -L -X POST \
110+
-H "Accept: application/vnd.github+json" \
111+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
112+
-H "X-GitHub-Api-Version: 2022-11-28" \
113+
-d '{"labels":["cla: signed"]}' \
114+
$ENDPOINT
115+
116+
- name: Label PR as CLA Allowlist
117+
if: ${{ steps.check_allowlist.outputs.is_allowed == 'true' }}
118+
run: |-
119+
if [[ "${{ github.event_name }}" == "pull_request_target" ]]; then
120+
PR_NUMBER="${{ github.event.pull_request.number }}"
121+
elif [[ "${{ github.event_name }}" == "issue_comment" ]]; then
122+
PR_NUMBER="${{ github.event.issue.number }}"
123+
fi
124+
ENDPOINT="https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/labels"
125+
# Remove 'cla: unsigned' label if present
126+
curl -L -X DELETE \
127+
-H "Accept: application/vnd.github+json" \
128+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
129+
-H "X-GitHub-Api-Version: 2022-11-28" \
130+
"$ENDPOINT/cla:%20unsigned" || true
131+
# Remove 'cla: signed' label if present
132+
curl -L -X DELETE \
133+
-H "Accept: application/vnd.github+json" \
134+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
135+
-H "X-GitHub-Api-Version: 2022-11-28" \
136+
"$ENDPOINT/cla:%20signed" || true
137+
# Add allowlist label
138+
curl -L -X POST \
139+
-H "Accept: application/vnd.github+json" \
140+
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
141+
-H "X-GitHub-Api-Version: 2022-11-28" \
142+
-d '{"labels":["cla: allowlist"]}' \
143+
$ENDPOINT

.github/workflows/rc.yml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
---
2+
name: RC for Major/Minor Releases
3+
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
commit_sha:
8+
description: Commit SHA to create release branch from
9+
required: true
10+
type: string
11+
12+
permissions:
13+
contents: write
14+
pull-requests: write
15+
16+
17+
# run concurrency group for the workflow
18+
concurrency:
19+
group: ${{ github.workflow }}-${{ github.ref }}
20+
cancel-in-progress: false
21+
22+
jobs:
23+
create-release-branch:
24+
runs-on: ubuntu-latest
25+
steps:
26+
- uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1.11.7
27+
id: gh-app-token
28+
with:
29+
app-id: ${{ vars.GH_APP_ID }}
30+
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
31+
32+
- name: Validate Commit SHA
33+
run: |
34+
if [[ ! "$INPUT_COMMIT_SHA" =~ ^[0-9a-f]{40}$ ]]; then
35+
echo "Invalid commit SHA: $INPUT_COMMIT_SHA. Please provide the full 40-character SHA."
36+
echo "Provided SHA: $INPUT_COMMIT_SHA"
37+
echo "Length: ${#$INPUT_COMMIT_SHA}"
38+
exit 1
39+
fi
40+
echo "Valid commit SHA: $INPUT_COMMIT_SHA"
41+
env:
42+
INPUT_COMMIT_SHA: ${{ github.event.inputs.commit_sha }}
43+
44+
- name: Checkout repository at commit SHA
45+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
46+
with:
47+
ref: ${{ github.event.inputs.commit_sha }}
48+
fetch-depth: 0
49+
token: ${{ steps.gh-app-token.outputs.token }}
50+
51+
- name: Get version from Cargo.toml
52+
id: get_version
53+
run: |
54+
# Extract the version from Cargo.toml
55+
version=$(grep -A 5 "\[package\]" Cargo.toml | grep "^version" | cut -d'"' -f2)
56+
if [ -z "$version" ]; then
57+
echo "Version not found in Cargo.toml" >&2
58+
exit 1
59+
fi
60+
echo "Version is $version"
61+
echo "version=$version" >> $GITHUB_OUTPUT
62+
63+
- name: Set release branch name
64+
id: set_branch
65+
run: |
66+
branch="release-v${{ steps.get_version.outputs.version }}"
67+
echo "release_branch=$branch" >> $GITHUB_ENV
68+
echo "Release branch will be: $branch"
69+
70+
- name: Check if release branch exists
71+
id: check_branch
72+
run: |
73+
branch="release-v${{ steps.get_version.outputs.version }}"
74+
if git ls-remote --exit-code --heads origin "$branch" > /dev/null 2>&1; then
75+
echo "exists=true" >> $GITHUB_OUTPUT
76+
else
77+
echo "exists=false" >> $GITHUB_OUTPUT
78+
fi
79+
80+
- name: Create release branch
81+
id: update_branch
82+
shell: bash
83+
run: |-
84+
branch="release-v${{ steps.get_version.outputs.version }}"
85+
commit_sha="${{ github.event.inputs.commit_sha }}"
86+
if [ "${{ steps.check_branch.outputs.exists }}" == "true" ]; then
87+
echo "Branch '$branch' already exists. Exiting with error."
88+
exit 1
89+
else
90+
echo "Branch '$branch' does not exist. Creating new branch from commit $commit_sha."
91+
git checkout -b $branch $commit_sha
92+
git push -f origin $branch
93+
fi

0 commit comments

Comments
 (0)