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

[TT-1326] Update Solidty Foundry pipeline with Slither #13986

Merged
merged 68 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
4326696
More univeral lcov prunning
Tofel Aug 1, 2024
8d9ce26
update Shared code cov
Tofel Aug 1, 2024
3b8049d
exclude deleted files from Slither
Tofel Aug 1, 2024
27b8009
use single source of truth for all Solidity Foundry jobs
Tofel Aug 1, 2024
7c782ee
fix json
Tofel Aug 1, 2024
30aa2a6
compact output with jq
Tofel Aug 1, 2024
82d1f07
fix condition for fmt
Tofel Aug 1, 2024
eed761e
try to scope tests to changes
Tofel Aug 1, 2024
f9e116b
move matrix check to step level
Tofel Aug 1, 2024
5bef6d9
fix outputs path
Tofel Aug 1, 2024
d1f5f2c
trigger
Tofel Aug 1, 2024
6f5f25e
test with Automation change
Tofel Aug 1, 2024
3c06881
try with shared
Tofel Aug 1, 2024
033a062
run fmt also if any sol files were modified
Tofel Aug 1, 2024
9d18fde
fix job name in collect metrics
Tofel Aug 1, 2024
94ffafa
trigger pipeline only for localised change + update changes info
Tofel Aug 1, 2024
a7fac9f
add changeset
Tofel Aug 1, 2024
4bb7e46
remove test change
Tofel Aug 1, 2024
67c8a5d
do not run forge fmt if shared contracts have changed
Tofel Aug 2, 2024
d9bb6f2
Merge branch 'develop' into tt_1326_update_Sol_Foundry
Tofel Aug 2, 2024
f9b56c4
try artifact pipeline by hijacking hardhat
Tofel Aug 2, 2024
77f4a3e
Merge branch 'develop' into tt_1326_update_Sol_Foundry
Tofel Aug 5, 2024
cb083ee
# This is a combination of 2 commits.
Tofel Aug 5, 2024
9ecb156
CR changes + test them
Tofel Aug 5, 2024
7eedda5
remove test files
Tofel Aug 5, 2024
9028d69
do not run Slither for test files
Tofel Aug 5, 2024
f8aafb3
do not run fmt if test files were modified
Tofel Aug 5, 2024
468a157
remove unused config file
Tofel Aug 5, 2024
c4d75f1
Merge branch 'develop' into tt_1325_solidity_pipelines_genhtml
Tofel Aug 5, 2024
3cfe081
restore old Hardhat pipeline
Tofel Aug 5, 2024
88c3d73
Merge branch 'tt_1326_update_Sol_Foundry' into tt_1325_solidity_pipel…
Tofel Aug 5, 2024
0a49359
add missing transmission setup
Tofel Aug 5, 2024
f2b7bd7
fix basic info condition, join 2 steps into 1, define higher-level co…
Tofel Aug 6, 2024
d7d07ad
define actions for installing Slither and solc-select
Tofel Aug 6, 2024
678f310
run all tests also if package.json changes; run them on all non_src c…
Tofel Aug 6, 2024
7b6e1ac
add action for validating whether all Slither reports and UML diagram…
Tofel Aug 6, 2024
ff9b2d9
fetch origin in validation action
Tofel Aug 6, 2024
e2912cc
compare with HEAD in validate action
Tofel Aug 6, 2024
77c7869
compare with origin in validation action
Tofel Aug 6, 2024
6ce8e85
handle both csv and shell arrays in the validation action
Tofel Aug 6, 2024
76594e1
Merge branch 'tt_1326_update_Sol_Foundry' into tt_1325_solidity_pipel…
Tofel Aug 6, 2024
c2b8b48
update artifact pipeline with new actions
Tofel Aug 6, 2024
b38792b
Merge branch 'develop' into tt_1325_solidity_pipelines_genhtml
Tofel Aug 6, 2024
e05a9b4
fix workflow after tests
Tofel Aug 6, 2024
d845abe
fix how validation actions works with commits
Tofel Aug 6, 2024
26a5cf3
Merge branch 'develop' into tt_1326_update_Sol_Foundry
Tofel Aug 6, 2024
7d911da
Merge branch 'tt_1326_update_Sol_Foundry' into tt_1325_solidity_pipel…
Tofel Aug 6, 2024
03f48a9
treat shared as any other product
Tofel Aug 7, 2024
7b472a8
small fixes
Tofel Aug 7, 2024
024e9e3
apply CR changes
Tofel Aug 7, 2024
a222fe7
remove special handling for deleted files
Tofel Aug 7, 2024
aa0af66
remove apt-get update
Tofel Aug 7, 2024
60e548d
Merge branch 'tt_1326_update_Sol_Foundry' into tt_1325_solidity_pipel…
Tofel Aug 7, 2024
8e22de6
use only dorny/paths
Tofel Aug 7, 2024
afdef19
remove unused input
Tofel Aug 7, 2024
7b7b9dd
CR changes: use dorny/paths with quantifier, move scope validation to…
Tofel Aug 7, 2024
0928fb9
fix workflow
Tofel Aug 7, 2024
27a5834
Merge branch 'tt_1326_update_Sol_Foundry' into tt_1325_solidity_pipel…
Tofel Aug 7, 2024
7d46431
fail bash scripts on erors
Tofel Aug 8, 2024
df771e3
add set -euo pipefail to bash scripts
Tofel Aug 8, 2024
1fb00d2
define action to detect foundry version
Tofel Aug 8, 2024
2034917
Merge branch 'tt_1326_update_Sol_Foundry' into tt_1325_solidity_pipel…
Tofel Aug 8, 2024
a18c5ad
fix select solc version script, better slither report output
Tofel Aug 8, 2024
32addb7
checkout repo
Tofel Aug 8, 2024
91fb818
Merge branch 'tt_1326_update_Sol_Foundry' into tt_1325_solidity_pipel…
Tofel Aug 8, 2024
8c9d3c4
add id
Tofel Aug 8, 2024
699c541
Merge branch 'tt_1326_update_Sol_Foundry' into tt_1325_solidity_pipel…
Tofel Aug 8, 2024
c286f72
Merge pull request #14015 from smartcontractkit/tt_1325_solidity_pipe…
Tofel Aug 9, 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
264 changes: 213 additions & 51 deletions .github/workflows/solidity-foundry.yml

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions contracts/.changeset/itchy-deers-deny.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@chainlink/contracts": patch
---

