Skip to content

Commit 4bf16f4

Browse files
Merge pull request #516 from DataDog/refactor/release-pr-based
refactor(ci): switch release flow to PR-based bump with API-created tag
2 parents 537a928 + 148f26b commit 4bf16f4

4 files changed

Lines changed: 135 additions & 28 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Policy for: .github/workflows/release-tag.yml in DataDog/pup
2+
issuer: https://token.actions.githubusercontent.com
3+
subject: repo:DataDog/pup:pull_request
4+
5+
claim_pattern:
6+
event_name: pull_request
7+
job_workflow_ref: DataDog/pup/\.github/workflows/release-tag\.yml@refs/pull/[0-9]+/merge
8+
ref: refs/pull/[0-9]+/merge
9+
repository: DataDog/pup
10+
11+
permissions:
12+
contents: write

.github/chainguard/release.sts.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Policy for: .github/workflows/release-prepare.yml in DataDog/pup
22
issuer: https://token.actions.githubusercontent.com
3-
subject: repo:DataDog/pup:environment:release
3+
subject: repo:DataDog/pup:ref:refs/heads/main
44

55
claim_pattern:
66
event_name: schedule|workflow_dispatch
@@ -10,3 +10,4 @@ claim_pattern:
1010

1111
permissions:
1212
contents: write
13+
pull_requests: write

.github/workflows/release-prepare.yml

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,15 @@ jobs:
4848
fi
4949
5050
# ---------------------------------------------------------------------------
51-
# Release: bump, commit to main, tag. Triggers release.yml via the tag push.
51+
# Release: bump Cargo.toml/Cargo.lock on a release/<tag> branch and open a PR.
52+
# Merging the PR triggers release-tag.yml, which creates the tag and triggers
53+
# release.yml.
5254
# ---------------------------------------------------------------------------
5355
release:
54-
name: Bump, Commit, Tag
56+
name: Open Release PR
5557
needs: check
5658
if: needs.check.outputs.proceed == 'true'
5759
runs-on: ubuntu-latest
58-
environment: release
5960
steps:
6061
- uses: DataDog/dd-octo-sts-action@96a25462dbcb10ebf0bfd6e2ccc917d2ab235b9a # v1.0.4
6162
id: octo-sts
@@ -66,7 +67,6 @@ jobs:
6667
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
6768
with:
6869
fetch-depth: 0
69-
token: ${{ steps.octo-sts.outputs.token }}
7070

7171
- name: Compute next version
7272
id: version
@@ -82,19 +82,28 @@ jobs:
8282
esac
8383
NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
8484
NEW_TAG="v${NEW_VERSION}"
85+
BRANCH="release/${NEW_TAG}"
8586
echo "current-tag=${CURRENT_TAG}" >> "$GITHUB_OUTPUT"
8687
echo "new-version=${NEW_VERSION}" >> "$GITHUB_OUTPUT"
8788
echo "new-tag=${NEW_TAG}" >> "$GITHUB_OUTPUT"
89+
echo "branch=${BRANCH}" >> "$GITHUB_OUTPUT"
8890
echo "Current: ${CURRENT_TAG}"
8991
echo "Next: ${NEW_TAG} (${BUMP} bump)"
9092
9193
- name: Preflight check
94+
env:
95+
GH_TOKEN: ${{ steps.octo-sts.outputs.token }}
96+
NEW_TAG: ${{ steps.version.outputs.new-tag }}
97+
BRANCH: ${{ steps.version.outputs.branch }}
9298
run: |
93-
NEW_TAG="${{ steps.version.outputs.new-tag }}"
9499
if git tag -l "$NEW_TAG" | grep -q .; then
95100
echo "::error::Tag '${NEW_TAG}' already exists."
96101
exit 1
97102
fi
103+
if gh api "repos/${GITHUB_REPOSITORY}/git/refs/heads/${BRANCH}" >/dev/null 2>&1; then
104+
echo "::error::Branch '${BRANCH}' already exists."
105+
exit 1
106+
fi
98107
99108
- name: Install Rust
100109
run: |
@@ -126,26 +135,66 @@ jobs:
126135
- name: Refresh Cargo.lock
127136
run: cargo check --quiet 2>&1 | grep -v "^$" || true
128137

