Skip to content

Commit

Permalink
[TT-1326] Update Solidty Foundry pipeline with Slither (smartcontract…
Browse files Browse the repository at this point in the history
…kit#13986)

* More univeral lcov prunning

* update Shared code cov

* exclude deleted files from Slither

* use single source of truth for all Solidity Foundry jobs

* fix json

* compact output with jq

* fix condition for fmt

* try to scope tests to changes

* move matrix check to step level

* fix outputs path

* trigger

* test with Automation change

* try with shared

* run fmt also if any sol files were modified

* fix job name in collect metrics

* trigger pipeline only for localised change + update changes info

* add changeset

* remove test change

* do not run forge fmt if shared contracts have changed

* try artifact pipeline by hijacking hardhat

* # This is a combination of 2 commits.
# This is the 1st commit message:

CR changes + test them

# This is the commit message #2:

use shell array

* CR changes + test them

use shell array

init array

CR changes + test them

use shell array

init array

* remove test files

* do not run Slither for test files

* do not run fmt if test files were modified

* remove unused config file

* restore old Hardhat pipeline

* add missing transmission setup

* fix basic info condition, join 2 steps into 1, define higher-level coverage exclusions

* define actions for installing Slither and solc-select

* run all tests also if package.json changes; run them on all non_src changes

* add action for validating whether all Slither reports and UML diagrams were generated

* fetch origin in validation action

* compare with HEAD in validate action

* compare with origin in validation action

* handle both csv and shell arrays in the validation action

* update artifact pipeline with new actions

* fix workflow after tests

* fix how validation actions works with commits

* treat shared as any other product

* small fixes

* apply CR changes

* remove special handling for deleted files

* remove apt-get update

* use only dorny/paths

* remove unused input

* CR changes: use dorny/paths with quantifier, move scope validation to an action, remove whitespaces

* fix workflow

* fail bash scripts on erors

* add set -euo pipefail to bash scripts

* define action to detect foundry version

* fix select solc version script, better slither report output

* checkout repo

* add id
  • Loading branch information
Tofel authored Aug 9, 2024
1 parent 98b9054 commit 4b91691
Show file tree
Hide file tree
Showing 18 changed files with 1,354 additions and 85 deletions.
26 changes: 26 additions & 0 deletions .github/actions/detect-solidity-foundry-version/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: 'Detect Foundry version in GNUmakefile'
description: 'Detects Foundry version in GNUmakefile'
inputs:
working-directory:
description: 'The GNUmakefile directory'
required: false
default: 'contracts'
outputs:
foundry-version:
description: 'Foundry version found in GNUmakefile'
value: ${{ steps.extract-foundry-version.outputs.foundry-version }}
runs:
using: 'composite'
steps:
- name: Extract Foundry version
id: extract-foundry-version
shell: bash
working-directory: ${{ inputs.working-directory }}
run: |
foundry_version=$(grep -Eo "foundryup --version [^ ]+" GNUmakefile | awk '{print $3}')
if [ -z "$foundry_version" ]; then
echo "::error::Foundry version not found in GNUmakefile"
exit 1
fi
echo "Foundry version found: $foundry_version"
echo "foundry-version=$foundry_version" >> $GITHUB_OUTPUT
10 changes: 10 additions & 0 deletions .github/actions/setup-slither/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: Setup Slither
description: Installs Slither 0.10.3 for contract analysis. Requires Python 3.6 or higher.
runs:
using: composite
steps:
- name: Install Slither
shell: bash
run: |
python -m pip install --upgrade pip
pip install slither-analyzer==0.10.3
30 changes: 30 additions & 0 deletions .github/actions/setup-solc-select/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Setup Solc Select
description: Installs Solc Select, required versions and selects the version to use. Requires Python 3.6 or higher.
inputs:
to_install:
description: Comma-separated list of solc versions to install
required: true
to_use:
description: Solc version to use
required: true

runs:
using: composite
steps:
- name: Install solc-select and solc
shell: bash
run: |
pip3 install solc-select
sudo ln -s /usr/local/bin/solc-select /usr/bin/solc-select
IFS=',' read -ra versions <<< "${{ inputs.to_install }}"
for version in "${versions[@]}"; do
solc-select install $version
if [ $? -ne 0 ]; then
echo "Failed to install Solc $version"
exit 1
fi
done
solc-select install ${{ inputs.to_use }}
solc-select use ${{ inputs.to_use }}
103 changes: 103 additions & 0 deletions .github/actions/validate-artifact-scope/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: Validate Artifact Scope
description: Checks there are any modified Solidity files outside of the specified scope. If so, it prints a warning message, but does not fail the workflow.
inputs:
product:
description: The product for which the artifacts are being generated
required: true
sol_files:
description: Comma-separated (CSV) or space-separated (shell) list of Solidity files to check
required: true

runs:
using: composite
steps:
- name: Transform input array
id: transform_input_array
shell: bash
run: |
is_csv_format() {
local input="$1"
if [[ "$input" =~ "," ]]; then
return 0
else
return 1
fi
}
is_space_separated_string() {
local input="$1"
if [[ "$input" =~ ^[^[:space:]]+([[:space:]][^[:space:]]+)*$ ]]; then
return 0
else
return 1
fi
}
array="${{ inputs.sol_files }}"
if is_csv_format "$array"; then
echo "::debug::CSV format detected, nothing to do"
echo "sol_files=$array" >> $GITHUB_OUTPUT
exit 0
fi
if is_space_separated_string "$array"; then
echo "::debug::Space-separated format detected, converting to CSV"
csv_array="${array// /,}"
echo "sol_files=$csv_array" >> $GITHUB_OUTPUT
exit 0
fi
echo "::error::Invalid input format for sol_files. Please provide a comma-separated (CSV) or space-separated (shell) list of Solidity files"
exit 1
- name: Check for changes outside of artifact scope
shell: bash
run: |
echo "::debug::All modified contracts:"
echo "${{ steps.transform_input_array.outputs.sol_files }}" | tr ',' '\n'
if [ "${{ inputs.product }}" = "shared" ]; then
excluded_paths_pattern="!/^contracts\/src\/v0\.8\/interfaces/ && !/^contracts\/src\/v0\.8\/${{ inputs.product }}/ && !/^contracts\/src\/v0\.8\/[^\/]+\.sol$/"
else
excluded_paths_pattern="!/^contracts\/src\/v0\.8\/${{ inputs.product }}/"
fi
echo "::debug::Excluded paths: $excluded_paths_pattern"
unexpected_files=$(echo "${{ steps.transform_input_array.outputs.sol_files }}" | tr ',' '\n' | awk "$excluded_paths_pattern")
missing_files=""
set -e
set -o pipefail
if [[ -n "$unexpected_files" ]]; then
products=()
productsStr=""
IFS=$'\n' read -r -d '' -a files <<< "$unexpected_files" || true
echo "Files: ${files[@]}"
for file in "${files[@]}"; do
missing_files+="$file,"
product=$(echo "$file" | awk -F'src/v0.8/' '{if ($2 ~ /\//) print substr($2, 1, index($2, "/")-1); else print "shared"}')
if [[ ! " ${products[@]} " =~ " ${product} " ]]; then
products+=("$product")
productsStr+="$product, "
fi
done
productsStr=${productsStr%, }
set +e
set +o pipefail
missing_files=$(echo $missing_files | tr ',' '\n')
echo "Error: Found modified contracts outside of the expected scope: ${{ inputs.product }}"
echo "Files:"
echo "$missing_files"
echo "Action required: If you want to generate artifacts for other products ($productsStr) run this workflow again with updated configuration"
echo "# Warning!" >> $GITHUB_STEP_SUMMARY
echo "## Reason: Found modified contracts outside of the expected scope: ${{ inputs.product }}" >> $GITHUB_STEP_SUMMARY
echo "### Files:" >> $GITHUB_STEP_SUMMARY
echo "$missing_files" >> $GITHUB_STEP_SUMMARY
echo "## Action required: If you want to generate artifacts for other products ($productsStr) run this workflow again with updated configuration" >> $GITHUB_STEP_SUMMARY
else
echo "No unexpected files found."
fi
115 changes: 115 additions & 0 deletions .github/actions/validate-solidity-artifacts/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
name: Validate Solidity Artifacts
description: Checks whether Slither reports and UML diagrams were generated for all necessary files. If not, a warning is printed in job summary, but the job is not marked as failed.
inputs:
slither_reports_path:
description: Path to the Slither reports directory (without trailing slash)
required: true
uml_diagrams_path:
description: Path to the UML diagrams directory (without trailing slash)
required: true
validate_slither_reports:
description: Whether Slither reports should be validated
required: true
validate_uml_diagrams:
description: Whether UML diagrams should be validated
required: true
sol_files:
description: Comma-separated (CSV) or space-separated (shell) list of Solidity files to check
required: true

runs:
using: composite
steps:
- name: Transform input array
id: transform_input_array
shell: bash
run: |
is_csv_format() {
local input="$1"
if [[ "$input" =~ "," ]]; then
return 0
else
return 1
fi
}
is_space_separated_string() {
local input="$1"
if [[ "$input" =~ ^[^[:space:]]+([[:space:]][^[:space:]]+)*$ ]]; then
return 0
else
return 1
fi
}
array="${{ inputs.sol_files }}"
if is_csv_format "$array"; then
echo "::debug::CSV format detected, nothing to do"
echo "sol_files=$array" >> $GITHUB_OUTPUT
exit 0
fi
if is_space_separated_string "$array"; then
echo "::debug::Space-separated format detected, converting to CSV"
csv_array="${array// /,}"
echo "sol_files=$csv_array" >> $GITHUB_OUTPUT
exit 0
fi
echo "::error::Invalid input format for sol_files. Please provide a comma-separated (CSV) or space-separated (shell) list of Solidity files"
exit 1
- name: Validate UML diagrams
if: ${{ inputs.validate_uml_diagrams == 'true' }}
shell: bash
run: |
echo "Validating UML diagrams"
IFS=',' read -r -a modified_files <<< "${{ steps.transform_input_array.outputs.sol_files }}"
missing_svgs=()
for file in "${modified_files[@]}"; do
svg_file="$(basename "${file%.sol}").svg"
if [ ! -f "${{ inputs.uml_diagrams_path }}/$svg_file" ]; then
echo "Error: UML diagram for $file not found"
missing_svgs+=("$file")
fi
done
if [ ${#missing_svgs[@]} -gt 0 ]; then
echo "Error: Missing UML diagrams for files: ${missing_svgs[@]}"
echo "# Warning!" >> $GITHUB_STEP_SUMMARY
echo "## Reason: Missing UML diagrams for files:" >> $GITHUB_STEP_SUMMARY
for file in "${missing_svgs[@]}"; do
echo " $file" >> $GITHUB_STEP_SUMMARY
done
echo "## Action required: Please try to generate artifacts for them locally or using a different tool" >> $GITHUB_STEP_SUMMARY
else
echo "All UML diagrams generated successfully"
fi
- name: Validate Slither reports
if: ${{ inputs.validate_slither_reports == 'true' }}
shell: bash
run: |
echo "Validating Slither reports"
IFS=',' read -r -a modified_files <<< "${{ steps.transform_input_array.outputs.sol_files }}"
missing_reports=()
for file in "${modified_files[@]}"; do
report_file="$(basename "${file%.sol}")-slither-report.md"
if [ ! -f "${{ inputs.slither_reports_path }}/$report_file" ]; then
echo "Error: Slither report for $file not found"
missing_reports+=("$file")
fi
done
if [ ${#missing_reports[@]} -gt 0 ]; then
echo "Error: Missing Slither reports for files: ${missing_reports[@]}"
echo "# Warning!" >> $GITHUB_STEP_SUMMARY
echo "## Reason: Missing Slither reports for files:" >> $GITHUB_STEP_SUMMARY
for file in "${missing_reports[@]}"; do
echo " $file" >> $GITHUB_STEP_SUMMARY
done
echo "## Action required: Please try to generate artifacts for them locally" >> $GITHUB_STEP_SUMMARY
else
echo "All Slither reports generated successfully"
fi
Loading

0 comments on commit 4b91691

Please sign in to comment.