Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,21 @@ Each entry specifies a contract to validate. The `reference` field controls what
}
```

#### Removing entries

By default, removing a contract from `upgrades.json` is a hard error — without this guard, deletions could silently bypass the upgrade-safety check. To intentionally drop entries (e.g. retiring a contract), set the top-level `"dangerous": true` flag in the same PR:

```json
{
"dangerous": true,
"contracts": [
{ "contract": "src/Greeter.sol:Greeter" }
]
}
```

Removals will be reported as a warning instead. Reset the flag back to `false` (or drop it) in a follow-up PR.

#### 3. Use the workflow

```yaml
Expand Down
38 changes: 28 additions & 10 deletions scripts/upgrade-safety/validate-config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ set -euo pipefail
# Validate that no contracts were removed from the upgrades config compared to the base branch.
# Compares by .contract field only. Prevents bypassing upgrade safety by removing entries.
#
# Set top-level "dangerous": true in upgrades.json to opt out of the removal guard for that PR
# (removals are reported as a warning instead of an error).
#
# Env inputs:
# UPGRADES_CONFIG — required, path to upgrades.json
# BASE_BRANCH — required, branch name to compare against
Expand Down Expand Up @@ -34,6 +37,7 @@ BASE_CONFIG=$(git show "origin/${BASE_BRANCH}:${UPGRADES_CONFIG}") || {

CURRENT_CONTRACTS=$(jq -r '[.contracts[].contract]' "$UPGRADES_CONFIG")
BASE_CONTRACTS=$(echo "$BASE_CONFIG" | jq -r '[.contracts[].contract]')
DANGEROUS=$(jq -r '.dangerous == true' "$UPGRADES_CONFIG")

# Find base branch contracts missing from current config
REMOVED=$(jq -n --argjson base "$BASE_CONTRACTS" --argjson current "$CURRENT_CONTRACTS" \
Expand All @@ -43,16 +47,30 @@ REMOVED_COUNT=$(echo "$REMOVED" | jq 'length')

if [[ "$REMOVED_COUNT" -gt 0 ]]; then
REMOVED_LIST=$(echo "$REMOVED" | jq -r '.[]')
echo "::error::$REMOVED_COUNT contract(s) removed from $UPGRADES_CONFIG compared to base branch ($BASE_BRANCH):"
echo "$REMOVED_LIST"
{
echo "## Upgrade Config Validation"
echo ""
echo "> **Error:** $REMOVED_COUNT contract(s) were removed from \`$UPGRADES_CONFIG\`:"
echo ""
echo "$REMOVED_LIST" | while read -r c; do echo "- \`$c\`"; done
} >> "$GITHUB_STEP_SUMMARY"
exit 1
if [[ "$DANGEROUS" == "true" ]]; then
echo "::warning::$REMOVED_COUNT contract(s) removed from $UPGRADES_CONFIG compared to base branch ($BASE_BRANCH) — allowed by \"dangerous\": true:"
echo "$REMOVED_LIST"
{
echo "## Upgrade Config Validation"
echo ""
echo "> **Warning:** $REMOVED_COUNT contract(s) were removed from \`$UPGRADES_CONFIG\` — allowed by \`\"dangerous\": true\`:"
echo ""
echo "$REMOVED_LIST" | while read -r c; do echo "- \`$c\`"; done
} >> "$GITHUB_STEP_SUMMARY"
else
echo "::error::$REMOVED_COUNT contract(s) removed from $UPGRADES_CONFIG compared to base branch ($BASE_BRANCH):"
echo "$REMOVED_LIST"
{
echo "## Upgrade Config Validation"
echo ""
echo "> **Error:** $REMOVED_COUNT contract(s) were removed from \`$UPGRADES_CONFIG\`:"
echo ""
echo "$REMOVED_LIST" | while read -r c; do echo "- \`$c\`"; done
echo ""
echo "> Set top-level \`\"dangerous\": true\` in \`$UPGRADES_CONFIG\` to allow this removal."
} >> "$GITHUB_STEP_SUMMARY"
exit 1
fi
fi

CURRENT_COUNT=$(echo "$CURRENT_CONTRACTS" | jq 'length')
Expand Down
Loading