Skip to content

chore(deps): bump actions/github-script from 8 to 9 (#16) #45

chore(deps): bump actions/github-script from 8 to 9 (#16)

chore(deps): bump actions/github-script from 8 to 9 (#16) #45

Workflow file for this run

name: E2E
on:
pull_request:
push:
branches:
- main
workflow_dispatch:
inputs:
profile:
description: Execution profile from e2e/ci.yml.
required: true
default: regression
type: string
projects:
description: Optional project override, one per line.
required: false
default: ""
type: string
labels:
description: Optional tag override, one per line.
required: false
default: ""
type: string
label-match:
description: Optional tag matching override.
required: false
default: profile
type: choice
options:
- profile
- all
- any
permissions:
contents: read
pull-requests: write
concurrency:
group: e2e-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
e2e:
name: E2E Gate
runs-on: ubuntu-latest
timeout-minutes: 45
env:
COMPOSE_PROJECT_NAME: e2e-${{ github.run_id }}-${{ github.run_attempt }}
steps:
- name: Check out repository
uses: actions/checkout@v7
- id: sut
name: Start example SUT and wait for readiness
continue-on-error: true
shell: bash
run: |
mkdir -p sut-logs
docker compose -f compose.e2e.yml up --detach --build --wait 2>&1 | tee sut-logs/startup.log
- id: e2e
name: Run E2E
if: steps.sut.outcome == 'success'
continue-on-error: true
uses: $/
env:
DEMO_RUNTIME_TOKEN: synthetic-token-not-a-secret
DEMO_RUNTIME_MESSAGE: |-
hello from the workflow
spaces, "quotes", $dollar and = survive
DEMO_UNLISTED_TOKEN: must-stay-outside-the-runner
with:
runtime-env: |
DEMO_RUNTIME_TOKEN
DEMO_RUNTIME_MESSAGE
profile: >-
${{ github.event_name == 'pull_request' && 'pull-request' ||
github.event_name == 'push' && 'main' || inputs.profile }}
projects: ${{ github.event_name == 'workflow_dispatch' && inputs.projects || '' }}
labels: ${{ github.event_name == 'workflow_dispatch' && inputs.labels || '' }}
label-match: >-
${{ github.event_name == 'workflow_dispatch' && inputs.label-match != 'profile' &&
inputs.label-match || '' }}
- id: sut-logs
name: Capture example SUT logs
if: always() && steps.sut.outcome != 'skipped'
continue-on-error: true
shell: bash
run: |
mkdir -p sut-logs
docker compose -f compose.e2e.yml logs --no-color --timestamps > sut-logs/services.log 2>&1
- id: sut-cleanup
name: Stop example SUT
if: always() && steps.sut.outcome != 'skipped'
continue-on-error: true
shell: bash
run: |
mkdir -p sut-logs
docker compose -f compose.e2e.yml down --volumes --remove-orphans > sut-logs/teardown.log 2>&1
- id: sut-artifact
name: Upload example SUT logs
if: always() && steps.sut.outcome != 'skipped'
continue-on-error: true
uses: actions/upload-artifact@v7
with:
name: sut-logs
path: sut-logs/
if-no-files-found: error
retention-days: 10
- name: Update pull request
if: always() && github.event_name == 'pull_request'
uses: actions/github-script@v9
env:
E2E_RESULT: ${{ steps.e2e.outputs.result }}
E2E_SUT_SETUP: ${{ steps.sut.outcome }}
E2E_SUT_CLEANUP: ${{ steps.sut-cleanup.outcome }}
E2E_SUT_LOGS: ${{ steps.sut-logs.outcome }}
E2E_SUT_ARTIFACT: ${{ steps.sut-artifact.outcome }}
E2E_PRIMARY_FAILURE: ${{ steps.e2e.outputs.primary-failure }}
E2E_TOTAL: ${{ steps.e2e.outputs.total }}
E2E_PASSED: ${{ steps.e2e.outputs.passed }}
E2E_FAILED: ${{ steps.e2e.outputs.failed }}
E2E_SKIPPED: ${{ steps.e2e.outputs.skipped }}
E2E_PROFILE: ${{ steps.e2e.outputs.profile }}
E2E_PROJECTS: ${{ steps.e2e.outputs.projects }}
E2E_LABELS: ${{ steps.e2e.outputs.labels }}
E2E_LABEL_MATCH: ${{ steps.e2e.outputs.label-match }}
E2E_RUNNER_CACHE_HIT: ${{ steps.e2e.outputs.runner-cache-hit }}
E2E_RUNNER_IMAGE: ${{ steps.e2e.outputs.runner-image-name }}
E2E_RESULTS_ARTIFACT: ${{ steps.e2e.outputs.results-artifact }}
E2E_REPORT_IMAGE: ${{ steps.e2e.outputs.report-image-name }}
E2E_REPORT_ARTIFACT: ${{ steps.e2e.outputs.report-image-artifact }}
with:
script: |
const marker = '<!-- playwright-e2e-report -->';
const value = (name, fallback = 'n/a') => process.env[name] || fallback;
const list = (name) => value(name).split('\n').filter(Boolean).join(', ');
const actionResult = value('E2E_RESULT', 'infrastructure-error');
const lifecycleFailures = ['E2E_SUT_SETUP', 'E2E_SUT_CLEANUP', 'E2E_SUT_LOGS', 'E2E_SUT_ARTIFACT']
.filter((name) => value(name) !== 'success');
const result = actionResult === 'failed'
? 'failed'
: lifecycleFailures.length ? 'infrastructure-error' : actionResult;
const icon = result === 'passed' ? '✅' : result === 'failed' ? '❌' : '⚠️';
const cache = value('E2E_RUNNER_CACHE_HIT', 'false') === 'true' ? 'reused' : 'built';
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
const rows = [
['Gate', `${icon} ${result}`],
['Caller SUT', `setup: ${value('E2E_SUT_SETUP')} · cleanup: ${value('E2E_SUT_CLEANUP')} · artifact: sut-logs`],
['Tests', `${value('E2E_PASSED', '0')} passed · ${value('E2E_FAILED', '0')} failed · ${value('E2E_SKIPPED', '0')} skipped · ${value('E2E_TOTAL', '0')} total`],
['Profile', value('E2E_PROFILE')],
['Projects', list('E2E_PROJECTS')],
['Tags', `${list('E2E_LABELS')} (${value('E2E_LABEL_MATCH')})`],
['Runner', `${value('E2E_RUNNER_IMAGE')} (${cache})`],
['Results', value('E2E_RESULTS_ARTIFACT')],
['Report image', `${value('E2E_REPORT_IMAGE')} · ${value('E2E_REPORT_ARTIFACT')}`],
['Run', `[Open workflow run](${runUrl})`],
];
const failureMessage = process.env.E2E_PRIMARY_FAILURE ||
(lifecycleFailures.length ? `Caller lifecycle did not succeed: ${lifecycleFailures.join(', ')}` : '');
const failure = failureMessage
? `\n> ${failureMessage}\n`
: '';
const body = [
marker,
'## E2E test report',
'',
'| | |',
'|---|---|',
...rows.map(([name, detail]) => `| ${name} | ${detail} |`),
failure,
].join('\n');
const comments = await github.paginate(github.rest.issues.listComments, {
...context.repo,
issue_number: context.issue.number,
per_page: 100,
});
const previous = comments.find((comment) =>
comment.user?.type === 'Bot' && comment.body?.includes(marker));
if (previous) {
await github.rest.issues.updateComment({
...context.repo,
comment_id: previous.id,
body,
});
} else {
await github.rest.issues.createComment({
...context.repo,
issue_number: context.issue.number,
body,
});
}
- name: Preserve E2E result
if: always()
shell: bash
env:
E2E_STEP_OUTCOME: ${{ steps.e2e.outcome }}
SUT_SETUP_OUTCOME: ${{ steps.sut.outcome }}
SUT_LOGS_OUTCOME: ${{ steps.sut-logs.outcome }}
SUT_CLEANUP_OUTCOME: ${{ steps.sut-cleanup.outcome }}
SUT_ARTIFACT_OUTCOME: ${{ steps.sut-artifact.outcome }}
run: |
for outcome in "$E2E_STEP_OUTCOME" "$SUT_SETUP_OUTCOME" "$SUT_LOGS_OUTCOME" "$SUT_CLEANUP_OUTCOME" "$SUT_ARTIFACT_OUTCOME"; do
if [[ "$outcome" != "success" ]]; then
exit 1
fi
done