git action added to bypass PRs #1011
Workflow file for this run
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
# - Github Version Control Checker | |
# - Watches changes on version-controlled contracts and makes sure that versions are bumped in case of relevant changes: | |
# - Relevant changes == anything except for changes of license identifier, solidity pragma of pure comment changes | |
# - watched paths: src/* | |
# - will check all modified or new contracts in watched paths | |
# - will fail if a new contract was added to watched paths without contract version | |
# - will fail if an existing contract was modified but version was not updated | |
# - will update the PR title to contain all contract names and their new versions (watched paths only) | |
name: Version Control Checker | |
on: | |
pull_request: | |
types: [opened, edited, synchronize, review_requested, ready_for_review] | |
jobs: | |
check-version: | |
# will only run once the PR is in "Ready for Review" state | |
if: ${{ github.event.pull_request.draft == false }} | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 ##### Fetch all history for all branches | |
- name: Get list of modified files by this PR | |
id: modified_files | |
run: | | |
BASE_REF="${{ github.event.pull_request.base.ref }}" | |
##### get all files modified by this PR | |
FILES=$(git diff --name-only origin/${BASE_REF} HEAD) | |
##### make sure that there are modified files | |
if [[ -z $FILES ]]; then | |
echo -e "\033[31mNo files found. This should not happen. Please check the code of the Github action\033[0m" | |
exit 1 | |
fi | |
##### Initialize empty variables | |
CONTRACTS="" | |
##### go through all file paths and identify all files in src/ folder (version control is only active in this folder) | |
while IFS= read -r FILE; do | |
if echo "$FILE" | grep -E '^src/.*\.sol$'; then | |
CONTRACTS="${CONTRACTS}${FILE}"$'\n' | |
fi | |
done <<< "$FILES" | |
##### if none found, exit here as there is nothing to do | |
if [[ -z "$CONTRACTS" ]]; then | |
echo -e "\033[32mNo version-controlled contracts found in files modified/added by this PR.\033[0m" | |
echo -e "\033[32mNo further checks are required.\033[0m" | |
# set action output to false | |
echo "CONTINUE=false" >> $GITHUB_ENV | |
exit 0 | |
else | |
# set action output to true | |
echo "CONTINUE=true" >> $GITHUB_ENV | |
fi | |
##### Write filenames to temporary files (using variables here was causing issues due to the file names) | |
echo -e "$CONTRACTS" > modified_contracts.txt | |
- name: Verify version updates on modified contracts | |
id: verify_version_changes | |
if: env.CONTINUE == 'true' | |
run: | | |
##### Read tmp file into variable | |
CONTRACTS=$(cat modified_contracts.txt) | |
##### Initialize variables | |
MISSING_VERSION_TAG=() | |
MISSING_VERSION_UPDATE=() | |
UPDATED_CONTRACTS=() | |
echo "--------------------" | |
##### Process each file separately | |
while IFS= read -r FILE; do | |
echo "Now checking contract: $FILE" | |
VERSION_TAG=$(grep -E '^/// @custom:version' "$FILE" || true) | |
VERSION=$(echo "$VERSION_TAG" | sed -E 's/^\/\/\/ @custom:version ([0-9]+\.[0-9]+\.[0-9]+).*$/\1/' || true) | |
##### Extract the filename without extension | |
FILENAME=$(basename "$FILE" .sol) | |
##### Check if a version tag exists in the contract file | |
if [[ -z "$VERSION_TAG" ]]; then | |
echo -e "\033[31mFile does not contain a version tag\033[0m" | |
MISSING_VERSION_TAG+=("$FILE") | |
else | |
echo -e "\033[32mFile contains a custom:version tag\033[0m" | |
##### get all changes of the current file/contract | |
DIFF_OUTPUT=$(git diff origin/${{ github.event.pull_request.base.ref }} HEAD "$FILE") | |
##### Check if the version was updated in this PR | |
if echo "$DIFF_OUTPUT" | grep -qE '^\+/// @custom:version'; then | |
echo -e "\033[32mFile version was updated in this PR to version $VERSION\033[0m" | |
NEW_VERSION=$(echo "$VERSION_TAG" | awk '{print $NF}') | |
TARGET_STRING="${FILENAME} v${NEW_VERSION}" | |
UPDATED_CONTRACTS+=("$TARGET_STRING") | |
else | |
##### Check if changes are relevant (ignore comments, formatting, pragma, license changes) | |
if echo "$DIFF_OUTPUT" | grep -qE '^\+\/\/\/|^\+pragma|^\+// SPDX-License-Identifier:'; then | |
echo -e "\033[32mChange is non-relevant (comments/formatting/pragma/license). No version update required.\033[0m" | |
else | |
##### add to files with missing version updates | |
echo -e "\033[31mThe file changed but the file version was not updated\033[0m" | |
MISSING_VERSION_UPDATE+=("$FILE") | |
fi | |
fi | |
fi | |
echo "--------------------" | |
done <<< "$CONTRACTS" | |
##### If any contract files are missing a version tag, this must be corrected before continuing | |
if [[ ${#MISSING_VERSION_TAG[@]} -ne 0 ]]; then | |
echo "--------------------" | |
echo ">>>>>>" | |
echo -e "\033[31mThe following files are missing a custom:version tag in their code:\033[0m" | |
echo "${MISSING_VERSION_TAG[*]}" | |
echo -e "\033[31mEvery version-controlled contract needs to have a custom:version tag in its code.\033[0m" | |
echo -e "\033[31mThis Github action cannot complete until these issues are solved.\033[0m" | |
exit 1 | |
fi | |
##### if the version was not updated in any of the changed contracts, store the list of affected files in a tmp file | |
if [[ ${#MISSING_VERSION_UPDATE[@]} -ne 0 ]]; then | |
echo "--------------------" | |
echo ">>>>>>" | |
echo -e "\033[31mThe following contract(s) have been modified but their version tags were not updated:\033[0m" | |
echo "${MISSING_VERSION_UPDATE[*]}" | |
echo -e "\033[31mPlease make sure to update a contract's version whenever there are changes in the file.\033[0m" | |
echo -e "\033[31mThis Github action cannot complete until these issues are solved.\033[0m" | |
echo "" | |
exit 1 | |
fi | |
##### store any contracts that were correctly updated in a tmp file so we can check the PR title after for each of those | |
if [[ ${#UPDATED_CONTRACTS[@]} -ne 0 ]]; then | |
##### create a string from the array with all contracts | |
UPDATED_CONTRACTS_STR=$(IFS=,; echo "${UPDATED_CONTRACTS[*]}") | |
echo "UPDATED_CONTRACTS=$UPDATED_CONTRACTS_STR" >> $GITHUB_ENV | |
echo -e "${UPDATED_CONTRACTS_STR[*]}" > updated_contracts.txt | |
else | |
echo -e "\033[32mDid not find any contracts for which version control is activated.\033[0m" | |
echo -e "\033[32mNo further checks are required.\033[0m" | |
echo "CONTINUE=false" >> $GITHUB_ENV | |
exit 0 | |
fi | |
- name: Compose updated PR title | |
env: | |
PR_TITLE: ${{ github.event.pull_request.title }} | |
run: | | |
##### Read tmp files into variables | |
if [ -f updated_contracts.txt ]; then | |
UPDATED_CONTRACTS=$(cat updated_contracts.txt) | |
else | |
UPDATED_CONTRACTS="" | |
fi | |
echo "UPDATED CONTRACTS: $UPDATED_CONTRACTS" | |
##### Step 1: Remove everything in and including brackets from the current title | |
BASE_TITLE=$(echo "$PR_TITLE" | sed 's/\s*\[.*$//') | |
echo "BASE_TITLE: $BASE_TITLE" | |
##### Step 2: Trim whitespace from the base title | |
BASE_TITLE="$(echo -e "${BASE_TITLE}" | sed 's/[[:space:]]*$//')" | |
##### Step 3: Construct the new title if there are updated contracts | |
if [[ -n "$UPDATED_CONTRACTS" ]]; then | |
# Create new title with updated contracts | |
PR_TITLE_UPDATED="${BASE_TITLE} [${UPDATED_CONTRACTS}]" | |
else | |
# If no updated contracts, keep the title as the base title | |
PR_TITLE_UPDATED="$BASE_TITLE" | |
fi | |
##### Step 4: Trim whitespace from the updated title | |
PR_TITLE_UPDATED="$(echo -e "${PR_TITLE_UPDATED}" | sed 's/[[:space:]]*$//')" | |
##### Step 5: Log current and new titles and check if an update is needed | |
echo "Current PR Title: '$PR_TITLE'" | |
echo "New PR Title: '$PR_TITLE_UPDATED'" | |
if [[ "$PR_TITLE" != "$PR_TITLE_UPDATED" ]]; then | |
echo "Updating PR title from '$PR_TITLE' to '$PR_TITLE_UPDATED'." | |
echo "PR_TITLE_UPDATED=$PR_TITLE_UPDATED" >> $GITHUB_ENV | |
echo "CONTINUE=true" >> $GITHUB_ENV | |
else | |
echo -e "\033[32mNo PR title updates are required. This Github action will end here.\033[0m" | |
echo "CONTINUE=false" >> $GITHUB_ENV | |
exit 0 | |
fi | |
- name: Update the PR title on GitHub | |
if: env.CONTINUE == 'true' | |
env: | |
GH_PAT: ${{ secrets.GIT_ACTIONS_BOT_PAT_CLASSIC }} | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
PR_TITLE_UPDATED: ${{ env.PR_TITLE_UPDATED }} | |
run: | | |
##### unset the default git token (does not have sufficient rights to perform the update) | |
unset GITHUB_TOKEN | |
##### use the Personal Access Token to log into git CLI | |
echo $GH_PAT | gh auth login --with-token | |
if ! echo $GH_PAT | gh auth login --with-token; then | |
echo -e "\033[31mFailed to authenticate with GitHub. Git action cannot continue\033[0m" | |
exit 1 | |
fi | |
##### update the PR title | |
if ! gh pr edit ${{ github.event.pull_request.number }} --title "${{ env.PR_TITLE_UPDATED }}"; then | |
echo "::error::Failed to update PR title" | |
echo -e "\033[31mFailed to update PR title. Git action cannot continue\033[0m" | |
exit 1 | |
fi |