Skip to content

Commit 4ef554f

Browse files
Merge branch 'main' of github.com:smartcontractkit/cre-sdk-typescript into feat/no-excess
2 parents ce50c4f + d1c5893 commit 4ef554f

10 files changed

Lines changed: 654 additions & 4 deletions

File tree

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Template Compatibility Comment
2+
3+
# Triggered when the unprivileged "Template Compatibility Check" workflow
4+
# completes. This workflow has pull-requests: write so it can post PR comments.
5+
# It checks out the default branch (only) to load scripts/template-compatibility-comment.js,
6+
# then reads the artifact produced by the check workflow.
7+
#
8+
# SECURITY: workflow_run always runs on the default branch, so this workflow
9+
# definition and checked-out script cannot be tampered with by a PR contributor.
10+
# Artifact contents are treated as untrusted strings and sanitized before use.
11+
12+
on:
13+
workflow_run:
14+
workflows: ["Template Compatibility Check"]
15+
types: [completed]
16+
17+
permissions:
18+
contents: read
19+
pull-requests: write
20+
actions: read # required to download artifacts from another workflow run
21+
22+
jobs:
23+
post-comment:
24+
runs-on: ubuntu-latest
25+
26+
steps:
27+
- name: Checkout repository
28+
uses: actions/checkout@v6
29+
30+
- name: Download results artifact
31+
uses: actions/download-artifact@v8
32+
with:
33+
name: template-compat-results
34+
path: /tmp/compat-results
35+
run-id: ${{ github.event.workflow_run.id }}
36+
github-token: ${{ secrets.GITHUB_TOKEN }}
37+
38+
- name: Post or remove PR comment
39+
uses: actions/github-script@v8
40+
with:
41+
script: |
42+
const path = require('path');
43+
const run = require(path.join(process.env.GITHUB_WORKSPACE, 'scripts', 'template-compatibility-comment.js'));
44+
await run({ github, context });
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
name: Template Compatibility Check
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
7+
concurrency:
8+
group: template-compat-${{ github.head_ref || github.ref }}
9+
cancel-in-progress: true
10+
11+
# This job is informational — it is intentionally NOT a required status check
12+
# so that breaking SDK changes (major version bumps) can still be merged.
13+
# When templates break, a comment is posted on the PR with details.
14+
# For intentional breaking changes, create a matching branch in cre-templates
15+
# named compat/<your-sdk-branch-name> with the template fixes applied.
16+
# The job will automatically detect and test against that branch.
17+
18+
permissions:
19+
contents: read
20+
21+
jobs:
22+
template-compatibility:
23+
runs-on: ubuntu-latest
24+
timeout-minutes: 20
25+
26+
defaults:
27+
run:
28+
shell: bash {0}
29+
30+
env:
31+
TEMPLATES_REPO: smartcontractkit/cre-templates
32+
33+
steps:
34+
- name: Checkout SDK
35+
uses: actions/checkout@v6
36+
with:
37+
submodules: recursive
38+
39+
- name: Setup Rust (1.85.0) with wasm target
40+
uses: actions-rust-lang/setup-rust-toolchain@150fca883cd4034361b621bd4e6a9d34e5143606 # v1.15.4
41+
with:
42+
toolchain: 1.85.0
43+
target: wasm32-wasip1
44+
override: true
45+
46+
- name: Setup Bun
47+
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
48+
with:
49+
bun-version: 1.3.12
50+
51+
- name: Cache Bun dependencies
52+
uses: actions/cache@v5
53+
with:
54+
path: ~/.bun/install/cache
55+
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }}
56+
57+
- name: Cache cargo + Javy
58+
uses: actions/cache@v5
59+
with:
60+
path: |
61+
~/.cargo/registry
62+
~/.cargo/git
63+
~/.cache/javy
64+
key: ${{ runner.os }}-cre-plugin-v8.1.0-${{ hashFiles('packages/cre-sdk-javy-plugin/src/javy_chainlink_sdk/Cargo.lock', 'packages/cre-sdk-javy-plugin/src/cre_generated_host.Cargo.lock') }}
65+
66+
- name: Install SDK dependencies
67+
run: bun install --frozen-lockfile
68+
69+
# Detect whether a matching compat branch exists in cre-templates.
70+
# If it does, we test against it (coordinated breaking change).
71+
# If not, we fall back to main.
72+
- name: Detect cre-templates ref to test against
73+
id: detect-ref
74+
env:
75+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
76+
HEAD_REF: ${{ github.head_ref }}
77+
run: |
78+
SAFE_HEAD_REF="${HEAD_REF//[^a-zA-Z0-9._\/-]/}"
79+
COMPAT_BRANCH="compat/$SAFE_HEAD_REF"
80+
81+
if gh api "repos/$TEMPLATES_REPO/branches/$COMPAT_BRANCH" &>/dev/null; then
82+
echo "ref=$COMPAT_BRANCH" >> "$GITHUB_OUTPUT"
83+
echo "Using compat branch: $COMPAT_BRANCH"
84+
else
85+
echo "ref=main" >> "$GITHUB_OUTPUT"
86+
echo "No compat branch found, using: main"
87+
fi
88+
89+
- name: Checkout cre-templates (${{ steps.detect-ref.outputs.ref }})
90+
uses: actions/checkout@v6
91+
with:
92+
repository: ${{ env.TEMPLATES_REPO }}
93+
ref: ${{ steps.detect-ref.outputs.ref }}
94+
path: cre-templates
95+
token: ${{ secrets.GITHUB_TOKEN }}
96+
97+
- name: Setup Node (for npm)
98+
uses: actions/setup-node@v6
99+
with:
100+
node-version: '24'
101+
102+
- name: Run template compatibility check
103+
id: template-check
104+
env:
105+
TEMPLATES_DIR: cre-templates
106+
run: |
107+
set +e
108+
OUTPUT=$(./scripts/test-templates.sh 2>&1)
109+
EXIT_CODE=$?
110+
set -e
111+
112+
echo "$OUTPUT" > /tmp/template-check-output.txt
113+
114+
# Surface it in the action log regardless
115+
echo "$OUTPUT"
116+
117+
echo "exit_code=$EXIT_CODE" >> "$GITHUB_OUTPUT"
118+
119+
# Bundle everything the comment workflow needs into an artifact.
120+
# The comment workflow runs with pull-requests: write but must never
121+
# execute external code — it only reads these files.
122+
- name: Save results for comment workflow
123+
if: always()
124+
env:
125+
PR_NUMBER: ${{ github.event.pull_request.number }}
126+
TEMPLATES_REF: ${{ steps.detect-ref.outputs.ref }}
127+
HEAD_REF: ${{ github.head_ref }}
128+
EXIT_CODE: ${{ steps.template-check.outputs.exit_code }}
129+
run: |
130+
mkdir -p /tmp/compat-results
131+
printf '%s' "$PR_NUMBER" > /tmp/compat-results/pr-number.txt
132+
printf '%s' "$TEMPLATES_REF" > /tmp/compat-results/templates-ref.txt
133+
printf '%s' "$HEAD_REF" > /tmp/compat-results/head-ref.txt
134+
printf '%s' "$EXIT_CODE" > /tmp/compat-results/exit-code.txt
135+
if [ -f /tmp/template-check-output.txt ]; then
136+
cp /tmp/template-check-output.txt /tmp/compat-results/output.txt
137+
fi
138+
139+
- name: Upload results artifact
140+
if: always()
141+
uses: actions/upload-artifact@v7
142+
with:
143+
name: template-compat-results
144+
path: /tmp/compat-results/
145+
retention-days: 7
146+
147+
# Always exit 0 — this job is informational, not a merge gate
148+
- name: Report result (non-blocking)
149+
if: always()
150+
run: |
151+
EXIT_CODE="${{ steps.template-check.outputs.exit_code }}"
152+
if [ "$EXIT_CODE" = "0" ]; then
153+
echo "✅ All templates are compatible with this SDK change."
154+
else
155+
echo "⚠️ Some templates failed — see PR comment for details."
156+
echo "This check is informational and does not block merging."
157+
fi
158+
exit 0

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"check:ci": "turbo run check:ci",
1515
"format": "turbo run format",
1616
"full-checks": "./scripts/full-checks.sh",
17+
"test:templates": "./scripts/test-templates.sh",
1718
"lint": "turbo run lint",
1819
"typecheck": "turbo run typecheck"
1920
},

