Skip to content

feat: Add UI components for Ledger status screens #115262

feat: Add UI components for Ledger status screens

feat: Add UI components for Ledger status screens #115262

name: Update LavaMoat policies
on:
issue_comment:
types: created
concurrency:
group: update-lavamoat-policies-${{ github.event.issue.number }}
cancel-in-progress: true
jobs:
prepare:
name: Prepare
# Only run when the comment is on a pull request containing '@metamaskbot update-policies'
if: ${{ github.event.issue.pull_request && startsWith(github.event.comment.body, '@metamaskbot update-policies') }}
runs-on: ubuntu-latest
timeout-minutes: 5
env:
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.issue.number }}
COMMENT_ID: ${{ github.event.comment.id }}
permissions:
contents: read
pull-requests: read
id-token: write
outputs:
IS_CROSS_REPO_PR: ${{ steps.is-cross-repo.outputs.IS_CROSS_REPO_PR }}
RUN_ID: ${{ steps.find-ci-run.outputs.RUN_ID }}
NO_CI_RUN: ${{ steps.find-ci-run.outputs.NO_CI_RUN }}
VALIDATION_PENDING: ${{ steps.find-ci-run.outputs.VALIDATION_PENDING }}
VALIDATION_SKIPPED: ${{ steps.find-ci-run.outputs.VALIDATION_SKIPPED }}
VALIDATION_FAILED: ${{ steps.find-ci-run.outputs.VALIDATION_FAILED }}
FAILED_JOBS: ${{ steps.find-ci-run.outputs.FAILED_JOBS }}
steps:
- name: Determine whether this PR is cross-repo
id: is-cross-repo
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: echo "IS_CROSS_REPO_PR=$(gh pr view "${PR_NUMBER}" --repo "${REPO}" --json isCrossRepository --jq '.isCrossRepository')" >> "$GITHUB_OUTPUT"
- name: Get token
if: ${{ steps.is-cross-repo.outputs.IS_CROSS_REPO_PR == 'false' }}
id: token
uses: MetaMask/github-tools/.github/actions/get-token@v1
with:
token-exchange-url: ${{ vars.TOKEN_EXCHANGE_URL }}
permissions: |
actions: read
contents: read
pull_requests: write
- name: React to the comment
if: ${{ steps.is-cross-repo.outputs.IS_CROSS_REPO_PR == 'false' }}
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"/repos/${REPO}/issues/comments/${COMMENT_ID}/reactions" \
-f content='+1'
- name: Find CI run for PR head commit
if: ${{ steps.is-cross-repo.outputs.IS_CROSS_REPO_PR == 'false' }}
id: find-ci-run
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
HEAD_SHA=$(gh pr view "${PR_NUMBER}" --repo "${REPO}" --json headRefOid --jq '.headRefOid')
echo "Looking for main.yml run for commit ${HEAD_SHA}..."
RUN_ID=$(gh run list \
--workflow=main.yml \
--repo "${REPO}" \
--commit="${HEAD_SHA}" \
--limit=1 \
--json databaseId \
--jq '.[0].databaseId // empty')
if [ -z "$RUN_ID" ]; then
echo "No CI run found"
echo "NO_CI_RUN=true" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Found run ${RUN_ID}, checking validation job status..."
JOBS_JSON=$(gh api "/repos/${REPO}/actions/runs/${RUN_ID}/jobs" --paginate \
--jq '[.jobs[] | select(.name | startswith("validate-lavamoat-policies"))]')
JOB_COUNT=$(echo "$JOBS_JSON" | jq 'length')
if [ "$JOB_COUNT" -eq 0 ]; then
echo "No validation jobs found in CI run (validation may have been skipped)"
echo "VALIDATION_SKIPPED=true" >> "$GITHUB_OUTPUT"
echo "RUN_ID=${RUN_ID}" >> "$GITHUB_OUTPUT"
exit 0
fi
PENDING=$(echo "$JOBS_JSON" | jq '[.[] | select(.status != "completed")] | length')
if [ "$PENDING" -gt 0 ]; then
echo "LavaMoat validation still running"
echo "VALIDATION_PENDING=true" >> "$GITHUB_OUTPUT"
exit 0
fi
FAILED_JOBS=$(echo "$JOBS_JSON" | jq -r '[.[] | select(.conclusion != "success") | "- [" + .name + "](" + .html_url + ") (" + .conclusion + ")"] | join("\n")')
echo "RUN_ID=${RUN_ID}" >> "$GITHUB_OUTPUT"
if [ -n "$FAILED_JOBS" ]; then
echo "LavaMoat validation completed with non-success conclusions — policy diffs may exist"
echo "VALIDATION_FAILED=true" >> "$GITHUB_OUTPUT"
{
echo 'FAILED_JOBS<<EOF'
echo "$FAILED_JOBS"
echo 'EOF'
} >> "$GITHUB_OUTPUT"
else
echo "LavaMoat validation completed — all policies up to date"
fi
apply-and-commit:
name: Apply policy diffs and commit
needs: prepare
if: ${{ !cancelled() && needs.prepare.outputs.IS_CROSS_REPO_PR == 'false' }}
runs-on: ubuntu-latest
timeout-minutes: 10
env:
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.issue.number }}
RUN_ID: ${{ needs.prepare.outputs.RUN_ID }}
NO_CI_RUN: ${{ needs.prepare.outputs.NO_CI_RUN }}
VALIDATION_PENDING: ${{ needs.prepare.outputs.VALIDATION_PENDING }}
VALIDATION_SKIPPED: ${{ needs.prepare.outputs.VALIDATION_SKIPPED }}
VALIDATION_FAILED: ${{ needs.prepare.outputs.VALIDATION_FAILED }}
FAILED_JOBS: ${{ needs.prepare.outputs.FAILED_JOBS }}
ACTION_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
permissions:
contents: read
id-token: write
steps:
- name: Get token
id: token
uses: MetaMask/github-tools/.github/actions/get-token@v1
with:
token-exchange-url: ${{ vars.TOKEN_EXCHANGE_URL }}
permissions: |
actions: read
contents: write
pull_requests: write
- name: Checkout repository
if: ${{ env.VALIDATION_FAILED == 'true' }}
uses: actions/checkout@v6
with:
token: ${{ steps.token.outputs.token }}
- name: Checkout pull request
if: ${{ env.VALIDATION_FAILED == 'true' }}
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: gh pr checkout "${PR_NUMBER}"
- name: Download policy diffs from CI
if: ${{ env.VALIDATION_FAILED == 'true' }}
uses: actions/download-artifact@v7
with:
path: lavamoat-policy-diffs
pattern: lavamoat-policy-diff-*
merge-multiple: true
run-id: ${{ env.RUN_ID }}
github-token: ${{ steps.token.outputs.token }}
- name: Check for policy diffs
if: ${{ !cancelled() }}
id: check-diffs
run: echo "HAS_DIFFS=$(compgen -G 'lavamoat-policy-diffs/*.patch' > /dev/null 2>&1 && echo true || echo false)" >> "$GITHUB_OUTPUT"
- name: Apply policy diffs
if: ${{ steps.check-diffs.outputs.HAS_DIFFS == 'true' }}
run: |
for patch in lavamoat-policy-diffs/*.patch; do
echo "Applying ${patch}..."
git apply "${patch}"
done
- name: Commit the updated policies
if: ${{ steps.check-diffs.outputs.HAS_DIFFS == 'true' }}
run: |
git config --global user.name 'MetaMask Bot'
git config --global user.email 'metamaskbot@users.noreply.github.com'
git commit -am "Update LavaMoat policies"
git push
- name: Compare policy changes
if: ${{ steps.check-diffs.outputs.HAS_DIFFS == 'true' }}
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
BASE_REF=$(gh pr view "${PR_NUMBER}" --json baseRefName --jq .baseRefName)
git fetch origin "${BASE_REF}"
compare_policies() {
local main_dir="$1"
local parent_dir="$2"
git diff "origin/${BASE_REF}" -- "${main_dir}policy.json" > /tmp/main_policy_diff
for folder in "${parent_dir}"*/; do
if [ "$folder" != "$main_dir" ]; then
local file="${folder}policy.json"
if [ -f "$file" ]; then
if diff -q /tmp/main_policy_diff <(git diff "origin/${BASE_REF}" -- "$file") > /dev/null 2>&1; then
echo "✅ ${file} changes match ${main_dir}policy.json changes"
else
echo "👀 ${file} changes **differ from** ${main_dir}policy.json changes"
fi
fi
fi
done
}
{
compare_policies "lavamoat/browserify/main/" "lavamoat/browserify/"
compare_policies "lavamoat/webpack/mv2/main/" "lavamoat/webpack/mv2/"
compare_policies "lavamoat/webpack/mv3/main/" "lavamoat/webpack/mv3/"
} > does_diff_diff.txt
- name: Post comment (policies updated)
if: ${{ steps.check-diffs.outputs.HAS_DIFFS == 'true' }}
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
echo -e 'Policies updated. \n👀 Please review the diff for suspicious new powers. \n\n> [!TIP] \n> Follow the policy review process outlined in the [LavaMoat Policy Review Process doc](https://github.com/MetaMask/metamask-extension/blob/main/docs/lavamoat-policy-review-process.md) before expecting an approval from Policy Reviewers. \n🧠 Learn how to read policy diffs: https://lavamoat.github.io/guides/policy-diff/#what-to-look-for-when-reviewing-a-policy-diff \n\n' | cat - does_diff_diff.txt | gh pr comment "${PR_NUMBER}" --repo "${REPO}" --body-file -
- name: Post comment (no CI run found)
if: ${{ needs.prepare.result == 'success' && env.NO_CI_RUN == 'true' }}
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
gh pr comment "${PR_NUMBER}" --repo "${REPO}" --body "No CI run found for this commit. Please wait for CI to start and retry \`@metamaskbot update-policies\`."
- name: Post comment (validation still running)
if: ${{ needs.prepare.result == 'success' && env.VALIDATION_PENDING == 'true' }}
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
gh pr comment "${PR_NUMBER}" --repo "${REPO}" --body "LavaMoat validation is still running. Please retry \`@metamaskbot update-policies\` after CI validation completes."
- name: Post comment (validation failed but no diffs available)
if: ${{ !cancelled() && env.VALIDATION_FAILED == 'true' && steps.check-diffs.outputs.HAS_DIFFS != 'true' }}
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
printf 'LavaMoat validation failed but no policy diffs were produced (the validation job may have crashed before generating diffs).\n\nFailed jobs:\n%s' "$FAILED_JOBS" | gh pr comment "${PR_NUMBER}" --repo "${REPO}" --body-file -
- name: Post comment (validation skipped)
if: ${{ needs.prepare.result == 'success' && env.VALIDATION_SKIPPED == 'true' }}
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
gh pr comment "${PR_NUMBER}" --repo "${REPO}" --body "LavaMoat validation was skipped in CI. Policies were not checked for this commit."
- name: Post comment (no policy changes)
if: ${{ needs.prepare.result == 'success' && env.RUN_ID && env.VALIDATION_FAILED != 'true' && !env.VALIDATION_PENDING && env.VALIDATION_SKIPPED != 'true' }}
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
gh pr comment "${PR_NUMBER}" --repo "${REPO}" --body "No policy changes"
- name: Post comment if the update failed
if: ${{ (failure() && !(env.VALIDATION_FAILED == 'true' && steps.check-diffs.outputs.HAS_DIFFS != 'true')) || needs.prepare.result == 'failure' }}
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
gh pr comment "${PR_NUMBER}" --repo "${REPO}" --body "Policy update failed. You can [review the logs or retry the policy update here](${ACTION_RUN_URL})"