129-
- name: Commit to main and tag
138+
- name: Create release branch via API (signed commit)
139+
id: commit
140+
env:
141+
GH_TOKEN: ${{ steps.octo-sts.outputs.token }}
142+
NEW_TAG: ${{ steps.version.outputs.new-tag }}
143+
CURRENT_TAG: ${{ steps.version.outputs.current-tag }}
144+
NEW_VERSION: ${{ steps.version.outputs.new-version }}
145+
BRANCH: ${{ steps.version.outputs.branch }}
130146
run: |
131-
NEW_TAG="${{ steps.version.outputs.new-tag }}"
132-
CURRENT_TAG="${{ steps.version.outputs.current-tag }}"
133-
NEW_VERSION="${{ steps.version.outputs.new-version }}"
134-
135-
git config user.name "dd-octo-sts[bot]"
136-
git config user.email "dd-octo-sts[bot]@users.noreply.github.com"
137-
138-
git add Cargo.toml Cargo.lock
139-
git commit -m "$(cat <<EOF
140-
chore(release): bump version to ${NEW_TAG}
141-
142-
- Update Cargo.toml package version ${CURRENT_TAG#v} → ${NEW_VERSION}
143-
- Refresh Cargo.lock
144-
EOF
145-
)"
146-
147-
git push origin main
148-
149-
git tag -a "$NEW_TAG" -m "$NEW_TAG"
150-
git push origin "$NEW_TAG"
151-
echo "Tagged and pushed ${NEW_TAG}"
147+
set -euo pipefail
148+
REPO="${GITHUB_REPOSITORY}"
149+
150+
BASE_SHA=$(gh api "repos/${REPO}/git/refs/heads/main" --jq .object.sha)
151+
BASE_TREE=$(gh api "repos/${REPO}/git/commits/${BASE_SHA}" --jq .tree.sha)
152+
153+
CARGO_TOML_BLOB=$(jq -n --rawfile c Cargo.toml '{content: $c, encoding: "utf-8"}' \
154+
| gh api "repos/${REPO}/git/blobs" --input - --jq .sha)
155+
CARGO_LOCK_BLOB=$(jq -n --rawfile c Cargo.lock '{content: $c, encoding: "utf-8"}' \
156+
| gh api "repos/${REPO}/git/blobs" --input - --jq .sha)
157+
158+
TREE_SHA=$(jq -n \
159+
--arg base "${BASE_TREE}" \
160+
--arg toml "${CARGO_TOML_BLOB}" \
161+
--arg lock "${CARGO_LOCK_BLOB}" \
162+
'{
163+
base_tree: $base,
164+
tree: [
165+
{path: "Cargo.toml", mode: "100644", type: "blob", sha: $toml},
166+
{path: "Cargo.lock", mode: "100644", type: "blob", sha: $lock}
167+
]
168+
}' | gh api "repos/${REPO}/git/trees" --input - --jq .sha)
169+
170+
MESSAGE=$(printf 'chore(release): bump version to %s\n\n- Update Cargo.toml package version %s → %s\n- Refresh Cargo.lock' \
171+
"${NEW_TAG}" "${CURRENT_TAG#v}" "${NEW_VERSION}")
172+
173+
COMMIT_SHA=$(jq -n \
174+
--arg msg "${MESSAGE}" \
175+
--arg tree "${TREE_SHA}" \
176+
--arg parent "${BASE_SHA}" \
177+
'{message: $msg, tree: $tree, parents: [$parent]}' \
178+
| gh api "repos/${REPO}/git/commits" --input - --jq .sha)
179+
180+
gh api "repos/${REPO}/git/refs" \
181+
-f ref="refs/heads/${BRANCH}" \
182+
-f sha="${COMMIT_SHA}"
183+
184+
echo "commit-sha=${COMMIT_SHA}" >> "$GITHUB_OUTPUT"
185+
echo "Created signed commit ${COMMIT_SHA} on ${BRANCH}"
186+
187+
- name: Open Release PR
188+
env:
189+
GH_TOKEN: ${{ steps.octo-sts.outputs.token }}
190+
NEW_TAG: ${{ steps.version.outputs.new-tag }}
191+
CURRENT_TAG: ${{ steps.version.outputs.current-tag }}
192+
BRANCH: ${{ steps.version.outputs.branch }}
193+
run: |
194+
BODY=$(printf 'Automated version bump from %s to %s.\n\nMerging this PR triggers `release-tag.yml`, which creates the `%s` tag and in turn triggers `release.yml` (goreleaser).' \
195+
"${CURRENT_TAG}" "${NEW_TAG}" "${NEW_TAG}")
196+
gh pr create \
197+
--base main \
198+
--head "${BRANCH}" \
199+
--title "chore(release): bump version to ${NEW_TAG}" \
200+
--body "${BODY}"

.github/workflows/release-tag.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Tag Release
2+
3+
on:
4+
pull_request:
5+
types: [closed]
6+
7+
permissions:
8+
id-token: write
9+
contents: read
10+
11+
jobs:
12+
tag:
13+
name: Create release tag
14+
if: >
15+
github.event.pull_request.merged == true &&
16+
startsWith(github.event.pull_request.head.ref, 'release/') &&
17+
github.event.pull_request.head.repo.full_name == github.repository
18+
runs-on: ubuntu-latest
19+
steps:
20+
- uses: DataDog/dd-octo-sts-action@96a25462dbcb10ebf0bfd6e2ccc917d2ab235b9a # v1.0.4
21+
id: octo-sts
22+
with:
23+
scope: datadog/pup
24+
policy: release-tag
25+
26+
- name: Create tag
27+
env:
28+
GH_TOKEN: ${{ steps.octo-sts.outputs.token }}
29+
HEAD_REF: ${{ github.event.pull_request.head.ref }}
30+
MERGE_SHA: ${{ github.event.pull_request.merge_commit_sha }}
31+
run: |
32+
set -euo pipefail
33+
TAG_NAME="${HEAD_REF#release/}"
34+
if [[ ! "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
35+
echo "::error::Invalid tag name '${TAG_NAME}' derived from head_ref '${HEAD_REF}'"
36+
exit 1
37+
fi
38+
if gh api "repos/${GITHUB_REPOSITORY}/git/refs/tags/${TAG_NAME}" >/dev/null 2>&1; then
39+
echo "::error::Tag '${TAG_NAME}' already exists."
40+
exit 1
41+
fi
42+
gh api "repos/${GITHUB_REPOSITORY}/git/refs" \
43+
-f ref="refs/tags/${TAG_NAME}" \
44+
-f sha="${MERGE_SHA}"
45+
echo "Created tag ${TAG_NAME} → ${MERGE_SHA}"

0 commit comments

Comments
 (0)