Skip to content

Commit 103f7cb

Browse files
dasanraFbartoli
andauthored
feat: add update registry script (safe-global#95)
## Overview Adds script for automating registry additions --------- Co-authored-by: Florent Bartoli <florent.b@safe.global>
1 parent 7f768a8 commit 103f7cb

File tree

4 files changed

+916
-2
lines changed

4 files changed

+916
-2
lines changed
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
name: Update Modules Registry
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
chain_id:
7+
description: 'Chain ID where modules were deployed'
8+
required: true
9+
type: string
10+
module_type:
11+
description: 'Module type'
12+
required: true
13+
type: choice
14+
options:
15+
- allowance
16+
- social-recovery
17+
version:
18+
description: 'Module version (allowance: 0.1.1, social-recovery: 0.1.0)'
19+
required: true
20+
type: choice
21+
options:
22+
- '0.1.0'
23+
- '0.1.1'
24+
contract_address:
25+
description: 'Deployed contract address (0x...)'
26+
required: true
27+
type: string
28+
29+
# Prevent concurrent runs that could cause conflicts
30+
concurrency:
31+
group: update-registry-${{ github.event.inputs.chain_id }}
32+
cancel-in-progress: false
33+
34+
jobs:
35+
update-registry:
36+
name: Update Module Registry
37+
runs-on: ubuntu-latest
38+
timeout-minutes: 15
39+
permissions:
40+
contents: write
41+
pull-requests: write
42+
43+
steps:
44+
- name: Checkout repository
45+
uses: actions/checkout@v4
46+
with:
47+
fetch-depth: 0
48+
49+
- name: Setup pnpm
50+
uses: pnpm/action-setup@v4
51+
with:
52+
version: 9
53+
54+
- name: Setup Node.js
55+
uses: actions/setup-node@v4
56+
with:
57+
node-version: 20.x
58+
cache: pnpm
59+
60+
- name: Install dependencies
61+
run: pnpm install --frozen-lockfile
62+
63+
- name: Validate inputs
64+
env:
65+
CHAIN_ID: ${{ github.event.inputs.chain_id }}
66+
MODULE_TYPE: ${{ github.event.inputs.module_type }}
67+
VERSION: ${{ github.event.inputs.version }}
68+
CONTRACT_ADDRESS: ${{ github.event.inputs.contract_address }}
69+
run: |
70+
# Validate chain_id is numeric only
71+
if ! [[ "$CHAIN_ID" =~ ^[0-9]+$ ]]; then
72+
echo "::error::Invalid chain_id format: must contain only digits"
73+
exit 1
74+
fi
75+
76+
# Validate address format (0x + 40 hex characters)
77+
if ! [[ "$CONTRACT_ADDRESS" =~ ^0x[a-fA-F0-9]{40}$ ]]; then
78+
echo "::error::Invalid contract_address format: must be 0x followed by 40 hexadecimal characters"
79+
exit 1
80+
fi
81+
82+
# Validate version format (X.Y.Z)
83+
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
84+
echo "::error::Invalid version format: must be in X.Y.Z format"
85+
exit 1
86+
fi
87+
88+
- name: Update registry
89+
id: update
90+
env:
91+
CHAIN_ID: ${{ github.event.inputs.chain_id }}
92+
MODULE_TYPE: ${{ github.event.inputs.module_type }}
93+
VERSION: ${{ github.event.inputs.version }}
94+
CONTRACT_ADDRESS: ${{ github.event.inputs.contract_address }}
95+
run: |
96+
pnpm update-registry \
97+
--chain-id "${CHAIN_ID}" \
98+
--module "${MODULE_TYPE}" \
99+
--version "${VERSION}" \
100+
--address "${CONTRACT_ADDRESS}"
101+
102+
- name: Create Pull Request
103+
if: steps.update.outputs.has_changes == 'true'
104+
env:
105+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
106+
CHAIN_ID: ${{ github.event.inputs.chain_id }}
107+
MODULE_TYPE: ${{ github.event.inputs.module_type }}
108+
VERSION: ${{ github.event.inputs.version }}
109+
CONTRACT_ADDRESS: ${{ github.event.inputs.contract_address }}
110+
ASSET_PATH: ${{ steps.update.outputs.asset_path }}
111+
run: |
112+
# Configure git
113+
git config user.name "github-actions[bot]"
114+
git config user.email "github-actions[bot]@users.noreply.github.com"
115+
116+
# Create branch name pattern for searching
117+
BASE_BRANCH_NAME="add-chain-${CHAIN_ID}-${MODULE_TYPE}-v${VERSION}"
118+
119+
# Check if there's already an open PR for this chain/module/version combination
120+
EXISTING_BRANCHES=$(git ls-remote --heads origin "refs/heads/${BASE_BRANCH_NAME}*" | awk '{print $2}' | sed 's|refs/heads/||')
121+
122+
if [ -n "$EXISTING_BRANCHES" ]; then
123+
echo "Found existing branch(es) for this chain/module/version combination."
124+
125+
# Check each branch for open PRs
126+
for branch in $EXISTING_BRANCHES; do
127+
if gh pr list --head "$branch" --state open --json number,url --jq '.[0].number' 2>/dev/null | grep -q '^[0-9]'; then
128+
PR_INFO=$(gh pr list --head "$branch" --state open --json number,url --jq '.[0] | "#\(.number) - \(.url)"')
129+
echo "::notice::Open PR already exists for this deployment: $PR_INFO"
130+
echo "Skipping as changes are already proposed."
131+
exit 0
132+
fi
133+
done
134+
135+
echo "Existing branches found but no open PRs. Proceeding with new branch."
136+
fi
137+
138+
# Always use timestamp to prevent race conditions with parallel runs
139+
BRANCH_NAME="${BASE_BRANCH_NAME}-$(date +%s)"
140+
141+
# Create and switch to new branch
142+
git checkout -b "$BRANCH_NAME"
143+
144+
# Commit changes
145+
git add "$ASSET_PATH"
146+
git commit -m "feat: add chain $CHAIN_ID to $MODULE_TYPE module v$VERSION
147+
148+
- Chain ID: $CHAIN_ID
149+
- Module: $MODULE_TYPE
150+
- Version: $VERSION
151+
- Address: $CONTRACT_ADDRESS
152+
153+
Automated update from deployment-scripts workflow."
154+
155+
# Push branch
156+
git push origin "$BRANCH_NAME"
157+
158+
# Create PR
159+
PR_TITLE="feat: Add chain $CHAIN_ID to $MODULE_TYPE module v$VERSION"
160+
PR_BODY="## Module Registry Update
161+
162+
This PR adds a new chain deployment to the Safe Modules registry.
163+
164+
### Deployment Details
165+
166+
| Property | Value |
167+
|----------|-------|
168+
| **Chain ID** | \`$CHAIN_ID\` |
169+
| **Module** | $MODULE_TYPE |
170+
| **Version** | $VERSION |
171+
| **Address** | \`$CONTRACT_ADDRESS\` |
172+
173+
### Modified Files
174+
175+
- \`$ASSET_PATH\`
176+
177+
---
178+
179+
> 🤖 This PR was automatically created by the deployment-scripts workflow."
180+
181+
# Create PR and capture any errors
182+
if ! PR_OUTPUT=$(gh pr create \
183+
--title "$PR_TITLE" \
184+
--body "$PR_BODY" \
185+
--base main \
186+
--head "$BRANCH_NAME" \
187+
--label "automated" 2>&1); then
188+
echo "::error::Failed to create PR: $PR_OUTPUT"
189+
exit 1
190+
fi
191+
echo "::notice::Successfully created PR for chain $CHAIN_ID"
192+
193+
- name: Summary
194+
if: always()
195+
run: |
196+
echo "## 📦 Module Registry Update Result" >> $GITHUB_STEP_SUMMARY
197+
echo "" >> $GITHUB_STEP_SUMMARY
198+
199+
if [ "${{ steps.update.outputs.has_changes }}" == "true" ]; then
200+
echo "✅ **Changes detected** - PR created to add this deployment to the registry." >> $GITHUB_STEP_SUMMARY
201+
elif [ "${{ steps.update.outputs.action }}" == "unchanged" ]; then
202+
echo "ℹ️ **No changes needed** - chain already registered with same address." >> $GITHUB_STEP_SUMMARY
203+
else
204+
echo "⚠️ **Update completed** - check logs for details." >> $GITHUB_STEP_SUMMARY
205+
fi

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
"build": "rimraf dist && tsc",
1515
"lint": "eslint --max-warnings 0 src/",
1616
"lint:fix": "pnpm run lint --fix",
17-
"prepare": "pnpm run build"
17+
"prepare": "pnpm run build",
18+
"update-registry": "tsx scripts/update-registry.ts"
1819
},
1920
"repository": {
2021
"type": "git",
@@ -36,7 +37,9 @@
3637
"eslint-plugin-prettier": "^5.1.3",
3738
"prettier": "^3.3.2",
3839
"rimraf": "^5.0.7",
40+
"tsx": "^4.7.0",
3941
"typescript": "^5.4.5",
40-
"typescript-eslint": "^7.13.0"
42+
"typescript-eslint": "^7.13.0",
43+
"viem": "^2.44.0"
4144
}
4245
}

0 commit comments

Comments
 (0)