More comprehensive & product-scoped Solidity Foundry pipeline
4 changes: 4 additions & 0 deletions contracts/.slither.config-pr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"filter_paths": "(openzeppelin|mocks/|test/|tests/|testhelpers)",
"detectors_to_exclude": "pragma"
}
29 changes: 0 additions & 29 deletions contracts/scripts/ccip_lcov_prune

This file was deleted.

80 changes: 80 additions & 0 deletions contracts/scripts/ci/generate_slither_report.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/bin/bash

function check_chainlink_dir() {
local param_dir="chainlink"
current_dir=$(pwd)

current_base=$(basename "$current_dir")

if [ "$current_base" != "$param_dir" ]; then
>&2 echo "The script must be run from the root of $param_dir directory"
exit 1
fi
}

check_chainlink_dir

if [ "$#" -lt 5 ]; then
>&2 echo "Generates Markdown Slither reports and saves them to a target directory."
>&2 echo "Usage: $0 <https://github.com/ORG/REPO/blob/COMMIT/> <config-file> <root-directory-with–contracts> <comma-separated list of contracts> <where-to-save-reports> [slither extra params]"
exit 1
fi

REPO_URL=$1
CONFIG_FILE=$2
SOURCE_DIR=$3
FILES=${4// /} # Remove any spaces from the list of files
TARGET_DIR=$5
SLITHER_EXTRA_PARAMS=$6

run_slither() {
local FILE=$1
local TARGET_DIR=$2

# needed, because the action we use returns all modified files, also deleted ones and we must skip those
if [ ! -f "$FILE" ]; then
echo "Warning: File not found: $FILE"
echo "Skipping..."
return
fi

source ./contracts/scripts/ci/select_solc_version.sh "$FILE"
if [ $? -ne 0 ]; then
>&2 echo "Error: Failed to select Solc version for $FILE"
exit 1
fi

SLITHER_OUTPUT_FILE="$TARGET_DIR/$(basename "${FILE%.sol}")-slither-report.md"

output=$(slither --config-file "$CONFIG_FILE" "$FILE" --checklist --markdown-root "$REPO_URL" --fail-none $SLITHER_EXTRA_PARAMS)
if [ $? -ne 0 ]; then
>&2 echo "Slither failed for $FILE"
exit 1
fi
output=$(echo "$output" | sed '/\*\*THIS CHECKLIST IS NOT COMPLETE\*\*. Use `--show-ignored-findings` to show all the results./d' | sed '/Summary/d')

echo "# Summary for $FILE" > "$SLITHER_OUTPUT_FILE"
echo "$output" >> "$SLITHER_OUTPUT_FILE"
}

process_files() {
local SOURCE_DIR=$1
local TARGET_DIR=$2
local FILES=(${3//,/ }) # Split the comma-separated list into an array

mkdir -p "$TARGET_DIR"

for FILE in "${FILES[@]}"; do
FILE=${FILE//\"/}
run_slither "$SOURCE_DIR/$FILE" "$TARGET_DIR"
done
}

process_files "$SOURCE_DIR" "$TARGET_DIR" "${FILES[@]}"

if [ $? -ne 0 ]; then
>&2 echo "Error: Failed to generate Slither reports"
exit 1
fi

echo "Slither reports saved in $TARGET_DIR folder"
28 changes: 28 additions & 0 deletions contracts/scripts/ci/modify_remappings.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

if [ "$#" -ne 2 ]; then
>&2 echo "Usage: $0 <directory_prefix> <remappings_file>"
exit 1
fi

DIR_PREFIX=$1
REMAPPINGS_FILE=$2

if [ ! -f "$REMAPPINGS_FILE" ]; then
>&2 echo "Error: Remappings file '$REMAPPINGS_FILE' not found."
exit 1
fi

OUTPUT_FILE="remappings_modified.txt"

while IFS= read -r line; do
if [[ "$line" =~ ^[^=]+= ]]; then
REMAPPED_PATH="${line#*=}"
MODIFIED_LINE="${line%=*}=${DIR_PREFIX}/${REMAPPED_PATH}"
echo "$MODIFIED_LINE" >> "$OUTPUT_FILE"
else
echo "$line" >> "$OUTPUT_FILE"
fi
done < "$REMAPPINGS_FILE"

echo "Modified remappings have been saved to: $OUTPUT_FILE"
114 changes: 114 additions & 0 deletions contracts/scripts/ci/select_solc_version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/bin/bash

function check_chainlink_dir() {
local param_dir="chainlink"
current_dir=$(pwd)

current_base=$(basename "$current_dir")

if [ "$current_base" != "$param_dir" ]; then
echo "The script must be run from the root of $param_dir directory"
exit 1
fi
}

check_chainlink_dir

FILE="$1"

if [ "$#" -lt 1 ]; then
echo "Detects the Solidity version of a file and selects the appropriate Solc version."
echo "If the version is not installed, it will be installed and selected."
echo "Will prefer to use the version from Foundry profile if it satisfies the version in the file."
echo "Usage: $0 <file>"
exit 1
fi

if [ -z "$FILE" ]; then
echo "Error: File not provided."
exit 1
fi

extract_product() {
local path=$1

echo "$path" | awk -F'src/[^/]*/' '{print $2}' | cut -d'/' -f1
}

extract_pragma() {
local FILE=$1

if [[ -f "$FILE" ]]; then
SOLCVER="$(grep --no-filename '^pragma solidity' "$FILE" | cut -d' ' -f3)"
else
echo "$FILE is not a file or it could not be found. Exiting."
return 1
fi
SOLCVER="$(echo "$SOLCVER" | sed 's/[^0-9\.^]//g')"
>&2 echo "::debug::Detected Solidity version in pragma: $SOLCVER"
echo "$SOLCVER"
}

echo "Detecting Solc version for $FILE"

# Set FOUNDRY_PROFILE to the product name only if it is set; otherwise either already set value will be used or it will be empty
PRODUCT=$(extract_product "$FILE")
if [ -n "$PRODUCT" ]; then
FOUNDRY_PROFILE="$PRODUCT"
fi
SOLC_IN_PROFILE=$(forge config --json --root contracts | jq ".solc")
SOLC_IN_PROFILE=$(echo "$SOLC_IN_PROFILE" | tr -d "'\"")
echo "::debug::Detected Solidity version in profile: $SOLC_IN_PROFILE"

SOLCVER=$(extract_pragma "$FILE")

exit_code=$?
if [ $exit_code -ne 0 ]; then
echo "Error: Failed to extract the Solidity version from $FILE."
return 1
fi

SOLCVER=$(echo "$SOLCVER" | tr -d "'\"")

if [[ "$SOLC_IN_PROFILE" != "null" && -n "$SOLCVER" ]]; then
set +e
COMPAT_SOLC_VERSION=$(npx semver "$SOLC_IN_PROFILE" -r "$SOLCVER")
exit_code=$?
set -e
if [[ $exit_code -eq 0 && -n "$COMPAT_SOLC_VERSION" ]]; then
echo "::debug::Version $SOLC_IN_PROFILE satisfies the constraint $SOLCVER"
SOLC_TO_USE="$SOLC_IN_PROFILE"
else
echo "::debug::Version $SOLC_IN_PROFILE does not satisfy the constraint $SOLCVER"
SOLC_TO_USE="$SOLCVER"
fi
elif [[ "$SOLC_IN_PROFILE" != "null" && -z "$SOLCVER" ]]; then
>&2 echo "No version found in the Solidity file. Exiting"
return 1
elif [[ "$SOLC_IN_PROFILE" == "null" && -n "$SOLCVER" ]]; then
echo "::debug::Using the version from the file: $SOLCVER"
SOLC_TO_USE="$SOLCVER"
else
>&2 echo "No version found in the profile or the Solidity file."
return 1
fi

echo "Will use $SOLC_TO_USE"
SOLC_TO_USE=$(echo "$SOLC_TO_USE" | tr -d "'\"")
SOLC_TO_USE="$(echo "$SOLC_TO_USE" | sed 's/[^0-9\.]//g')"

INSTALLED_VERSIONS=$(solc-select versions)

if echo "$INSTALLED_VERSIONS" | grep -q "$SOLC_TO_USE"; then
echo "::debug::Version $SOLCVER is already installed."
if echo "$INSTALLED_VERSIONS" | grep "$SOLC_TO_USE" | grep -q "current"; then
echo "::debug::Version $SOLCVER is already selected."
else
echo "::debug::Selecting $SOLC_TO_USE"
solc-select use "$SOLC_TO_USE"
fi
else
echo "::debug::Version $SOLC_TO_USE is not installed."
solc-select install "$SOLC_TO_USE"
solc-select use "$SOLC_TO_USE"
fi
77 changes: 77 additions & 0 deletions contracts/scripts/lcov_prune
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/bin/bash

if [ "$#" -ne 3 ]; then
>&2 echo "Usage: $0 <product_name> <input_coverage_file> <output_coverage_file>"
exit 1
fi

set -e

product_name=$1
input_coverage_file=$2
output_coverage_file=$3

# src/v0.8/ccip/libraries/Internal.sol
# src/v0.8/ccip/libraries/RateLimiter.sol
# src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol
# src/v0.8/ccip/libraries/MerkleMultiProof.sol
# src/v0.8/ccip/libraries/Pool.sol
# excluded because Foundry doesn't support coverage on library files

# BurnWithFromMintTokenPool is excluded because Forge doesn't seem to
# register coverage, even though it is 100% covered.
exclusion_list_ccip=(
"src/v0.8/ccip/ocr/OCR2Abstract.sol"
"src/v0.8/ccip/libraries/Internal.sol"
"src/v0.8/ccip/libraries/RateLimiter.sol"
"src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol"
"src/v0.8/ccip/libraries/MerkleMultiProof.sol"
"src/v0.8/ccip/libraries/Pool.sol"
"src/v0.8/ConfirmedOwnerWithProposal.sol"
"src/v0.8/tests/MockV3Aggregator.sol"
"src/v0.8/ccip/applications/CCIPClientExample.sol"
"src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol"
)

exclusion_list_shared=(
"*/shared/*"
)

exclusion_list_common=(
"*/$product_name/test/*"
"*/vendor/*"
)

all_exclusions=()

case "$product_name" in
"ccip")
all_exclusions+=("${exclusion_list_ccip[@]}")
;;
"shared")
# No product-specific exclusions for shared
;;
*)
;;
esac

all_exclusions+=("${exclusion_list_common[@]}")

if [ "$product_name" != "shared" ]; then
all_exclusions+=("${exclusion_list_shared[@]}")
fi

echo "Excluding the following files for product $product_name:"
for exclusion in "${all_exclusions[@]}"; do
echo "$exclusion"
done

lcov_command="lcov --remove $input_coverage_file -o $output_coverage_file"

for exclusion in "${all_exclusions[@]}"; do
lcov_command+=" \"$exclusion\""
done

lcov_command+=" --rc lcov_branch_coverage=1"

eval $lcov_command
Loading