@@ -194,7 +194,7 @@ commands:
194194 parameters :
195195 version :
196196 type : string
197- default : " nightly "
197+ default : " stable "
198198 install_path :
199199 type : string
200200 default : /home/circleci/bin
@@ -204,41 +204,55 @@ commands:
204204 command : |
205205 FOUNDRY_REPO="foundry-rs/foundry"
206206 FOUNDRY_VERSION="<< parameters.version >>"
207- # Make authenticated requests when the Github token is available
208- if [[ -n "$GITHUB_READ_TOKEN" ]]; then
209- EXTRA_HEADERS=(--header 'Authorization: Bearer '"${GITHUB_READ_TOKEN}")
207+ RELEASE_URL="https://github.com/${FOUNDRY_REPO}/releases/download/${FOUNDRY_VERSION}"
208+ echo "export FOUNDRY_VERSION=${FOUNDRY_VERSION}" >> "$BASH_ENV"
209+ echo "export RELEASE_URL=${RELEASE_URL}" >> "$BASH_ENV"
210+ ATTESTATION_URL=$(curl --silent --location --fail "${RELEASE_URL}/foundry_${FOUNDRY_VERSION}_linux_amd64.attestation.txt") || {
211+ echo "Failed to fetch attestation file"
212+ exit 1
213+ }
214+ ATTESTATION_JSON=$(curl --silent --location --fail --header "Accept: application/json" "${ATTESTATION_URL}") || {
215+ echo "Failed to fetch attestation JSON"
216+ exit 1
217+ }
218+ RELEASE_SHA=$(echo "${ATTESTATION_JSON}" | jq --raw-output '.payload.attestation.sourceRepositoryDigest')
219+ if [[ -z "$RELEASE_SHA" || "$RELEASE_SHA" == "null" ]]; then
220+ echo "Failed to extract release SHA from attestation"
221+ exit 1
210222 fi
211- FOUNDRY_RELEASE_SHA=$(curl \
212- --silent \
213- --fail \
214- --show-error \
215- "${EXTRA_HEADERS[@]}" \
216- "https://api.github.com/repos/${FOUNDRY_REPO}/git/refs/tags/${FOUNDRY_VERSION}" \
217- | jq --raw-output .object.sha \
218- )
219- echo "export FOUNDRY_REPO=$FOUNDRY_REPO" >> "$BASH_ENV"
220- echo "export FOUNDRY_VERSION=$FOUNDRY_VERSION" >> "$BASH_ENV"
221- echo "export FOUNDRY_RELEASE_TAG='${FOUNDRY_VERSION}'" >> "$BASH_ENV"
222- # Save commit sha for caching
223- echo "$FOUNDRY_RELEASE_SHA" > /tmp/workspace/foundry-release-sha
223+ echo "${RELEASE_SHA}" > /tmp/workspace/foundry-release-sha
224+ # Extract forge checksum from the attestation
225+ EXPECTED_FORGE_CHECKSUM=$(echo "${ATTESTATION_JSON}" | jq --raw-output '.payload.attestation.subjects[] | select(.subjectName=="forge") | .subjectDigest' | sed 's/sha256://')
226+ if [[ -z "$EXPECTED_FORGE_CHECKSUM" || "$EXPECTED_FORGE_CHECKSUM" == "null" ]]; then
227+ echo "Failed to extract forge checksum from attestation"
228+ exit 1
229+ fi
230+ echo "export EXPECTED_FORGE_CHECKSUM=${EXPECTED_FORGE_CHECKSUM}" >> "$BASH_ENV"
224231 - restore_cache :
225232 keys :
226- - foundry-<< parameters.version >>-{{ arch }}-{{ checksum "/tmp/workspace/foundry-release-sha" }}
233+ - foundry-v1- << parameters.version >>-{{ arch }}-{{ checksum "/tmp/workspace/foundry-release-sha" }}
227234 # WARNING! If you edit anything between here and save_cache, remember to invalidate the cache manually.
228235 - run :
229236 name : Install foundry
230237 command : |
231- ! forge --version 2> /dev/null
232- curl \
233- --fail \
234- --location \
235- --output /tmp/foundry.tar.gz \
236- "https://github.com/${FOUNDRY_REPO}/releases/download/${FOUNDRY_RELEASE_TAG}/foundry_${FOUNDRY_VERSION}_linux_amd64.tar.gz"
237- cd "<< parameters.install_path >>"
238- tar --extract --gzip --file /tmp/foundry.tar.gz --one-top-level
239- ln --symbolic --force foundry/{forge,anvil,cast,chisel} .
238+ if forge --version 2> /dev/null; then
239+ echo "Foundry already cached, skipping install"
240+ else
241+ curl --fail --location --output /tmp/foundry.tar.gz "${RELEASE_URL}/foundry_${FOUNDRY_VERSION}_linux_amd64.tar.gz"
242+ cd "<< parameters.install_path >>"
243+ tar --extract --gzip --file /tmp/foundry.tar.gz --one-top-level
244+ # TODO: Use `gh attestation verify foundry/forge --owner foundry-rs` for signature verification.
245+ # Current approach only verifies checksum without validating the signature.
246+ # https://docs.github.com/en/actions/how-tos/secure-your-work/use-artifact-attestations/use-artifact-attestations#verifying-an-artifact-attestation-for-binaries
247+ ACTUAL=$(sha256sum foundry/forge | cut --delimiter=' ' --fields=1)
248+ if [[ "$EXPECTED_FORGE_CHECKSUM" != "$ACTUAL" ]]; then
249+ echo "Checksum mismatch: expected $EXPECTED_FORGE_CHECKSUM, got $ACTUAL"
250+ exit 1
251+ fi
252+ ln --symbolic --force foundry/{forge,anvil,cast,chisel} .
253+ fi
240254 - save_cache :
241- key : foundry-<< parameters.version >>-{{ arch }}-{{ checksum "/tmp/workspace/foundry-release-sha" }}
255+ key : foundry-v1- << parameters.version >>-{{ arch }}-{{ checksum "/tmp/workspace/foundry-release-sha" }}
242256 paths :
243257 - << parameters.install_path >>
244258
@@ -1646,9 +1660,6 @@ jobs:
16461660 python2 :
16471661 type : boolean
16481662 default : false
1649- foundry_version :
1650- type : string
1651- default : " nightly"
16521663 docker :
16531664 - image : << parameters.image >>
16541665 resource_class : << parameters.resource_class >>
@@ -1662,8 +1673,7 @@ jobs:
16621673 - checkout
16631674 - attach_workspace :
16641675 at : /tmp/workspace
1665- - install_foundry :
1666- version : << parameters.foundry_version >>
1676+ - install_foundry
16671677 - run :
16681678 name : Ensure pnpm is installed if npm is present
16691679 command : |
0 commit comments