packages/cre-sdk-examples/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@chainlink/cre-sdk-examples",
33
"private": true,
4-
"version": "1.7.0",
4+
"version": "1.8.0",
55
"type": "module",
66
"author": "Ernest Nowacki",
77
"license": "BUSL-1.1",

packages/cre-sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@chainlink/cre-sdk",
3-
"version": "1.7.0",
3+
"version": "1.8.0",
44
"type": "module",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

packages/cre-sdk/src/generated-sdk/capabilities/blockchain/evm/v1alpha/client_sdk_gen.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,16 @@ export class ClientCapability {
123123

124124
/** Available ChainSelector values */
125125
static readonly SUPPORTED_CHAIN_SELECTORS = {
126+
'adi-mainnet': 4059281736450291836n,
127+
'adi-testnet': 9418205736192840573n,
126128
'apechain-testnet-curtis': 9900119385908781505n,
127129
'arc-testnet': 3034092155422581607n,
128130
'avalanche-mainnet': 6433500567565415381n,
129131
'avalanche-testnet-fuji': 14767482510784806043n,
130132
'binance_smart_chain-mainnet': 11344663589394136015n,
131133
'binance_smart_chain-testnet': 13264668187771770619n,
132134
'celo-mainnet': 1346049177634351622n,
135+
'celo-sepolia': 3761762704474186180n,
133136
'cronos-testnet': 2995292832068775165n,
134137
'dtcc-testnet-andesite': 15513093881969820114n,
135138
'ethereum-mainnet': 5009297550715157269n,

packages/cre-sdk/src/generated/capabilities/blockchain/evm/v1alpha/client_pb.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/**
2+
* Used by .github/workflows/template-compatibility-comment.yml.
3+
* Reads /tmp/compat-results from the prior workflow's artifact and posts or
4+
* removes a PR comment via the GitHub API.
5+
*/
6+
module.exports = async ({ github, context }) => {
7+
const fs = require('fs');
8+
9+
const read = (filename) => {
10+
try {
11+
return fs.readFileSync(`/tmp/compat-results/${filename}`, 'utf8').trim();
12+
} catch {
13+
return '';
14+
}
15+
};
16+
17+
// Validate PR number — must be a positive integer.
18+
const prNumber = parseInt(read('pr-number.txt'), 10);
19+
if (!Number.isInteger(prNumber) || prNumber <= 0) {
20+
console.log('Invalid or missing PR number in artifact; skipping comment.');
21+
return;
22+
}
23+
24+
const exitCode = read('exit-code.txt');
25+
const fullOutput = read('output.txt');
26+
// Sanitize values read from the artifact before embedding in markdown
27+
// to prevent injection (e.g. a malicious branch name or script output
28+
// containing markdown syntax that escapes a code fence).
29+
const templatesRef = read('templates-ref.txt').replace(/[^a-zA-Z0-9._\/-]/g, '');
30+
const headRef = read('head-ref.txt').replace(/[^a-zA-Z0-9._\/-]/g, '');
31+
32+
const marker = '<!-- template-compat-comment -->';
33+
34+
const { data: comments } = await github.rest.issues.listComments({
35+
owner: context.repo.owner,
36+
repo: context.repo.repo,
37+
issue_number: prNumber,
38+
});
39+
const existing = comments.find((c) => c.body.includes(marker));
40+
41+
if (exitCode === '0') {
42+
// Templates pass — remove any stale failure comment.
43+
if (existing) {
44+
await github.rest.issues.deleteComment({
45+
owner: context.repo.owner,
46+
repo: context.repo.repo,
47+
comment_id: existing.id,
48+
});
49+
}
50+
return;
51+
}
52+
53+
// Extract just the "Results" and "Failure Details" sections from output.
54+
const resultsMatch = fullOutput.match(/={8,}\nResults:.*\n={8,}[\s\S]*/);
55+
const failureSummary = resultsMatch ? resultsMatch[0].trim() : fullOutput.trim();
56+
57+
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.payload.workflow_run.id}`;
58+
const refNote =
59+
templatesRef === 'main'
60+
? 'tested against `cre-templates:main`'
61+
: `tested against \`cre-templates:${templatesRef}\` (compat branch)`;
62+
63+
const body = [
64+
'## ⚠️ Template Compatibility Failures',
65+
'',
66+
`This PR breaks one or more templates in [cre-templates](https://github.com/smartcontractkit/cre-templates) (${refNote}).`,
67+
'',
68+
'```',
69+
failureSummary,
70+
'```',
71+
'',
72+
`[View full output →](${runUrl})`,
73+
'',
74+
'<details>',
75+
'<summary>What should I do?</summary>',
76+
'',
77+
'- **Accidental break:** Fix the SDK change so existing templates continue to compile.',
78+
`- **Intentional breaking change:** Create a branch in \`cre-templates\` named \`compat/${headRef}\` with the template fixes applied. This job will automatically retest against that branch.`,
79+
'',
80+
'</details>',
81+
].join('\n');
82+
83+
const commentBody = `${marker}\n${body}`;
84+
85+
if (existing) {
86+
await github.rest.issues.updateComment({
87+
owner: context.repo.owner,
88+
repo: context.repo.repo,
89+
comment_id: existing.id,
90+
body: commentBody,
91+
});
92+
} else {
93+
await github.rest.issues.createComment({
94+
owner: context.repo.owner,
95+
repo: context.repo.repo,
96+
issue_number: prNumber,
97+
body: commentBody,
98+
});
99+
}
100+
};

0 commit comments

Comments
 (0)