Commit aebf669c authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

Archive contract artifacts (#11626)

To demonstrate how we can make our deployments more modular, this PR proposes archiving smart contract artifacts as tarballs that get uploaded to GCS. This  allows deployment tools to use precompiled artifacts rather than generating them on-the fly.

The archives are named after the hash of all Solidity files in the contracts-bedrock folder, including those in `lib/`, plus some additional metadata files like `foundry.toml` and `semver-lock.json`. See `calculate-checksum.sh` for details on how the algorithm works. I'm open to feedback around what should make up the checksum.

Since the atifacts are content-addressable, this PR also updates the CI pipeline to download the artifacts from GCS prior to running `pnpm monorepo`. When the Solidity codebase doesn't change, this allows the `pnpm monorepo` job to skip compiling Solidity altogether. While this won't work as well when we're actively modifying the Solidity codebase, since the hash will change, it does provide a modest speedup in CI.
parent 0dcccf6a
...@@ -194,6 +194,10 @@ jobs: ...@@ -194,6 +194,10 @@ jobs:
- run: - run:
name: print forge version name: print forge version
command: forge --version command: forge --version
- run:
name: Pull artifacts
command: bash scripts/ops/pull-artifacts.sh
working_directory: packages/contracts-bedrock
- run: - run:
name: Build contracts name: Build contracts
environment: environment:
...@@ -1461,6 +1465,24 @@ jobs: ...@@ -1461,6 +1465,24 @@ jobs:
working_directory: ./packages/contracts-bedrock working_directory: ./packages/contracts-bedrock
- notify-failures-on-develop - notify-failures-on-develop
publish-contract-artifacts:
docker:
- image: <<pipeline.parameters.ci_builder_image>>
resource_class: medium
steps:
- gcp-cli/install
- gcp-oidc-authenticate:
gcp_cred_config_file_path: /root/gcp_cred_config.json
oidc_token_file_path: /root/oidc_token.json
service_account_email: GCP_SERVICE_CONTRACTS_ACCOUNT_EMAIL
- checkout
- attach_workspace: { at: "." }
- install-contracts-dependencies
- run:
name: Publish artifacts
command: bash scripts/ops/publish-artifacts.sh
working_directory: packages/contracts-bedrock
workflows: workflows:
main: main:
when: when:
...@@ -1475,6 +1497,11 @@ workflows: ...@@ -1475,6 +1497,11 @@ workflows:
jobs: jobs:
- pnpm-monorepo: - pnpm-monorepo:
name: pnpm-monorepo name: pnpm-monorepo
- publish-contract-artifacts:
requires:
- pnpm-monorepo
context:
- oplabs-gcr-release
- contracts-bedrock-tests - contracts-bedrock-tests
- contracts-bedrock-coverage - contracts-bedrock-coverage
- contracts-bedrock-checks: - contracts-bedrock-checks:
......
#!/usr/bin/env bash
set -euo pipefail
echoerr() {
echo "$@" 1>&2
}
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
CONTRACTS_DIR="$SCRIPT_DIR/../.."
cd "$CONTRACTS_DIR"
echoerr "> Calculating contracts checksum..."
find . -type f -name '*.sol' -exec sha256sum {} + > manifest.txt
sha256sum semver-lock.json >> manifest.txt
sha256sum foundry.toml >> manifest.txt
# need to specify the locale to ensure consistent sorting across platforms
LC_ALL=C sort -o manifest.txt manifest.txt
checksum=$(sha256sum manifest.txt | awk '{print $1}')
rm manifest.txt
echoerr "> Done."
echo -n "$checksum"
\ No newline at end of file
#!/usr/bin/env bash
set -euo pipefail
echoerr() {
echo "$@" 1>&2
}
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
CONTRACTS_DIR="$SCRIPT_DIR/../.."
DEPLOY_BUCKET="oplabs-contract-artifacts"
cd "$CONTRACTS_DIR"
# ensure that artifacts exists and is non-empty
if [ ! -d "forge-artifacts" ] || [ -z "$(ls -A forge-artifacts)" ]; then
echoerr "> No forge-artifacts directory found."
exit 1
fi
if [ ! -d "artifacts" ] || [ -z "$(ls -A artifacts)" ]; then
echoerr "> No artifacts directory found."
exit 1
fi
checksum=$(bash scripts/ops/calculate-checksum.sh)
echoerr "> Checking for existing artifacts..."
exists=$(curl -s -o /dev/null --fail -LI "https://storage.googleapis.com/$DEPLOY_BUCKET/artifacts-v1-$checksum.tar.gz" || echo "fail")
if [ "$exists" != "fail" ]; then
echoerr "> Existing artifacts found, nothing to do."
exit 0
fi
echoerr "> Archiving artifacts..."
archive_name="artifacts-v1-$checksum.tar.gz"
# use gtar on darwin
if [[ "$OSTYPE" == "darwin"* ]]; then
tar="gtar"
else
tar="tar"
fi
"$tar" -czf "$archive_name" artifacts forge-artifacts cache
du -sh "$archive_name" | awk '{$1=$1};1' # trim leading whitespace
echoerr "> Done."
echoerr "> Uploading artifacts to GCS..."
gcloud storage cp "$archive_name" "gs://$DEPLOY_BUCKET/$archive_name"
echoerr "> Done."
rm "$archive_name"
\ No newline at end of file
#!/usr/bin/env bash
set -euo pipefail
echoerr() {
echo "$@" 1>&2
}
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
CONTRACTS_DIR="$SCRIPT_DIR/../.."
cd "$CONTRACTS_DIR"
checksum=$(bash scripts/ops/calculate-checksum.sh)
archive_name="artifacts-v1-$checksum.tar.gz"
echoerr "> Checking for existing artifacts..."
exists=$(curl -s -o /dev/null --fail -LI "https://storage.googleapis.com/oplabs-contract-artifacts/$archive_name" || echo "fail")
if [ "$exists" == "fail" ]; then
echoerr "> No existing artifacts found, exiting."
exit 0
fi
echoerr "> Cleaning up existing artifacts..."
rm -rf artifacts
rm -rf forge-artifacts
rm -rf cache
echoerr "> Done."
echoerr "> Found existing artifacts. Downloading..."
curl -o "$archive_name" "https://storage.googleapis.com/oplabs-contract-artifacts/$archive_name"
echoerr "> Done."
echoerr "> Extracting existing artifacts..."
tar -xzvf "$archive_name"
echoerr "> Done."
echoerr "> Cleaning up."
rm "$archive_name"
echoerr "> Done."
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment