Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ci): carve out storage layout CI #127

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
7db6013
feat(ci): carve out storage layout CI
MaxMustermann2 Nov 27, 2024
f84c3a1
fix(ci): update status fast
MaxMustermann2 Nov 27, 2024
7d5a4b4
feat(ci): carve out storage layout CI
MaxMustermann2 Nov 27, 2024
c05fca0
respond to AI comments
MaxMustermann2 Nov 27, 2024
ee19085
Merge branch 'feat/storage-layout-check'
MaxMustermann2 Nov 27, 2024
dd628db
respond to more AI comments
MaxMustermann2 Nov 27, 2024
0dd8655
Merge branch 'feat/storage-layout-check'
MaxMustermann2 Nov 27, 2024
1ff0aa2
error out if expected files do not exist
MaxMustermann2 Nov 27, 2024
3b78803
fix(ci): escape the params
MaxMustermann2 Nov 27, 2024
c38e6c7
Merge branch 'feat/storage-layout-check'
MaxMustermann2 Nov 27, 2024
0510384
fix(ci): fail faster if the parent job failed
MaxMustermann2 Nov 27, 2024
1f202c2
Merge branch 'feat/storage-layout-check'
MaxMustermann2 Nov 27, 2024
b0e4314
rename input for clarity
MaxMustermann2 Nov 27, 2024
78ba65c
Merge branch 'feat/storage-layout-check'
MaxMustermann2 Nov 27, 2024
8e26760
do not set the key unless required
MaxMustermann2 Nov 27, 2024
6ca132c
Merge branch 'feat/storage-layout-check'
MaxMustermann2 Nov 27, 2024
65a4656
use not condition instead of == false
MaxMustermann2 Nov 27, 2024
66bc71c
Merge branch 'feat/storage-layout-check'
MaxMustermann2 Nov 27, 2024
1b9c587
remove superfluous comment
MaxMustermann2 Nov 27, 2024
aadac30
fix(ci): add timeout
MaxMustermann2 Nov 27, 2024
a667b0b
Merge branch 'feat/storage-layout-check'
MaxMustermann2 Nov 27, 2024
081a143
feat(forge-ci): parallelize layout extraction
MaxMustermann2 Nov 27, 2024
56c71cd
fix(ci): use artifacts with different names
MaxMustermann2 Nov 27, 2024
df267d6
fix(ci): flatten combination correctly
MaxMustermann2 Nov 27, 2024
8bf4f1c
split deployed layout job to parallel
MaxMustermann2 Nov 27, 2024
5ed62a2
fix(ci): make matrix single line output
MaxMustermann2 Nov 27, 2024
7164340
fix(ci): download current run artifact
MaxMustermann2 Nov 27, 2024
93a0a13
fix(ci): remove debug
MaxMustermann2 Nov 27, 2024
3866fc9
fix(ci): always create matrix
MaxMustermann2 Nov 27, 2024
491ecba
fix(ci): update job timeouts
MaxMustermann2 Nov 27, 2024
99bb116
fix(ci): respond to AI comments
MaxMustermann2 Nov 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 244 additions & 0 deletions .github/workflows/compare-layouts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
name: Compare Storage Layouts

on:
workflow_run:
workflows: ["Forge CI"]
types:
- completed

permissions:
contents: read
statuses: write
pull-requests: write

