Skip to content

mripper

mripper #111

Workflow file for this run

name: mripper
on:
schedule:
- cron: "0 15 * * *"
workflow_dispatch:
inputs:
image:
description: "GCP image"
required: false
default: "projects/ubuntu-os-cloud/global/images/ubuntu-2404-noble-amd64-v20260225"
type: string
permissions:
contents: write
env:
PROJECT: flashbots-tests
IMAGE: ${{ inputs.image || 'projects/ubuntu-os-cloud/global/images/ubuntu-2404-noble-amd64-v20260225' }}
NETWORK: default
SUBNET: default
jobs:
rip:
strategy:
fail-fast: false
matrix:
include:
- zone: us-east4-a
machine_type: c3-standard-4
- zone: us-east4-a
machine_type: c3-standard-8
- zone: us-east4-a
machine_type: c3-standard-22
- zone: us-east4-a
machine_type: c3-standard-44
- zone: us-east5-b
machine_type: c3-standard-4
# No quota
# - zone: us-east5-b
# machine_type: c3-standard-22
# - zone: us-east5-b
# machine_type: c3-standard-44
- zone: europe-west4-a
machine_type: c3-standard-4
- zone: europe-west4-a
machine_type: c3-standard-22
- zone: europe-west4-a
machine_type: c3-standard-44
- zone: asia-northeast1-b
machine_type: c3-standard-4
- zone: asia-northeast1-b
machine_type: c3-standard-22
- zone: asia-northeast1-b
machine_type: c3-standard-44
runs-on: ubuntu-latest
name: "${{ matrix.zone }} / ${{ matrix.machine_type }}"
env:
INSTANCE_NAME: "mr-${{ matrix.zone }}-${{ matrix.machine_type }}-${{ github.run_id }}"
ZONE: ${{ matrix.zone }}
MACHINE_TYPE: ${{ matrix.machine_type }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Authenticate to GCP
uses: google-github-actions/auth@v3
with:
credentials_json: "${{ secrets.GCP_SA_KEY }}"
- name: Set up gcloud
uses: google-github-actions/setup-gcloud@v3
- name: Create VM
run: |
FIREWALL_RULE="${INSTANCE_NAME}-ssh"
echo "FIREWALL_RULE=${FIREWALL_RULE}" >> "$GITHUB_ENV"
gcloud compute instances create "$INSTANCE_NAME" \
--project="$PROJECT" \
--zone="$ZONE" \
--machine-type="$MACHINE_TYPE" \
--image="$IMAGE" \
--network="$NETWORK" \
--subnet="$SUBNET" \
--confidential-compute-type=TDX \
--maintenance-policy=TERMINATE \
--no-shielded-secure-boot \
--no-shielded-vtpm \
--boot-disk-size=10GB \
--boot-disk-type=pd-balanced \
--tags="$INSTANCE_NAME"
gcloud compute firewall-rules create "$FIREWALL_RULE" \
--project="$PROJECT" \
--network="$NETWORK" \
--allow=tcp:22 \
--target-tags="$INSTANCE_NAME" \
--direction=INGRESS
- name: Wait for SSH
run: |
for i in $(seq 1 60); do
if gcloud compute ssh "$INSTANCE_NAME" \
--project="$PROJECT" --zone="$ZONE" \
--command="true" --quiet 2>/dev/null; then
echo "SSH is ready"
exit 0
fi
sleep 5
done
echo "::error::Timed out waiting for SSH"
exit 1
- name: Run computed measurement
run: |
gcloud compute scp ./rip.sh "${INSTANCE_NAME}:/tmp/rip.sh" \
--project="$PROJECT" --zone="$ZONE" --quiet
gcloud compute ssh "$INSTANCE_NAME" \
--project="$PROJECT" --zone="$ZONE" \
--command="chmod +x /tmp/rip.sh && sudo /tmp/rip.sh computed"
- name: Fetch computed measurement
run: |
mkdir -p mr
gcloud compute scp "${INSTANCE_NAME}:/tmp/dcap-computed.json" ./dcap-computed.json \
--project="$PROJECT" --zone="$ZONE" --quiet
- name: Compare with existing measurement
id: compare
run: |
PREFIX="${ZONE}_${MACHINE_TYPE}"
FILES=$(ls mr/${PREFIX}_*.json 2>/dev/null || true)
if [[ -z "$FILES" ]]; then
echo "No existing measurements found for ${PREFIX}"
echo "changed=true" >> "$GITHUB_OUTPUT"
# All registers are new
jq -r 'keys[]' ./dcap-computed.json | tr '\n' ',' | sed 's/,$//' > /tmp/changed-registers.txt
else
MATCHED=""
for f in $FILES; do
if diff -q <(jq -S . "$f") <(jq -S . ./dcap-computed.json) >/dev/null 2>&1; then
MATCHED="$f"
break
fi
done
if [[ -n "$MATCHED" ]]; then
echo "Computed DCAP measurement MATCHES existing: $MATCHED"
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "Computed DCAP measurement DIFFERS from all existing measurements"
echo "changed=true" >> "$GITHUB_OUTPUT"
# Diff against the latest file to identify which registers changed
LATEST=$(ls -t mr/${PREFIX}_*.json | head -1)
CHANGED_REGS=""
for key in $(jq -r 'keys[]' ./dcap-computed.json); do
OLD=$(jq -S --arg k "$key" '.[$k]' "$LATEST")
NEW=$(jq -S --arg k "$key" '.[$k]' ./dcap-computed.json)
if [[ "$OLD" != "$NEW" ]]; then
CHANGED_REGS="${CHANGED_REGS:+${CHANGED_REGS},}${key}"
fi
done
echo "${CHANGED_REGS:-unknown}" > /tmp/changed-registers.txt
fi
fi
- name: Run raw measurement
if: steps.compare.outputs.changed == 'true'
run: |
gcloud compute ssh "$INSTANCE_NAME" \
--project="$PROJECT" --zone="$ZONE" \
--command="sudo /tmp/rip.sh raw"
- name: Fetch raw measurement
if: steps.compare.outputs.changed == 'true'
run: |
mkdir -p dcap-raw
gcloud compute scp "${INSTANCE_NAME}:/tmp/dcap-raw" ./dcap-raw-result \
--project="$PROJECT" --zone="$ZONE" --quiet
- name: Save results
if: steps.compare.outputs.changed == 'true'
run: |
TIMESTAMP=$(date +%Y-%m-%dT%H%M%S)
PREFIX="${ZONE}_${MACHINE_TYPE}"
MR_FILE="mr/${PREFIX}_${TIMESTAMP}.json"
RAW_FILE="dcap-raw/${PREFIX}_${TIMESTAMP}"
cp ./dcap-computed.json "$MR_FILE"
cp ./dcap-raw-result "$RAW_FILE"
# Save paths for the change summary artifact
echo "$MR_FILE" > /tmp/mr-path.txt
echo "$RAW_FILE" > /tmp/raw-path.txt
- name: Upload change summary
if: steps.compare.outputs.changed == 'true'
uses: actions/upload-artifact@v4
with:
name: "change-${{ matrix.zone }}-${{ matrix.machine_type }}"
path: |
/tmp/changed-registers.txt
/tmp/mr-path.txt
/tmp/raw-path.txt
- name: Commit and push
if: steps.compare.outputs.changed == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
PREFIX="${ZONE}_${MACHINE_TYPE}"
git add "mr/${PREFIX}_"*.json "dcap-raw/${PREFIX}_"*
if git diff --cached --quiet; then
echo "No changes to commit"
else
git commit -m "mripper: new measurement for ${PREFIX}"
for i in 1 2 3 4 5; do
git pull --rebase && git push && exit 0
sleep $((i * 2))
done
echo "::error::Failed to push after 5 attempts"
exit 1
fi
- name: Cleanup VM
if: always()
run: |
gcloud compute firewall-rules delete "$FIREWALL_RULE" \
--project="$PROJECT" --quiet 2>/dev/null || true
gcloud compute instances delete "$INSTANCE_NAME" \
--project="$PROJECT" --zone="$ZONE" --quiet 2>/dev/null || true
notify:
needs: rip
if: always()
runs-on: ubuntu-latest
name: Slack notification
steps:
- name: Download change summaries
uses: actions/download-artifact@v8
with:
pattern: "change-*"
path: changes
continue-on-error: true
- name: Build and send Slack message
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
run: |
# Check if any changes were detected
if [[ ! -d changes ]] || [[ -z "$(ls changes/)" ]]; then
echo "No measurement changes detected, skipping notification"
exit 0
fi
# Build the details section from each artifact
# Artifact dirs are named: change-{zone}-{machine_type}
DETAILS=""
for dir in changes/change-*; do
[[ -d "$dir" ]] || continue
# Parse zone and machine type from directory name
NAME=$(basename "$dir")
# Strip "change-" prefix
COMBO="${NAME#change-}"
# Split on last hyphen-delimited segment that starts with c3
# e.g. us-east4-a-c3-standard-4 -> zone=us-east4-a machine=c3-standard-4
ZONE=$(echo "$COMBO" | sed 's/-\(c3-.*\)$//')
MACHINE=$(echo "$COMBO" | grep -o 'c3-.*')
REGISTERS=$(cat "$dir/changed-registers.txt" 2>/dev/null || echo "unknown")
MR_PATH=$(cat "$dir/mr-path.txt" 2>/dev/null || true)
RAW_PATH=$(cat "$dir/raw-path.txt" 2>/dev/null || true)
REPO_URL="${{ github.server_url }}/${{ github.repository }}/blob/main"
LINKS=""
[[ -n "$MR_PATH" ]] && LINKS="<${REPO_URL}/${MR_PATH}|computed>"
[[ -n "$RAW_PATH" ]] && LINKS="${LINKS:+${LINKS}, }<${REPO_URL}/${RAW_PATH}|raw>"
DETAILS="${DETAILS}\n• *${ZONE}* / \`${MACHINE}\` — changed: \`${REGISTERS}\` (${LINKS})"
done
if [[ -z "$DETAILS" ]]; then
echo "No change details found, skipping notification"
exit 0
fi
# Send Slack message
PAYLOAD=$(cat <<SLACK
{
"text": "Measurements changed after a TCB update",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": ":warning: Measurements changed after a TCB update"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "New DCAP measurements were detected that differ from all previously recorded values. Consider updating your offline measurement tools to support the new TCB.\n${DETAILS}"
}
},
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View workflow run>"
}
]
}
]
}
SLACK
)
curl -sf -X POST -H 'Content-type: application/json' --data "$PAYLOAD" "$SLACK_WEBHOOK_URL"