Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
42 changes: 42 additions & 0 deletions op-deployer/pkg/deployer/artifacts/cmd/mktar/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import (
"io"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"strings"
"time"

"github.com/klauspost/compress/zstd"
)
Expand Down Expand Up @@ -150,6 +152,13 @@ func main() {
log.Fatalf("walk: %v", err)
}

// Add COMMIT file if git is available
if commit := getGitCommit(absBase); commit != "" {
if err := addCommitFile(tw, commit); err != nil {
log.Fatalf("failed to add COMMIT file: %v", err)
}
}

if err := tw.Flush(); err != nil {
log.Fatalf("flush tar: %v", err)
}
Expand Down Expand Up @@ -216,3 +225,36 @@ func linkTarget(path string, info os.FileInfo) string {
}
return target
}

func getGitCommit(baseDir string) string {
cmd := exec.Command("git", "rev-parse", "HEAD")
cmd.Dir = baseDir
output, err := cmd.Output()
if err != nil {
return ""
}
return strings.TrimSpace(string(output))
}

func addCommitFile(tw *tar.Writer, commit string) error {
hdr := &tar.Header{
Name: "COMMIT",
Size: int64(len(commit)),
Mode: 0644,
ModTime: time.Now(),
AccessTime: time.Now(),
ChangeTime: time.Now(),
Typeflag: tar.TypeReg,
}

if err := tw.WriteHeader(hdr); err != nil {
return err
}

if _, err := tw.Write([]byte(commit)); err != nil {
return err
}

log.Printf("a COMMIT")
return nil
}
18 changes: 16 additions & 2 deletions op-deployer/pkg/deployer/integration_test/cli/verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func TestCLIVerify(t *testing.T) {
"--artifacts-locator", "embedded",
}, nil)

require.Contains(t, output, "Contract verified successfully")
require.Contains(t, output, "Contract already verified")
require.Contains(t, output, "superchainConfigProxyAddress")
})

Expand All @@ -138,7 +138,8 @@ func TestCLIVerify(t *testing.T) {

require.Contains(t, output, "Starting automatic contract verification")
require.Contains(t, output, "Verification Summary")
require.Contains(t, output, "verified=5")
require.Contains(t, output, "verified=0")
require.Contains(t, output, "skipped=5")
require.Contains(t, output, "failed=0")
})