jobs:
# The cache storage in the reusable foundry setup takes far too long.
# Do this job first to update the commit status and comment ASAP.
set-commit-status:
runs-on: ubuntu-latest
outputs:
number: ${{ steps.pr-context.outputs.number }}
steps:
- name: Set commit status
# trigger is no matter what, because the status should be updated
if: always()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# this step would have been better located in forge-ci.yml, but since it needs the secret
# it is placed here. first, it is updated to pending here and failure/success is updated later.
run: |
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
-d '{
"state": "pending",
"context": "Compare Storage Layouts",
"description": "In progress...",
"target_url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
}' \
https://api.github.com/repos/${{ github.repository }}/statuses/${{ github.event.workflow_run.head_commit.id }}
MaxMustermann2 marked this conversation as resolved.
Show resolved Hide resolved
- name: Get PR number
id: pr-context
if: ${{ github.event.workflow_run.event == 'pull_request' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_TARGET_REPO: ${{ github.repository }}
PR_BRANCH: |-
${{
(github.event.workflow_run.head_repository.owner.login != github.event.workflow_run.repository.owner.login)
&& format('{0}:{1}', github.event.workflow_run.head_repository.owner.login, github.event.workflow_run.head_branch)
|| github.event.workflow_run.head_branch
}}
run: |
pr_number=$(gh pr view --repo "${PR_TARGET_REPO}" "${PR_BRANCH}" \
--json 'number' --jq '.number')
if [ -z "$pr_number" ]; then
echo "Error: PR number not found for branch '${PR_BRANCH}' in repository '${PR_TARGET_REPO}'" >&2
exit 1
fi
echo "number=$pr_number" >> "${GITHUB_OUTPUT}"
- name: Set message
id: set-message
env:
WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
WORKFLOW_NAME: ${{ github.workflow }}
SHA: ${{ github.event.workflow_run.head_commit.id }}
run: |
message="🚀 The $WORKFLOW_NAME workflow has started."
echo "message=$message Check the [workflow run]($WORKFLOW_URL) for progress. ($SHA)" >> "${GITHUB_OUTPUT}"
- name: Update CI Status
uses: marocchino/sticky-pull-request-comment@v2
if: ${{ github.event.workflow_run.event == 'pull_request' }}
with:
header: ${{ github.workflow }}
hide_details: true
number: ${{ steps.pr-context.outputs.number }}
message: ${{ steps.set-message.outputs.message }}

setup:
# A full job can be used as a reusable workflow but not a step.
uses: ./.github/workflows/reusable-foundry-setup.yml
with:
# The below line does not accept environment variables,
# so it becomes the single source of truth for the version, within this workflow.
# Any `pinning` of the version should be done here and forge-ci.yml.
foundry-version: nightly
MaxMustermann2 marked this conversation as resolved.
Show resolved Hide resolved

# The actual job to compare the storage layouts.
compare-storage-layouts:
needs:
- setup
- set-commit-status
runs-on: ubuntu-latest

env:
ALCHEMY_API_KEY: ${{ secrets.ALCHEMY_API_KEY }}
ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

steps:
# Log the workflow trigger details for debugging.
- name: Echo workflow trigger details
run: |
echo "Workflow run event: ${{ github.event.workflow_run.event }}"
echo "Workflow run conclusion: ${{ github.event.workflow_run.conclusion }}"
echo "Workflow run name: ${{ github.event.workflow_run.name }}"
echo "Workflow run URL: ${{ github.event.workflow_run.html_url }}"
echo "Commit SHA: ${{ github.event.workflow_run.head_commit.id }}"
echo "Workflow Run ID: ${{ github.event.workflow_run.id }}"
# The repository needs to be available for script/deployedContracts.json
# and script/compareLayouts.js. We do not restore the build data because
# the compiled layouts are restored from the artifact and not rebuilt.
- name: Checkout the repository
if: ${{ github.event.workflow_run.conclusion == 'success' }}
uses: actions/checkout@v4
# The toolchain is needed to run `cast storage`
- name: Restore cached Foundry toolchain
if: ${{ github.event.workflow_run.conclusion == 'success' }}
uses: actions/cache/restore@v3
with:
path: ${{ needs.setup.outputs.installation-dir }}
key: ${{ needs.setup.outputs.cache-key }}
- name: Add Foundry to PATH
if: ${{ github.event.workflow_run.conclusion == 'success' }}
run: echo "${{ needs.setup.outputs.installation-dir }}" >> "$GITHUB_PATH"
- name: Fetch the deployed layouts
MaxMustermann2 marked this conversation as resolved.
Show resolved Hide resolved
if: ${{ github.event.workflow_run.conclusion == 'success' }}
run: |
set -e
data=$(cat script/deployedContracts.json)
bootstrap=$(echo "$data" | jq -r '.clientChain.bootstrapLogic // empty')
clientGateway=$(echo "$data" | jq -r '.clientChain.clientGatewayLogic // empty')
vault=$(echo "$data" | jq -r '.clientChain.vaultImplementation // empty')
rewardVault=$(echo "$data" | jq -r '.clientChain.rewardVaultImplementation // empty')
capsule=$(echo "$data" | jq -r '.clientChain.capsuleImplementation // empty')
pwd=$(pwd)
cd /tmp
# Create an array of contract names and addresses
declare -A contracts=(
["Bootstrap"]="$bootstrap"
["ClientChainGateway"]="$clientGateway"
["Vault"]="$vault"
["RewardVault"]="$rewardVault"
["ExoCapsule"]="$capsule"
)
# Iterate over the array and run `cast storage` for each contract
for contract in "${!contracts[@]}"; do
address=${contracts[$contract]}
if [[ -n $address ]]; then
echo "Processing $contract at address $address"
cast storage --json "$address" --rpc-url "https://eth-sepolia.g.alchemy.com/v2/$ALCHEMY_API_KEY" \
--etherscan-api-key "$ETHERSCAN_API_KEY" > "$contract.deployed.json"
MaxMustermann2 marked this conversation as resolved.
Show resolved Hide resolved
mv "$contract.deployed.json" "$pwd"
else
echo "Skipping $contract as no address is provided"
fi
done
cd "$pwd"
# Restore the layouts from the previous job
MaxMustermann2 marked this conversation as resolved.
Show resolved Hide resolved
- name: Restore the layout files from the artifact
if: ${{ github.event.workflow_run.conclusion == 'success' }}
uses: dawidd6/action-download-artifact@v6
with:
name: storage-layouts-${{ github.event.workflow_run.head_commit.id }}
run_id: ${{ github.event.workflow_run.id }}
- name: Extract the restored layouts
if: ${{ github.event.workflow_run.conclusion == 'success' }}
run: unzip storage-layouts.zip
- name: Set up Node.js
if: ${{ github.event.workflow_run.conclusion == 'success' }}
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Clear npm cache
if: ${{ github.event.workflow_run.conclusion == 'success' }}
run: npm cache clean --force
- name: Install the required dependency
if: ${{ github.event.workflow_run.conclusion == 'success' }}
run: npm install @openzeppelin/upgrades-core
- name: Compare the layouts
if: ${{ github.event.workflow_run.conclusion == 'success' }}
id: compare-layouts
run: |
node script/compareLayouts.js
# Even if this fails, the CI status should be updated.
continue-on-error: true
- name: Update parent commit status
if: always()
# if the outcome is not set, it will post failure
run: |
outcome=$(
[[ "${{ steps.compare-layouts.outcome }}" == "success" ]] &&
echo "success" ||
echo "failure"
)
description=$(
[[ "${{ steps.compare-layouts.outcome }}" == "success" ]] &&
echo "Storage layouts match" ||
([[ "${{ steps.compare-layouts.outcome }}" == "failure" ]] &&
echo "Storage layouts do not match" ||
echo "Job skipped since ${{ github.event.workflow_run.name }} failed.")
)
MaxMustermann2 marked this conversation as resolved.
Show resolved Hide resolved
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
-d "{
\"state\": \"${outcome}\",
\"context\": \"Compare Storage Layouts\",
\"description\": \"${description}\",
\"target_url\": \"https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\"
}" \
https://api.github.com/repos/${{ github.repository }}/statuses/${{ github.event.workflow_run.head_commit.id }}
- name: Set message again
id: set-message-again
env:
WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
WORKFLOW_NAME: ${{ github.workflow }}
SHA: ${{ github.event.workflow_run.head_commit.id }}
run: |
if [ ${{ steps.compare-layouts.outcome }} == "success" ]; then
message="✅ The $WORKFLOW_NAME workflow has completed successfully."
elif [ ${{ steps.compare-layouts.outcome }} == "failure" ]; then
message="❌ The $WORKFLOW_NAME workflow has failed!"
else
message="⏭ The $WORKFLOW_NAME workflow was skipped."
fi
echo "message=$message Check the [workflow run]($WORKFLOW_URL) for details. ($SHA)" >> "${GITHUB_OUTPUT}"
- name: Update CI Status
uses: marocchino/sticky-pull-request-comment@v2
if: ${{ github.event.workflow_run.event == 'pull_request' }}
with:
header: ${{ github.workflow }}
hide_details: true
number: ${{ needs.set-commit-status.outputs.number }}
message: ${{ steps.set-message-again.outputs.message }}
- name: Exit with the correct code
if: always()
# if the outcome is not set, it will exit 1. so, a failure in the parent job will
# result in a failure here.
run: |
if [[ "${{ steps.compare-layouts.outcome }}" == "success" ]]; then
exit 0
else
exit 1
fi
87 changes: 0 additions & 87 deletions .github/workflows/compare_deployed_storage_layout.py

This file was deleted.

Loading
Loading