Skip to content

Commit 8b099e9

Browse files
authored
feat(action): get-refs-from-pr-body (#1592)
* feat (action): get-pr-body-refs * changeset * fixes * debug * fix: sigscanner response
1 parent baa0f76 commit 8b099e9

22 files changed

Lines changed: 46054 additions & 357 deletions

.changeset/ninety-falcons-shout.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"get-refs-from-pr-body": major
3+
---
4+
5+
feat: initial version

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,4 @@ bin/
5555

5656
# codeql
5757
**/.codeql/**
58+
/.pnpm-store/
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# get-refs-from-pr-body
2+
3+
Extracts per-repo git refs from a PR body, resolves them to concrete commit
4+
SHAs, and verifies each SHA through the internal SigScanner service before
5+
returning them as outputs. Any override that fails validation, resolution, or
6+
signature verification fails the action.
7+
8+
The migration from `tools/scripts/get-refs-from-pr-body.js` preserves the
9+
original PR-body parsing behavior (three chain repos: `core`, `solana`,
10+
`starknet`) and adds SHA resolution + verification.
11+
12+
## What it does
13+
14+
1. Skips silently on non-`pull_request` events, emitting each repo's default ref
15+
so downstream jobs continue to work on `push`, `schedule`, etc.
16+
2. Fetches the PR body for the invoking pull request.
17+
3. For each configured repo (`core`, `solana`, `starknet`):
18+
- If the PR body contains an override (`<name> ref: <value>`):
19+
- Syntactically validates the ref (SHA, semver tag, or branch/tag name).
20+
- Resolves it to a 40-char commit SHA against the target repository via the
21+
GitHub API.
22+
- Verifies that SHA through SigScanner.
23+
- If no override is present, emits the hardcoded default ref (`develop`)
24+
as-is — no resolution or verification, since defaults point at trusted
25+
baseline branches.
26+
4. If every override succeeds, sets an output per repo containing the **resolved
27+
SHA** (or the raw default ref for defaulted repos). If any override fails at
28+
any step, the action fails with a report of every failure.
29+
30+
### Behavior change vs. the old script
31+
32+
The old script wrote the raw ref (e.g. `develop`) to its output. This action
33+
writes the **resolved SHA** for any ref that came from the PR body, so
34+
downstream `actions/checkout` steps pin to the exact commit that was verified —
35+
closing the race where a branch's HEAD can move between validation and checkout.
36+
37+
Defaults are emitted as raw refs (`develop`), unchanged from the old behavior.
38+
This covers all skip paths (non-`pull_request` event, empty PR body, PR body
39+
without any recognized overrides) and also per-repo defaulting (when the PR body
40+
has overrides for some but not all repos).
41+
42+
## Repo configuration
43+
44+
Hardcoded in `src/repo-config.ts`. Add a new entry there to support another
45+
chain repo — no input changes needed.
46+
47+
| Name | PR body pattern | Default | Target repo |
48+
| ---------- | ------------------- | --------- | ------------------------------------- |
49+
| `core` | `core ref: ...` | `develop` | `smartcontractkit/chainlink` |
50+
| `solana` | `solana ref: ...` | `develop` | `smartcontractkit/chainlink-solana` |
51+
| `starknet` | `starknet ref: ...` | `develop` | `smartcontractkit/chainlink-starknet` |
52+
53+
## Inputs
54+
55+
| Name | Required | Default | Description |
56+
| -------------------- | -------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
57+
| `github-token` || `${{ github.token }}` | GitHub token used to fetch the invoking PR body and to resolve refs to SHAs on the target repos. Must have read access to each target repository. |
58+
| `sigscanner-url` ||| SigScanner endpoint URL. Typically an org-wide secret. |
59+
| `sigscanner-api-key` ||| SigScanner API key. Typically an org-wide secret. |
60+
61+
## Outputs
62+
63+
| Name | Description |
64+
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
65+
| `core-ref` | For overrides: resolved and SigScanner-verified commit SHA for `smartcontractkit/chainlink`. When defaulted: the raw default ref (`develop`). |
66+
| `solana-ref` | For overrides: resolved and SigScanner-verified commit SHA for `smartcontractkit/chainlink-solana`. When defaulted: the raw default ref (`develop`). |
67+
| `starknet-ref` | For overrides: resolved and SigScanner-verified commit SHA for `smartcontractkit/chainlink-starknet`. When defaulted: the raw default ref (`develop`). |
68+
69+
## Example usage
70+
71+
```yaml
72+
jobs:
73+
init:
74+
runs-on: ubuntu-latest
75+
outputs:
76+
core-ref: ${{ steps.refs.outputs.core-ref }}
77+
solana-ref: ${{ steps.refs.outputs.solana-ref }}
78+
starknet-ref: ${{ steps.refs.outputs.starknet-ref }}
79+
steps:
80+
- name: Resolve PR body refs
81+
id: refs
82+
uses: smartcontractkit/.github/actions/get-refs-from-pr-body@<sha>
83+
with:
84+
sigscanner-url: ${{ secrets.SIGSCANNER_URL }}
85+
sigscanner-api-key: ${{ secrets.SIGSCANNER_API_KEY }}
86+
87+
build-core:
88+
needs: init
89+
runs-on: ubuntu-latest
90+
steps:
91+
- uses: actions/checkout@v4
92+
with:
93+
repository: smartcontractkit/chainlink
94+
ref: ${{ needs.init.outputs.core-ref }}
95+
```
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: get-refs-from-pr-body
2+
description:
3+
"Extracts per-repo git refs from a PR body, resolves them to SHAs, and
4+
verifies each SHA through SigScanner."
5+
6+
inputs:
7+
github-token:
8+
description:
9+
"GitHub token used to fetch the PR body and resolve refs to SHAs against
10+
the target repositories."
11+
default: ${{ github.token }}
12+
required: true
13+
14+
sigscanner-url:
15+
description: "SigScanner endpoint URL used to verify each resolved commit."
16+
required: true
17+
18+
sigscanner-api-key:
19+
description: "SigScanner API key (org-wide secret)."
20+
required: true
21+
22+
outputs:
23+
core-ref:
24+
description:
25+
"Resolved and verified commit SHA for smartcontractkit/chainlink, or the
26+
default ref when the action is skipped (non-pull_request events)."
27+
28+
solana-ref:
29+
description:
30+
"Resolved and verified commit SHA for smartcontractkit/chainlink-solana,
31+
or the default ref when the action is skipped."
32+
33+
starknet-ref:
34+
description:
35+
"Resolved and verified commit SHA for smartcontractkit/chainlink-starknet,
36+
or the default ref when the action is skipped."
37+
38+
runs:
39+
using: node24
40+
main: "dist/index.js"

0 commit comments

Comments
 (0)