chain-specs-periodic-update #1044
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: chain-specs-periodic-update | |
on: | |
schedule: | |
- cron: '0 8 * * *' # every day at 8am | |
workflow_dispatch: # allow triggering through the UI | |
jobs: | |
download-spec: | |
runs-on: ubuntu-latest | |
strategy: | |
matrix: | |
# This starts one parallel job for each of these addresses. | |
rpc-node-address: [ | |
"wss://rpc.polkadot.io", | |
"wss://kusama-rpc.polkadot.io", | |
"wss://westend-rpc.polkadot.io", | |
"wss://rococo-rpc.polkadot.io", | |
"wss://rpc.dotters.network/paseo" | |
] | |
fail-fast: false # Don't automatically cancel the jobs of the other RPC nodes if one fails | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
persist-credentials: false | |
path: repo | |
ref: main | |
- run: | | |
curl -L -O https://github.com/vi/websocat/releases/download/v1.9.0/websocat_linux64 | |
chmod +x websocat_linux64 | |
- run: | | |
echo '{"id":1,"jsonrpc":"2.0","method":"sync_state_genSyncSpec","params":[true]}' | | |
./websocat_linux64 -n1 -B 99999999 ${{ matrix.rpc-node-address }} > rpc_answer.json | |
- run: cat ./rpc_answer.json | jq .result > chain_spec.json | |
- id: get-chain-id # Reads the `id` field in the newly-downloaded chain spec | |
run: echo "id=`jq -r .id ./chain_spec.json`" >> $GITHUB_OUTPUT | |
- if: ${{ steps.get-chain-id.outputs.id == '' }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: failed-response-${{ github.run_id }} | |
path: | | |
rpc_answer.json | |
- run: | # Overwrite the `lightSyncState` field of the existing chain spec with the value of spec that's been downloaded. | |
tmp=$(mktemp) | |
output=./repo/packages/connect-known-chains/specs/${{ steps.get-chain-id.outputs.id }}.json | |
jq --slurpfile downloaded ./chain_spec.json '.lightSyncState = $downloaded[0].lightSyncState' "$output" > "$tmp" | |
mv "$tmp" "$output" | |
- run: | # Do the same as the previous step, but for the chain spec of the extension. This is done separately in case the spec is not the same with the one in `connect` | |
tmp=$(mktemp) | |
output=./repo/projects/extension/assets/chainspecs/${{ steps.get-chain-id.outputs.id }}.json | |
jq --slurpfile downloaded ./chain_spec.json '.lightSyncState = $downloaded[0].lightSyncState' "$output" > "$tmp" | |
mv "$tmp" "$output" | |
- run: | # Do the same as the previous step, but for the chain spec of the extension. This is done separately in case the spec is not the same with the one in `connect` | |
tmp=$(mktemp) | |
output=./repo/projects/wallet-template/assets/chainspecs/${{ steps.get-chain-id.outputs.id }}.json | |
jq --slurpfile downloaded ./chain_spec.json '.lightSyncState = $downloaded[0].lightSyncState' "$output" > "$tmp" | |
mv "$tmp" "$output" | |
- uses: actions/upload-artifact@v4 | |
with: | |
name: chain-spec-${{ steps.get-chain-id.outputs.id }} | |
# Note that passing `repo/**` maintains paths under `repo`. This is a bit of magic by the upload-artifact action. | |
path: | | |
repo/**/${{ steps.get-chain-id.outputs.id }}.json | |
create-pr: | |
runs-on: ubuntu-latest | |
if: ${{ always() }} # Run this job even if one of the steps of download-spec has failed | |
needs: download-spec | |
steps: | |
- name: Generate a token | |
id: gen_token | |
uses: actions/create-github-app-token@v1 | |
with: | |
app-id: ${{ secrets.SUBSTRATE_CONNECT_PR_APP_ID }} | |
private-key: ${{ secrets.SUBSTRATE_CONNECT_PR_APP_KEY }} | |
owner: ${{ github.repository_owner }} | |
- uses: actions/[email protected] | |
with: | |
path: repo | |
ref: main | |
- uses: actions/download-artifact@v4 | |
with: | |
# Since we're not passing a name, this automatically downloads *all* artifacts | |
# Unfortunately, this creates intermediary directories. | |
path: . | |
- run: cp -r ./chain-spec-*/* ./repo | |
- uses: peter-evans/create-pull-request@v6 | |
id: create-pr | |
with: | |
token: ${{ steps.gen_token.outputs.token }} | |
committer: CICD team <[email protected]> | |
author: CICD team <[email protected]> | |
path: repo | |
branch: automatic-checkpoints-update | |
base: main | |
title: "chore: update checkpoints in chain specifications" | |
# Note that the `download-spec` job above fails if the downloaded specification doesn't | |
# correspond to an existing file. It is therefore impossible that the pull request | |
# accidentally adds new specifications. | |
body: > | |
This pull request has been automatically generated by downloading chain | |
specifications from various JSON-RPC endpoints and extracting their checkpoints. | |
Keep in mind that introducing a malicious checkpoint can redirect users to the wrong | |
chain. If this pull request looks suspicious, please be cautious. | |
labels: "automerge" | |
commit-message: "chore: update checkpoints in chain specifications" | |
delete-branch: true | |
- name: Check PR creation status | |
if: steps.create-pr.outcome != 'success' | |
run: | | |
echo "Failed to create pull request" | |
exit 1 | |
- name: Create issue on failure | |
if: failure() | |
uses: actions/github-script@v7 | |
with: | |
github-token: ${{ steps.gen_token.outputs.token }} | |
script: | | |
github.rest.issues.create({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
title: 'Failed to create pull request for updating chain specifications', | |
body: 'The create-pr step failed in the chain-specs-periodic-update workflow. Please investigate the issue.', | |
labels: ['bug'] | |
}) |