Skip to content

Commit 4afd74a

Browse files
authored
ci: sign commits created by bots (#7397)
The former approaches had downsides such as using the wrong token, creating the commit on the runner, which prevents signing etc. This approach uses the right token and signs the commits server side. That way the github actions will still run and the commits should be signed.
1 parent 313fe22 commit 4afd74a

File tree

2 files changed

+99
-26
lines changed

2 files changed

+99
-26
lines changed

.github/workflows/dependabot-automation.yml

Lines changed: 68 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,9 @@ jobs:
160160
if: github.event.pull_request.user.login == 'dependabot[bot]' && needs.vendor-build.outputs.is_vendor_group == 'true' && needs.vendor-build.outputs.has_changes == 'true'
161161
runs-on: ubuntu-latest
162162
needs: vendor-build
163-
# Security: this job has write permissions but never runs installs/builds.
164-
# It only applies the vetted patch artifact and pushes a single commit.
163+
# Security: this job never runs installs/builds.
164+
# It only applies the vetted patch artifact and writes the update via the GitHub API.
165165
permissions:
166-
contents: write
167166
id-token: write
168167
steps:
169168
- uses: DataDog/dd-octo-sts-action@acaa02eee7e3bb0839e4272dacb37b8f3b58ba80 # v1.0.3
@@ -212,28 +211,77 @@ jobs:
212211
echo "Refusing to proceed: unexpected paths changed."
213212
exit 1
214213
fi
215-
- name: Create commit
216-
id: create-commit
217-
run: |
218-
set -euo pipefail
219-
220-
git config user.name github-actions
221-
git config user.email [email protected]
222-
223-
git add vendor/dist vendor/package.json vendor/yarn.lock
224-
git commit -m "update vendored dependencies with new versions"
225-
echo "commits=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
226-
- name: Push commit
214+
- name: Create verified commit via GitHub API (server-side)
227215
env:
228-
DD_OCTO_STS_TOKEN: ${{ steps.octo-sts.outputs.token }}
229216
TARGET_BRANCH: ${{ github.event.pull_request.head.ref }}
217+
GH_TOKEN: ${{ steps.octo-sts.outputs.token }}
230218
run: |
231219
set -euo pipefail
232220
233-
# Ensure the push is attributed to the octo-sts GitHub App token (not GITHUB_TOKEN),
234-
# so the resulting push triggers CI workflows normally.
235-
auth_header="AUTHORIZATION: basic $(printf 'x-access-token:%s' "$DD_OCTO_STS_TOKEN" | base64 | tr -d '\n')"
236-
git -c "http.https://github.com/.extraheader=$auth_header" push origin "HEAD:$TARGET_BRANCH"
221+
repo="${GITHUB_REPOSITORY}"
222+
expected_head_oid="$(git rev-parse HEAD)"
223+
224+
max_files=200
225+
max_total_bytes=$((10 * 1024 * 1024)) # 10 MiB
226+
227+
mapfile -t changes < <(git diff --name-status)
228+
change_count="${#changes[@]}"
229+
if [ "$change_count" -eq 0 ]; then
230+
echo "No changed files detected."
231+
exit 1
232+
fi
233+
if [ "$change_count" -gt "$max_files" ]; then
234+
echo "Too many changed files ($change_count > $max_files)."
235+
exit 1
236+
fi
237+
238+
additions='[]'
239+
deletions='[]'
240+
total_bytes=0
241+
for change in "${changes[@]}"; do
242+
read -r status path path2 <<<"$change"
243+
244+
if [[ "$status" == D ]]; then
245+
deletions="$(jq -c --arg path "$path" '. + [{path: $path}]' <<<"$deletions")"
246+
continue
247+
fi
248+
249+
# Treat renames as delete+add to keep the server-side tree in sync.
250+
if [[ "$status" == R* ]]; then
251+
deletions="$(jq -c --arg path "$path" '. + [{path: $path}]' <<<"$deletions")"
252+
path="$path2"
253+
fi
254+
255+
test -f "$path"
256+
file_bytes="$(stat -c '%s' "$path")"
257+
total_bytes=$((total_bytes + file_bytes))
258+
if [ "$total_bytes" -gt "$max_total_bytes" ]; then
259+
echo "Total changes too large (${total_bytes} bytes)."
260+
exit 1
261+
fi
262+
contents="$(base64 -w 0 "$path")"
263+
additions="$(jq -c --arg path "$path" --arg contents "$contents" '. + [{path: $path, contents: $contents}]' <<<"$additions")"
264+
done
265+
266+
variables="$(jq -c \
267+
--arg repo "$repo" \
268+
--arg branch "$TARGET_BRANCH" \
269+
--arg msg "update vendored dependencies with new versions" \
270+
--arg expected "$expected_head_oid" \
271+
--argjson additions "$additions" \
272+
--argjson deletions "$deletions" \
273+
'{
274+
input: {
275+
branch: { repositoryNameWithOwner: $repo, branchName: $branch },
276+
message: { headline: $msg },
277+
expectedHeadOid: $expected,
278+
fileChanges: { additions: $additions, deletions: $deletions }
279+
}
280+
}'
281+
)"
282+
283+
query='mutation($input: CreateCommitOnBranchInput!) { createCommitOnBranch(input: $input) { commit { oid url } } }'
284+
gh api graphql -f query="$query" -f variables="$variables" -q '.data.createCommitOnBranch.commit.oid' >/dev/null
237285
238286
# If branch protection is configured to dismiss stale approvals when new commits are pushed,
239287
# the vendoring commit will invalidate the earlier approval. Re-approve and (re-)enable

