@Desktop • UI e2e • Test App triggered by Sheng-Long on ref develop #38
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: "@Desktop • UI e2e • Test App" | |
run-name: "@Desktop • UI e2e • Test App triggered by ${{ inputs.login || github.actor }} ${{ format('on ref {0}', github.ref_name) }}" | |
on: | |
schedule: | |
- cron: "0 5 * * 1-5" | |
workflow_dispatch: | |
inputs: | |
ref: | |
description: the branch which triggered this workflow | |
required: false | |
login: | |
description: The GitHub username that triggered the workflow | |
required: false | |
base_ref: | |
description: The base branch to merge the head into when checking out the code | |
required: false | |
test_filter: | |
description: Filter test pattern to execute only tests suites named according to pattern(s) separated by '|' (e.g. to execute accounts and settings describe blocks "Accounts @smoke" or "Accounts @smoke|Settings") | |
required: false | |
invert_filter: | |
description: Ignore test having name pattern (entered in the previous field) | |
type: boolean | |
default: false | |
speculos_tests: | |
description: Run the speculos tests (if false, mocked tests will be run instead) | |
type: boolean | |
default: true | |
enable_broadcast: | |
description: Enable transaction broadcast | |
type: boolean | |
default: false | |
report_path: | |
description: Path where you want to store this execution's results | |
required: false | |
default: "allure-results-linux" | |
slack_notif: | |
description: "Send notification to Slack?" | |
required: false | |
type: boolean | |
default: false | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref_name != 'develop' && github.ref || github.run_id }} | |
cancel-in-progress: true | |
permissions: | |
id-token: write | |
contents: read | |
jobs: | |
e2e-tests-linux: | |
name: "Desktop Tests E2E (Ubuntu)" | |
outputs: | |
status: ${{ steps.tests.outcome }} | |
env: | |
NODE_OPTIONS: "--max-old-space-size=7168" | |
INSTRUMENT_BUILD: true | |
FORCE_COLOR: 3 | |
CI_OS: "ubuntu-latest" | |
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 | |
# DEBUG: "pw:browser*" | |
# DEBUG_LOGS: 1 | |
runs-on: [ledger-live-4xlarge] | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
ref: ${{ inputs.ref || github.sha }} | |
- name: Setup caches | |
id: caches | |
uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop | |
with: | |
skip-turbo-cache: "false" | |
accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} | |
roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} | |
region: ${{ secrets.AWS_CACHE_REGION }} | |
turbo-server-token: ${{ secrets.TURBOREPO_SERVER_TOKEN }} | |
- uses: LedgerHQ/ledger-live/tools/actions/composites/setup-test-desktop@develop | |
id: setup-test-desktop | |
with: | |
skip_ruby: true | |
install_playwright: true | |
turborepo-server-port: ${{ steps.caches.outputs.port }} | |
- name: generate token | |
id: generate-token | |
uses: tibdex/github-app-token@v1 | |
with: | |
app_id: ${{ secrets.GH_BOT_APP_ID }} | |
private_key: ${{ secrets.GH_BOT_PRIVATE_KEY }} | |
- name: Retrieving coin apps | |
uses: actions/checkout@v4 | |
with: | |
ref: generated/ledger-live-bot | |
repository: LedgerHQ/coin-apps | |
token: ${{ steps.generate-token.outputs.token }} | |
path: coin-apps | |
- name: pull docker image | |
run: docker pull ghcr.io/ledgerhq/speculos:sha-e262a0c | |
shell: bash | |
- name: Run playwright tests [Linux => xvfb-run] | |
id: tests | |
run: | | |
export COINAPPS=$PWD/coin-apps | |
if [ "$ENABLE_BROADCAST" = true ]; then export ENABLE_TRANSACTION_BROADCAST=1; fi | |
if [ "$SPECULOS_TESTS" = true ]; then export MOCK=0 && speculos_tests=":speculos"; fi | |
if [ "${{ inputs.invert_filter }}" = true ]; then invert_filter="-invert"; fi | |
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- pnpm desktop test:playwright$speculos_tests ${INPUTS_TEST_FILTER:+--grep$invert_filter} "${{ inputs.test_filter }}" | |
env: | |
INPUTS_TEST_FILTER: ${{ inputs.test_filter }} | |
SEED: ${{ secrets.SEED_QAA_B2C }} | |
ENABLE_BROADCAST: ${{ contains(inputs.enable_broadcast, 'true') }} | |
SPECULOS_TESTS: ${{ !contains(inputs.speculos_tests, 'false') }} | |
- name: upload diffs to s3 | |
if: ${{ !cancelled() }} | |
uses: LedgerHQ/ledger-live/tools/actions/upload-images@develop | |
id: s3 | |
with: | |
path: apps/ledger-live-desktop/tests/artifacts/test-results | |
workspace: ${{ github.workspace }} | |
os: linux | |
group-name: ${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_number }} | |
- name: upload ci suggested screenshots | |
if: ${{ !cancelled() }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: images | |
path: images-linux.json | |
- name: Upload playwright test results [On Failure] | |
uses: actions/upload-artifact@v4 | |
if: failure() && !cancelled() | |
with: | |
name: playwright-results-linux | |
path: | | |
apps/ledger-live-desktop/tests/artifacts/test-results | |
apps/ledger-live-desktop/tests/artifacts/html-report | |
apps/ledger-live-desktop/tests/artifacts/coverage | |
apps/ledger-live-desktop/tests/artifacts/videos | |
apps/ledger-live-desktop/tests/artifacts/logs | |
apps/ledger-live-desktop/tests/artifacts/*.log | |
- name: Upload Allure Report | |
if: ${{ !cancelled() }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: allure-results-linux | |
path: apps/ledger-live-desktop/allure-results | |
- name: Upload Allure Results | |
uses: actions/[email protected] | |
with: | |
name: "allure-results" | |
path: "apps/ledger-live-desktop/allure-results" | |
- name: Publish report on Allure Server | |
id: allure-server | |
if: ${{ !cancelled() }} | |
uses: LedgerHQ/[email protected] | |
with: | |
allure-server-url: "https://ledger-live.allure.green.ledgerlabs.net" | |
build-name: ${{ github.workflow }} | |
build-url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
username: ${{ vars.ALLURE_USERNAME }} | |
password: ${{ secrets.ALLURE_LEDGER_LIVE_PASSWORD }} | |
path: ${{ github.ref_name }}/linux | |
allure-results: "apps/ledger-live-desktop/allure-results" | |
- name: Write Allure report in summary | |
if: ${{ !cancelled() }} | |
shell: bash | |
run: echo "::notice title=Allure report URL::${{ steps.allure-server.outputs.report-url }}" | |
- name: Get summary | |
if: ${{ !cancelled() }} | |
shell: bash | |
run: | | |
cd apps/ledger-live-desktop | |
allure generate | |
cd allure-report/widgets | |
passedTests=$(jq '.statistic.passed' summary.json) | |
failedTests=$(jq '.statistic.failed' summary.json) | |
brokenTests=$(jq '.statistic.broken' summary.json) | |
skippedTests=$(jq '.statistic.skipped' summary.json) | |
totalTests=$(jq '.statistic.total' summary.json) | |
echo "TEST_RESULT=$passedTests passed, $failedTests failed, $brokenTests broken, $skippedTests skipped, $totalTests total" >> $GITHUB_ENV | |
- name: Get status color | |
if: ${{ !cancelled() }} | |
shell: bash | |
run: > | |
if ${{ steps.tests.outcome == 'success' }}; | |
then echo "STATUS_COLOR=#33FF39" >> $GITHUB_ENV; | |
elif ${{ steps.tests.outcome == 'failure' }}; | |
then echo "STATUS_COLOR=#FF333C" >> $GITHUB_ENV; | |
else echo "STATUS_COLOR=#F3FF33" >> $GITHUB_ENV; | |
fi | |
- uses: actions/github-script@v6 | |
if: ${{ !cancelled() }} | |
name: prepare status | |
id: status | |
with: | |
script: | | |
const fs = require("fs"); | |
const path = require("path"); | |
const [ owner, repo ] = "${{ github.repository }}".split("/"); | |
const jobs = await github.paginate(github.rest.actions.listJobsForWorkflowRunAttempt, { | |
owner, | |
repo, | |
run_id: "${{ github.run_id }}", | |
attempt_number: "${{ github.run_attempt }}", | |
}); | |
const findJobUrl = os => | |
jobs.find(job => job.name == `Live Desktop Tests (${os})`)?.html_url; | |
const keys = { | |
linux: { | |
symbol: "🐧", | |
name: "Linux", | |
jobUrl: findJobUrl("Linux") | |
}, | |
}; | |
const report = { | |
linux: { | |
pass: ${{ steps.tests.outcome == 'success' }}, | |
status: "${{ steps.tests.outcome }}", | |
} | |
}; | |
let summary = `### Playwright Tests | |
` | |
summary += `|` | |
const reportKeys = Object.keys(report); | |
const playwrightSuccess = Object.entries(report).every(([os, values]) => !!values.pass); | |
reportKeys.forEach((k) => { | |
summary += ` [${keys[k].symbol} ${keys[k].name}](${keys[k].jobUrl}) |`; | |
}); | |
summary += ` | |
|`; | |
for (let i = 0; i < reportKeys.length; i++) { | |
summary += ` :--: |`; | |
} | |
summary += ` | |
|`; | |
Object.entries(report).forEach(([os, values]) => { | |
summary += ` ${values.pass ? "✅" : "❌"} (${values.status}) |`; | |
}); | |
summary += ` | |
${{ steps.comment.outputs.body }} | |
` | |
const output = { | |
summary, | |
actions: [{ | |
// 20 chars max | |
label: "Regen. Screenshots", | |
// 20 chars max | |
identifier: "regen_screenshots", | |
// 40 chars max | |
description: "Will regenerate playwright screenshots", | |
}, { | |
// 20 chars max | |
label: "Run full LLD suite", | |
// 20 chars max | |
identifier: "lld_full_suite", | |
// 40 chars max | |
description: "Run the full e2e test suite for LLD", | |
}], | |
}; | |
if (${{ !inputs.slack_notif && github.event_name == 'workflow_dispatch' }}) return; | |
const slackPayload = { | |
"text": "Ledger Live Desktop tests results on ${{github.ref_name}}", | |
"attachments": [ | |
{ | |
"color": "${{ env.STATUS_COLOR }}", | |
"blocks": [ | |
{ | |
"type": "header", | |
"text": { | |
"type": "plain_text", | |
"text": ":ledger-logo: Ledger Live Desktop tests results on ${{ github.ref_name }}", | |
"emoji": true | |
} | |
}, | |
{ | |
"type": "divider" | |
}, | |
{ | |
"type": "header", | |
"text": { | |
"type": "plain_text", | |
"text": "E2E Tests" | |
} | |
}, | |
{ | |
"type": "section", | |
"text": { | |
"type": "mrkdwn", | |
"text": `- 🐧 linux: ${report.linux.pass ? "✅" : "❌"} ${process.env.TEST_RESULT || 'No test results'}` | |
} | |
}, | |
{ | |
"type": "divider" | |
}, | |
{ | |
"type": "section", | |
"fields": [ | |
{ | |
"type": "mrkdwn", | |
"text": "*Allure Report*\n<${{ steps.allure-server.outputs.report-url }}|allure-results-linux>" | |
}, | |
{ | |
"type": "mrkdwn", | |
"text": "*Workflow*\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Workflow Run>" | |
} | |
] | |
} | |
] | |
} | |
] | |
}; | |
fs.writeFileSync("payload-slack-content.json", JSON.stringify(slackPayload), "utf-8"); | |
- name: Print Slack Payload Content | |
if: ${{ !cancelled() && (inputs.slack_notif || github.event_name == 'schedule' )}} | |
run: cat ${{ github.workspace }}/payload-slack-content.json | |
- name: post to a Slack channel | |
id: slack | |
uses: slackapi/[email protected] | |
if: ${{ !cancelled() && (inputs.slack_notif || github.event_name == 'schedule' )}} | |
with: | |
channel-id: "C05FKJ7DFAP" | |
payload-file-path: ${{ github.workspace }}/payload-slack-content.json | |
env: | |
SLACK_BOT_TOKEN: ${{ secrets.SLACK_LIVE_CI_BOT_TOKEN }} |