mirror of
https://github.com/actualbudget/actual.git
synced 2026-11-09 10:45:04 -06:00
The /update-vrt workflow always runs from the default branch, so this container fix must land there for the desktop shard to build native modules against Electron 43's V8 headers, which gcc 11/12 (jammy) cannot parse. Matches the change to the functional-desktop-app job in e2e-test.yml on the Electron 43 upgrade branch (#8769). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
338 lines
12 KiB
YAML
338 lines
12 KiB
YAML
name: VRT Update - Generate
|
|
# SECURITY: This workflow runs in untrusted fork context with no write permissions.
|
|
# It only generates VRT patch artifacts that are later applied by vrt-update-apply.yml
|
|
# Triggered by commenting "/update-vrt" on a pull request.
|
|
on:
|
|
issue_comment:
|
|
types: [created]
|
|
|
|
permissions:
|
|
contents: read
|
|
pull-requests: read
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.event.issue.number }}
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
add-reaction:
|
|
name: Add 👀 Reaction
|
|
runs-on: depot-ubuntu-latest
|
|
# Only run on PR comments containing /update-vrt
|
|
if: >
|
|
github.event.issue.pull_request &&
|
|
startsWith(github.event.comment.body, '/update-vrt')
|
|
permissions:
|
|
pull-requests: write
|
|
steps:
|
|
- name: Add 👀 reaction to comment
|
|
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
with:
|
|
script: |
|
|
await github.rest.reactions.createForIssueComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
comment_id: context.payload.comment.id,
|
|
content: 'eyes'
|
|
});
|
|
|
|
get-pr:
|
|
name: Resolve PR details
|
|
runs-on: depot-ubuntu-latest
|
|
if: >
|
|
github.event.issue.pull_request &&
|
|
startsWith(github.event.comment.body, '/update-vrt')
|
|
outputs:
|
|
head_sha: ${{ steps.pr.outputs.head_sha }}
|
|
head_ref: ${{ steps.pr.outputs.head_ref }}
|
|
head_repo: ${{ steps.pr.outputs.head_repo }}
|
|
steps:
|
|
- name: Get PR details
|
|
id: pr
|
|
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
with:
|
|
script: |
|
|
const { data: pr } = await github.rest.pulls.get({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: context.issue.number
|
|
});
|
|
core.setOutput('head_sha', pr.head.sha);
|
|
core.setOutput('head_ref', pr.head.ref);
|
|
core.setOutput('head_repo', pr.head.repo.full_name);
|
|
|
|
build-web:
|
|
name: Build web bundle
|
|
runs-on: depot-ubuntu-latest
|
|
needs: get-pr
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
ref: ${{ needs.get-pr.outputs.head_sha }}
|
|
persist-credentials: false
|
|
|
|
- name: Set up environment
|
|
uses: ./.github/actions/setup
|
|
with:
|
|
download-translations: 'false'
|
|
- name: Build browser bundle
|
|
# REACT_APP_NETLIFY=true flips isNonProductionEnvironment() on in the
|
|
# bundle so the "Create test file" button (used by every e2e beforeEach
|
|
# via ConfigurationPage.createTestFile()) is still rendered in a
|
|
# production build. Without it, e2e tests would time out waiting for
|
|
# a button that was tree-shaken out.
|
|
# --skip-translations keeps VRT screenshots deterministic by rendering
|
|
# source-code English instead of upstream Weblate en.json (which can
|
|
# drift between snapshot capture and test runs).
|
|
env:
|
|
REACT_APP_NETLIFY: 'true'
|
|
run: yarn build:browser --skip-translations
|
|
- name: Upload build artifact
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: desktop-client-build
|
|
path: packages/desktop-client/build/
|
|
retention-days: 1
|
|
overwrite: true
|
|
|
|
browser-vrt:
|
|
name: Browser VRT (shard ${{ matrix.shard }}/3)
|
|
runs-on: depot-ubuntu-latest
|
|
needs: [get-pr, build-web]
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
shard: [1, 2, 3]
|
|
container:
|
|
image: mcr.microsoft.com/playwright:v1.61.1-jammy
|
|
env:
|
|
E2E_USE_BUILD: '1'
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
ref: ${{ needs.get-pr.outputs.head_sha }}
|
|
persist-credentials: false
|
|
|
|
- name: Trust workspace directory
|
|
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
|
shell: bash
|
|
|
|
- name: Set up environment
|
|
uses: ./.github/actions/setup
|
|
with:
|
|
download-translations: 'false'
|
|
- name: Download web build
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
name: desktop-client-build
|
|
path: packages/desktop-client/build/
|
|
- name: Run VRT Tests
|
|
continue-on-error: true
|
|
run: yarn vrt --update-snapshots --shard=${{ matrix.shard }}/3
|
|
- name: Create shard patch with PNG changes only
|
|
id: create-patch
|
|
run: |
|
|
git config --global user.name "github-actions[bot]"
|
|
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
|
|
git add "**/*.png"
|
|
|
|
if git diff --staged --quiet; then
|
|
echo "has_changes=false" >> "$GITHUB_OUTPUT"
|
|
echo "No VRT changes in this shard"
|
|
exit 0
|
|
fi
|
|
|
|
echo "has_changes=true" >> "$GITHUB_OUTPUT"
|
|
|
|
git commit -m "Update VRT screenshots (browser shard ${{ matrix.shard }})"
|
|
git format-patch -1 HEAD --stdout > vrt-shard.patch
|
|
|
|
# Validate patch only contains PNG files. `git format-patch` emits a
|
|
# `GIT binary patch` block for PNGs (no +++/--- lines), so check
|
|
# `diff --git` headers — those are present for both text and binary.
|
|
if grep -E '^diff --git ' vrt-shard.patch \
|
|
| grep -vE '^diff --git a/[^[:space:]]+\.png b/[^[:space:]]+\.png$'; then
|
|
echo "ERROR: Shard patch contains non-PNG files!"
|
|
exit 1
|
|
fi
|
|
- name: Upload shard patch
|
|
if: steps.create-patch.outputs.has_changes == 'true'
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: vrt-shard-browser-${{ matrix.shard }}
|
|
path: vrt-shard.patch
|
|
retention-days: 1
|
|
overwrite: true
|
|
|
|
desktop-vrt:
|
|
name: Desktop VRT
|
|
runs-on: depot-ubuntu-latest
|
|
needs: get-pr
|
|
container:
|
|
# noble (gcc 13) is required to compile native modules against Electron 43+ headers;
|
|
# jammy's gcc 11/12 cannot parse them. Keep in sync with the functional-desktop-app job in e2e-test.yml.
|
|
image: mcr.microsoft.com/playwright:v1.61.1-noble
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
ref: ${{ needs.get-pr.outputs.head_sha }}
|
|
persist-credentials: false
|
|
|
|
- name: Trust workspace directory
|
|
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
|
shell: bash
|
|
|
|
- name: Set up environment
|
|
uses: ./.github/actions/setup
|
|
with:
|
|
download-translations: 'false'
|
|
|
|
# Build tools are needed to rebuild native modules like better-sqlite3 used by the Desktop app, which is required to run VRT tests on the Desktop app and generate updated snapshots.
|
|
- name: Install build tools
|
|
run: apt-get update && apt-get install -y build-essential python3
|
|
|
|
- name: Run Desktop VRT Tests
|
|
continue-on-error: true
|
|
run: |
|
|
yarn rebuild-electron
|
|
xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24" -- yarn e2e:desktop --update-snapshots
|
|
|
|
- name: Create shard patch with PNG changes only
|
|
id: create-patch
|
|
run: |
|
|
git config --global user.name "github-actions[bot]"
|
|
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
|
|
git add "**/*.png"
|
|
|
|
if git diff --staged --quiet; then
|
|
echo "has_changes=false" >> "$GITHUB_OUTPUT"
|
|
echo "No VRT changes in desktop shard"
|
|
exit 0
|
|
fi
|
|
|
|
echo "has_changes=true" >> "$GITHUB_OUTPUT"
|
|
|
|
git commit -m "Update VRT screenshots (desktop)"
|
|
git format-patch -1 HEAD --stdout > vrt-shard.patch
|
|
|
|
# See validation note in browser-vrt above.
|
|
if grep -E '^diff --git ' vrt-shard.patch \
|
|
| grep -vE '^diff --git a/[^[:space:]]+\.png b/[^[:space:]]+\.png$'; then
|
|
echo "ERROR: Desktop shard patch contains non-PNG files!"
|
|
exit 1
|
|
fi
|
|
|
|
- name: Upload shard patch
|
|
if: steps.create-patch.outputs.has_changes == 'true'
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: vrt-shard-desktop
|
|
path: vrt-shard.patch
|
|
retention-days: 1
|
|
overwrite: true
|
|
|
|
merge-patch:
|
|
name: Merge VRT Patches
|
|
runs-on: depot-ubuntu-latest
|
|
needs: [get-pr, browser-vrt, desktop-vrt]
|
|
if: ${{ !cancelled() && needs.get-pr.result == 'success' }}
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
ref: ${{ needs.get-pr.outputs.head_sha }}
|
|
persist-credentials: false
|
|
|
|
- name: Download all shard patches
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
path: /tmp/shard-patches
|
|
pattern: vrt-shard-*
|
|
|
|
- name: Merge shard patches
|
|
id: create-patch
|
|
shell: bash
|
|
run: |
|
|
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
|
git config --global user.name "github-actions[bot]"
|
|
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
|
|
# actions/download-artifact puts a lone matched artifact directly in
|
|
# `path` but gives each of several its own `path/<name>/` subdir, so
|
|
# recurse instead of globbing `*/vrt-shard.patch` (which would miss
|
|
# the common single-shard case).
|
|
mapfile -t patches < <(find /tmp/shard-patches -type f -name 'vrt-shard.patch' | sort)
|
|
|
|
if [ ${#patches[@]} -eq 0 ]; then
|
|
echo "has_changes=false" >> "$GITHUB_OUTPUT"
|
|
echo "No shard patches to merge"
|
|
exit 0
|
|
fi
|
|
|
|
# Defense in depth: re-validate every shard patch before applying.
|
|
# See validation note in browser-vrt above for why we match
|
|
# `diff --git` headers instead of +++/--- lines.
|
|
for patch in "${patches[@]}"; do
|
|
echo "Validating $patch"
|
|
if grep -E '^diff --git ' "$patch" \
|
|
| grep -vE '^diff --git a/[^[:space:]]+\.png b/[^[:space:]]+\.png$'; then
|
|
echo "ERROR: $patch contains non-PNG files!"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Apply each shard patch. Shards touch disjoint PNG files so
|
|
# order does not matter. --index stages the applied changes.
|
|
for patch in "${patches[@]}"; do
|
|
echo "Applying $patch"
|
|
git apply --index "$patch"
|
|
done
|
|
|
|
if git diff --staged --quiet; then
|
|
echo "has_changes=false" >> "$GITHUB_OUTPUT"
|
|
echo "No VRT changes after merge"
|
|
exit 0
|
|
fi
|
|
|
|
echo "has_changes=true" >> "$GITHUB_OUTPUT"
|
|
|
|
git commit -m "Update VRT screenshots"
|
|
git format-patch -1 HEAD --stdout > vrt-update.patch
|
|
|
|
# Final guard on the combined patch.
|
|
if grep -E '^diff --git ' vrt-update.patch \
|
|
| grep -vE '^diff --git a/[^[:space:]]+\.png b/[^[:space:]]+\.png$'; then
|
|
echo "ERROR: Merged patch contains non-PNG files!"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Merged patch created successfully with PNG changes only"
|
|
|
|
- name: Upload patch artifact
|
|
if: steps.create-patch.outputs.has_changes == 'true'
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: vrt-patch-${{ github.event.issue.number }}
|
|
path: vrt-update.patch
|
|
retention-days: 5
|
|
|
|
- name: Save PR metadata
|
|
if: steps.create-patch.outputs.has_changes == 'true'
|
|
run: |
|
|
mkdir -p pr-metadata
|
|
echo "${{ github.event.issue.number }}" > pr-metadata/pr-number.txt
|
|
echo "${NEEDS_GET_PR_OUTPUTS_HEAD_REF}" > pr-metadata/head-ref.txt
|
|
echo "${NEEDS_GET_PR_OUTPUTS_HEAD_REPO}" > pr-metadata/head-repo.txt
|
|
env:
|
|
NEEDS_GET_PR_OUTPUTS_HEAD_REF: ${{ needs.get-pr.outputs.head_ref }}
|
|
NEEDS_GET_PR_OUTPUTS_HEAD_REPO: ${{ needs.get-pr.outputs.head_repo }}
|
|
|
|
- name: Upload PR metadata
|
|
if: steps.create-patch.outputs.has_changes == 'true'
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: vrt-metadata-${{ github.event.issue.number }}
|
|
path: pr-metadata/
|
|
retention-days: 5
|