Expand All @@ -165,6 +166,19 @@ func setupMockBlockscout(t *testing.T) string {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")

if strings.HasPrefix(r.URL.Path, "/api/v2/smart-contracts/") {
response := map[string]interface{}{
"message": "OK",
"is_verified": true,
"is_fully_verified": true,
"is_partially_verified": false,
"is_verified_via_eth_bytecode_db": false,
"is_verified_via_sourcify": false,
}
_ = json.NewEncoder(w).Encode(response)
return
}

var action string
if r.Method == http.MethodPost {
if err := r.ParseForm(); err != nil {
Expand Down
165 changes: 37 additions & 128 deletions packages/contracts-bedrock/scripts/ops/publish-artifacts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,20 @@ set -euo pipefail
usage() {
echo "Usage: $0 [--force|-f]"
echo ""
echo "Publish contract artifacts to GCS with optional zstd compression."
echo "Publish contract artifacts to GCS using op-deployer's build process."
echo ""
echo "Options:"
echo " --force, -f Force upload even if artifacts already exist"
echo " --help, -h Show this help message"
echo ""
echo "If zstd is available, creates both .tar.gz and .tar.zst files."
echo "Otherwise, creates only .tar.gz with a warning about future zstd requirement."
echo "Uses 'just build-contracts' and 'just copy-contract-artifacts' from op-deployer."
exit 0
}

echoerr() {
echo "$@" 1>&2
}

# Check for help flag
if [ "${1:-}" = "--help" ] || [ "${1:-}" = "-h" ]; then
usage
fi
Expand All @@ -30,157 +28,68 @@ CONTRACTS_DIR="$SCRIPT_DIR/../.."
DEPLOY_BUCKET="oplabs-contract-artifacts"
BUCKET_URL="https://storage.googleapis.com/$DEPLOY_BUCKET"

cd "$CONTRACTS_DIR"
# Resolve paths
ROOT_DIR=$(cd -- "$CONTRACTS_DIR/../.." &> /dev/null && pwd)
OP_DEPLOYER_DIR="$ROOT_DIR/op-deployer"

if [ ! -d "$OP_DEPLOYER_DIR" ]; then
echoerr "> ERROR: op-deployer not found at $OP_DEPLOYER_DIR"
exit 1
fi

# Check for force flag
FORCE=false
if [ "${1:-}" = "--force" ] || [ "${1:-}" = "-f" ]; then
FORCE=true
echoerr "> Force mode enabled - will overwrite existing artifacts"
fi

if command -v zstd > /dev/null 2>&1; then
HAS_ZSTD=true
echoerr "> zstd found, will create both .tar.gz and .tar.zst files"
else
HAS_ZSTD=false
echoerr "> zstd not found, will create only .tar.gz files"
echoerr "> WARNING: zstd not available. In the future, only zstd will be supported."
fi
checksum=$(bash "$CONTRACTS_DIR/scripts/ops/calculate-checksum.sh")

# 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)

archive_name_gz="artifacts-v1-$checksum.tar.gz"
archive_name_zst="artifacts-v1-$checksum.tar.zst"

upload_url_gz="$BUCKET_URL/$archive_name_gz"
upload_url_zst="$BUCKET_URL/$archive_name_zst"

echoerr "> Checksum: $checksum"
echoerr "> Checking for existing artifacts..."

if [ "$HAS_ZSTD" = true ]; then
exists_zst=$(curl -s -o /dev/null --fail -LI "$upload_url_zst" || echo "fail")
if [ "$exists_zst" != "fail" ] && [ "$FORCE" = false ]; then
echoerr "> Existing artifacts found (.tar.zst), nothing to do. Use --force to overwrite."
exit 0
fi
fi

exists_gz=$(curl -s -o /dev/null --fail -LI "$upload_url_gz" || echo "fail")

if [ "$exists_gz" != "fail" ] && [ "$FORCE" = false ]; then
echoerr "> Existing artifacts found (.tar.gz), nothing to do. Use --force to overwrite."
exists_zst=$(curl -s -o /dev/null --fail -LI "$upload_url_zst" || echo "fail")
if [ "$exists_zst" != "fail" ] && [ "$FORCE" = false ]; then
echoerr "> Existing artifacts found (.tar.zst), nothing to do. Use --force to overwrite."
exit 0
fi

echoerr "> Archiving artifacts..."

# use gtar on darwin
if [[ "$OSTYPE" == "darwin*" ]]; then
tar="gtar"
else
tar="tar"
fi

rm -f COMMIT
commit=$(git rev-parse HEAD)
echo "$commit" > COMMIT

tar_args=("artifacts" "forge-artifacts" "COMMIT")
if [ -d "cache" ]; then
tar_args+=("cache")
echoerr "> Including cache directory in archive"
else
echoerr "> Cache directory not found, excluding from archive"
fi

if [ "$HAS_ZSTD" = true ]; then
echoerr "> Compressing artifacts (.tar.gz and .tar.zst)..."

# Create intermediate tar file first for reliable compression
temp_tar="artifacts-v1-$checksum.tar"
"$tar" -cf "$temp_tar" "${tar_args[@]}"

gzip -9 < "$temp_tar" > "$archive_name_gz" &
gz_pid=$!

zstd --ultra -22 -f "$temp_tar" -o "$archive_name_zst" &
zst_pid=$!

wait "$gz_pid"
wait "$zst_pid"

rm "$temp_tar"
echoerr "> Building contracts and creating artifacts..."

du -sh "$archive_name_gz" | awk '{$1=$1};1' # trim leading whitespace
echoerr "> Created .tar.gz archive"
du -sh "$archive_name_zst" | awk '{$1=$1};1' # trim leading whitespace
echoerr "> Created .tar.zst archive"
cd "$OP_DEPLOYER_DIR"

# Compare file sizes in MB
gz_size=$(stat -f%z "$archive_name_gz" 2> /dev/null || stat -c%s "$archive_name_gz" 2> /dev/null || echo "0")
zst_size=$(stat -f%z "$archive_name_zst" 2> /dev/null || stat -c%s "$archive_name_zst" 2> /dev/null || echo "0")
echoerr "> Running 'just build-contracts'..."
just build-contracts

if [ "$gz_size" -gt 0 ] && [ "$zst_size" -gt 0 ]; then
gz_mb=$(awk "BEGIN {printf \"%.2f\", $gz_size / 1048576}")
zst_mb=$(awk "BEGIN {printf \"%.2f\", $zst_size / 1048576}")
savings=$((gz_size - zst_size))
savings_percent=$((100 * savings / gz_size))
echoerr "> Size comparison: .tar.gz=${gz_mb}MB, .tar.zst=${zst_mb}MB (${savings_percent}% smaller)"
fi
else
echoerr "> Compressing artifacts (.tar.gz)..."
echoerr "> Running 'just copy-contract-artifacts'..."
just copy-contract-artifacts

"$tar" -czf "$archive_name_gz" "${tar_args[@]}"
du -sh "$archive_name_gz" | awk '{$1=$1};1' # trim leading whitespace
echoerr "> Created .tar.gz archive"
ARTIFACTS_TZST="./pkg/deployer/artifacts/forge-artifacts/artifacts.tzst"
if [ ! -f "$ARTIFACTS_TZST" ]; then
echoerr "> ERROR: Failed to create artifacts.tzst"
exit 1
fi

echoerr "> Done."
TEMP_DIR=$(mktemp -d)
trap 'rm -rf "$TEMP_DIR"' EXIT

cp "$ARTIFACTS_TZST" "$TEMP_DIR/$archive_name_zst"
du -sh "$TEMP_DIR/$archive_name_zst" | awk '{$1=$1};1'
echoerr "> Created .tar.zst archive"

echoerr "> Uploading artifacts to $BUCKET_URL..."

# Force single-stream upload to improve reliability
gcloud config set storage/parallel_composite_upload_enabled False
if [ "$HAS_ZSTD" = true ]; then
# Upload with checksum-based names
gcloud --verbosity="info" storage cp "$archive_name_gz" "$archive_name_zst" "gs://$DEPLOY_BUCKET/"
echoerr "> Uploaded to: $upload_url_gz"
echoerr "> Uploaded to: $upload_url_zst"

# Also upload as "latest" for PR fallback
echoerr "> Uploading as 'latest' for PR fallback..."
gcloud --verbosity="info" storage cp "$archive_name_gz" "gs://$DEPLOY_BUCKET/artifacts-v1-latest.tar.gz"
gcloud --verbosity="info" storage cp "$archive_name_zst" "gs://$DEPLOY_BUCKET/artifacts-v1-latest.tar.zst"
echoerr "> Uploaded to: https://storage.googleapis.com/$DEPLOY_BUCKET/artifacts-v1-latest.tar.gz"
echoerr "> Uploaded to: https://storage.googleapis.com/$DEPLOY_BUCKET/artifacts-v1-latest.tar.zst"
else
# Upload with checksum-based name
gcloud --verbosity="info" storage cp "$archive_name_gz" "gs://$DEPLOY_BUCKET/$archive_name_gz"
echoerr "> Uploaded to: $upload_url_gz"

# Also upload as "latest" for PR fallback
echoerr "> Uploading as 'latest' for PR fallback..."
gcloud --verbosity="info" storage cp "$archive_name_gz" "gs://$DEPLOY_BUCKET/artifacts-v1-latest.tar.gz"
echoerr "> Uploaded to: https://storage.googleapis.com/$DEPLOY_BUCKET/artifacts-v1-latest.tar.gz"
fi

echoerr "> Done."
gcloud --verbosity="info" storage cp "$TEMP_DIR/$archive_name_zst" "gs://$DEPLOY_BUCKET/$archive_name_zst"
echoerr "> Uploaded to: $upload_url_zst"

rm "$archive_name_gz"
if [ "$HAS_ZSTD" = true ]; then
rm "$archive_name_zst"
fi
rm COMMIT
echoerr "> Uploading as 'latest' for PR fallback..."
gcloud --verbosity="info" storage cp "gs://$DEPLOY_BUCKET/$archive_name_zst" "gs://$DEPLOY_BUCKET/artifacts-v1-latest.tar.zst"
echoerr "> Uploaded to: https://storage.googleapis.com/$DEPLOY_BUCKET/artifacts-v1-latest.tar.zst"

echoerr "> Done."