.github/workflows/update-3rdparty-licenses.yml

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,19 @@ jobs:
99
update-3rdparty-licenses:
1010
runs-on: ubuntu-latest
1111
permissions:
12-
contents: write
12+
contents: read
13+
id-token: write
1314
env:
1415
REPOSITORY_URL: ${{ github.server_url }}/${{ github.repository }}
1516
steps:
17+
- name: Mint GitHub App token (octo-sts) for bot PR updates
18+
if: github.event.pull_request.user.type == 'Bot' && github.event_name == 'pull_request'
19+
uses: DataDog/dd-octo-sts-action@acaa02eee7e3bb0839e4272dacb37b8f3b58ba80 # v1.0.3
20+
id: octo-sts
21+
with:
22+
scope: DataDog/dd-trace-js
23+
policy: update-3rdparty-licenses
24+
1625
- name: Check out PR branch
1726
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
1827

@@ -72,6 +81,7 @@ jobs:
7281
GITHUB_HEAD_REF: ${{ github.head_ref }}
7382
PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
7483
BASE_REPO: ${{ github.repository }}
84+
GH_TOKEN: ${{ steps.octo-sts.outputs.token }}
7585
run: |
7686
set -e
7787
@@ -83,13 +93,28 @@ jobs:
8393
if [[ "$PR_USER_TYPE" == "Bot" ]] && [[ "${GITHUB_EVENT_NAME}" == "pull_request" ]] && [[ "$PR_HEAD_REPO" == "$BASE_REPO" ]]; then
8494
echo "🤖 Bot-created PR detected. Auto-committing LICENSE-3rdparty.csv changes..."
8595
86-
git config --local user.email "[email protected]"
87-
git config --local user.name "GitHub Action"
96+
expected_head_oid="$(git rev-parse HEAD)"
97+
contents="$(base64 -w 0 LICENSE-3rdparty.csv)"
8898
89-
git add LICENSE-3rdparty.csv
90-
git commit -m "Update LICENSE-3rdparty.csv"
99+
variables="$(jq -c \
100+
--arg repo "$GITHUB_REPOSITORY" \
101+
--arg branch "$GITHUB_HEAD_REF" \
102+
--arg msg "Update LICENSE-3rdparty.csv" \
103+
--arg expected "$expected_head_oid" \
104+
--arg path "LICENSE-3rdparty.csv" \
105+
--arg contents "$contents" \
106+
'{
107+
input: {
108+
branch: { repositoryNameWithOwner: $repo, branchName: $branch },
109+
message: { headline: $msg },
110+
expectedHeadOid: $expected,
111+
fileChanges: { additions: [{ path: $path, contents: $contents }] }
112+
}
113+
}'
114+
)"
91115
92-
git push origin HEAD:${GITHUB_HEAD_REF}
116+
query='mutation($input: CreateCommitOnBranchInput!) { createCommitOnBranch(input: $input) { commit { oid url } } }'
117+
gh api graphql -f query="$query" -f variables="$variables" -q '.data.createCommitOnBranch.commit.url' >/dev/null
93118
94119
echo "✅ Successfully committed and pushed LICENSE-3rdparty.csv updates"
95120
else

0 commit comments

Comments
 (0)