diff --git a/.github/workflows/doc-examples-deploy.yml b/.github/workflows/doc-examples-deploy.yml index 032c79e52cc..f008be5f2b6 100644 --- a/.github/workflows/doc-examples-deploy.yml +++ b/.github/workflows/doc-examples-deploy.yml @@ -1,14 +1,85 @@ -# (C) 2024 GoodData Corporation +# (C) 2025 GoodData Corporation -# Deploy of ui sdk examples from rel/9.9 branch name: Doc ~ Examples deploy on: workflow_dispatch: jobs: - release-ui-sdk-examples-deploy: - secrets: inherit - permissions: - contents: write - id-token: write - uses: ./.github/workflows/rw-doc-examples-deploy.yml + warm-up-cache: + runs-on: + group: infra1-runners-arc + labels: runners-cxa-xlarge + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 2 + - name: Git config user + uses: snow-actions/git-config-user@v1.0.0 + with: + name: git-action + email: git-action@gooddata.com + - name: Warmup rush + env: + NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + uses: ./.github/actions/rush/warm-up-rush + build: + needs: [warm-up-cache] + runs-on: + group: infra1-runners-arc + labels: runners-rxa-xlarge + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 2 + - name: Git config user + uses: snow-actions/git-config-user@v1.0.0 + with: + name: git-action + email: git-action@gooddata.com + - name: Debug + run: git log -1 + - name: Setup rush + env: + NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + uses: ./.github/actions/rush/set-up-rush + - name: Rush build + run: node common/scripts/install-run-rush.js build --to @gooddata/sdk-ui-tests + + e2e-backstop: + needs: [warm-up-cache,build] + runs-on: + group: infra1-runners-arc + labels: runners-mxa-2xlarge # bigger runner as backstop sometimes cannot launch the browser + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 2 + - name: Git config user + uses: snow-actions/git-config-user@v1.0.0 + with: + name: git-action + email: git-action@gooddata.com + - name: Setup rush + env: + NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + uses: ./.github/actions/rush/set-up-rush + - name: Rush build + run: | + node common/scripts/install-run-rush.js build --to @gooddata/sdk-ui-tests + - name: Run backstop tests + run: | + export EXECUTOR_NUMBER=$GH_RUN_ID + ./common/scripts/ci/run_backstop_tests.sh + env: + GH_RUN_ID: ${{ github.run_id }} + - name: Cleanup backstop artifacts + if: ${{ !cancelled() && failure() }} + run: | + node libs/sdk-ui-tests/backstop/backstop-write-all-artifacts.cjs + - name: Archive the cypress test artifacts + uses: actions/upload-artifact@v4 + if: ${{ !cancelled() && failure() }} + with: + name: backstop-test-artifacts-failed + path: | + libs/sdk-ui-tests/backstop/output/**/* diff --git a/libs/sdk-ui-tests/backstop/backstop-write-all-artifacts.cjs b/libs/sdk-ui-tests/backstop/backstop-write-all-artifacts.cjs new file mode 100644 index 00000000000..68d0352660b --- /dev/null +++ b/libs/sdk-ui-tests/backstop/backstop-write-all-artifacts.cjs @@ -0,0 +1,68 @@ +/** + * Process backstop output results. + * + * Adjust config so that the html report is correctly displayed and contains all tests. + * + **/ +const fs = require("fs"); +const path = require("path"); + +const currentDir = __dirname; +const references = "reference"; + +console.log(`Storing all artifacts from ${currentDir}/output`); + +const outputPath = path.join(currentDir, "output"); +const htmlReportPath = path.join(outputPath, "html-report"); +const outputConfig = path.join(htmlReportPath, "config.js"); + +if (!fs.existsSync(outputConfig)) { + console.log("No backstop output, skipping cleanup of test artifacts"); + process.exit(1); +} + +// this will be the newly added directory to output, to which we copy +// reference screenshots for failed tests +const referenceDirectory = path.join(outputPath, references); +fs.mkdirSync(referenceDirectory, { recursive: true }); + +const configData = fs.readFileSync(outputConfig, "utf8"); + +// the config json we're interested in is wrapped with report({...}); +const configJson = configData.slice("report(".length, -2); +const data = JSON.parse(configJson); + +data.tests.forEach((test) => { + if (test.status === "pass" || test.status === "fail") { + const referenceFile = test.pair?.reference; + const referencePath = path.join(htmlReportPath, referenceFile); + const baseReferenceFilename = path.basename(referencePath); + const destReference = path.join(referenceDirectory, baseReferenceFilename); + + if (fs.existsSync(referencePath)) { + fs.copyFileSync(referencePath, destReference); + } + } else { + console.log(`Processing "${test.pair?.label}", unrecognized test status: "${test.status}"`); + } +}); + +const updatedTests = data.tests + .filter((test) => test.status === "fail") + .map((test) => ({ + ...test, + pair: { + ...test.pair, + reference: test.pair?.reference?.replace(`../../${references}`, `../${references}`), + }, + })); + +const replacedConfig = { + ...data, + tests: updatedTests, +}; +const stringified = JSON.stringify(replacedConfig, null, 2); + +// replace original config with adjusted one +const result = `report(${stringified});`; +fs.writeFileSync(outputConfig, result, "utf8");