diff --git a/.github/workflows/update-chain-specs.yml b/.github/workflows/update-chain-specs.yml new file mode 100644 index 000000000..ab2a6b8c4 --- /dev/null +++ b/.github/workflows/update-chain-specs.yml @@ -0,0 +1,90 @@ +name: chain-specs-periodic-update + +on: + schedule: + - cron: '0 8 * * *' # every day at 8am + + +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" + ] + fail-fast: false # Don't automatically cancel the jobs of the other RPC nodes if one fails + + steps: + - uses: actions/checkout@v3 + with: + 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 }} | + jq .result > chain_spec.json + - id: get-chain-id # Reads the `id` field in the newly-downloaded chain spec + run: echo "::set-output name=id::`jq -r .id ./chain_spec.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/src/connector/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/public/assets/${{ 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@v3 + 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: + - uses: actions/checkout@v3 + with: + path: repo + ref: main + - uses: actions/download-artifact@v3 + 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@v4 + with: + # We use a custom secret (rather than the default GITHUB_TOKEN) so that opening the pull + # request triggers other actions such as the CI checks. GitHub prevents actions that use + # GITHUB_TOKEN from triggering further actions, to avoid recursive actions. + token: ${{ secrets.GH_TOKEN }} + path: repo + branch: automatic-checkpoints-update + base: main + title: 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. + commit-message: Update checkpoints in chain specifications + delete-branch: true