mirror of
https://github.com/expo/explore.git
synced 2026-11-14 10:08:17 -10:00
Capture on this machine (local iOS simulators and Android emulators, with agent-device or Argent) as well as on EAS Simulator; name several capture targets per config (a phone, a foldable closed and open, Android) and review them in parallel with shared builds; repack locally with a local simulator; and make captures faster and harder to break: controller fault containment, an Argent fold recovery, upright captures of an opened iPhone Duo, a settle after each root reset, a route retry after an adb drop, emulator port reservation, a startup sweep of what interrupted captures leave running, and agent-device 0.21.28.
75 lines
4.5 KiB
JavaScript
75 lines
4.5 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { readFile } from "node:fs/promises";
|
|
import test from "node:test";
|
|
import { parse } from "yaml";
|
|
|
|
const source = await readFile(new URL("../../templates/explore-review.yml", import.meta.url), "utf8");
|
|
const workflow = parse(source);
|
|
|
|
test("report publishes one normal ZIP artifact to the hosted Viewer", () => {
|
|
const report = workflow.jobs.report;
|
|
const packageIndex = report.steps.findIndex(step => step.name === "Package hosted review bundle");
|
|
const uploadIndex = report.steps.findIndex(step => step.name === "Upload hosted review bundle");
|
|
const publishIndex = report.steps.findIndex(step => step.name === "Publish current PR hosted links");
|
|
assert.ok(packageIndex > 0 && uploadIndex > packageIndex && publishIndex > uploadIndex);
|
|
assert.match(report.steps[packageIndex].run, /ci:report --input/);
|
|
const upload = report.steps[uploadIndex];
|
|
assert.equal(upload.with.name, "explore-review-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.target }}");
|
|
assert.equal(upload.with.path, "${{ runner.temp }}/explore-report");
|
|
assert.equal(upload.with.archive, undefined);
|
|
assert.equal(upload.with["retention-days"], 30);
|
|
assert.equal(report.steps[publishIndex].env.ARTIFACT_URL, "${{ steps.viewer.outputs.artifact-url }}");
|
|
assert.match(report.steps[publishIndex].run, /ci:publish/);
|
|
assert.doesNotMatch(source, /EXPLORE_VIEWER_ORIGIN/);
|
|
assert.doesNotMatch(source, /build:report|expo-explore\.html|archive: false|EXPLORE_DATA_|CONVEX|git push|orphan/);
|
|
});
|
|
|
|
test("capture transfer uses explicit secret-free output paths and short retention", () => {
|
|
const steps = workflow.jobs.capture.steps;
|
|
const restore = steps.find(step => step.name === "Download optional exact-base evidence");
|
|
assert.equal(restore["continue-on-error"], true);
|
|
const transfer = steps.find(step => step.name === "Upload captured review for packaging");
|
|
assert.equal(transfer.with["retention-days"], 7);
|
|
assert.match(transfer.with.path, /report-input\.json/);
|
|
assert.match(transfer.with.path, /base-export/);
|
|
assert.match(transfer.with.path, /head-export/);
|
|
assert.doesNotMatch(transfer.with.path, /session|\/explore-review\s*$/);
|
|
const diagnostics = steps.find(step => step.name === "Upload planning and failure diagnostics");
|
|
assert.equal(diagnostics.if, "always()");
|
|
assert.match(diagnostics.with.path, /explore-diagnostics/);
|
|
assert.equal(diagnostics.with["retention-days"], 7);
|
|
assert.equal(diagnostics.with["if-no-files-found"], "ignore");
|
|
});
|
|
|
|
test("report job persists its own diagnostics even when packaging or publication fails", () => {
|
|
const step = workflow.jobs.report.steps.find(step => step.name === "Upload report failure diagnostics");
|
|
assert.equal(step.if, "always()");
|
|
assert.equal(step.with.path, "${{ runner.temp }}/explore-diagnostics");
|
|
assert.equal(step.with["retention-days"], 7);
|
|
assert.equal(step.with.name, "explore-report-diagnostics-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.target }}");
|
|
});
|
|
|
|
test("failure reporting downloads only this run attempt's failed-job diagnostics", () => {
|
|
const job = workflow.jobs.failure;
|
|
assert.equal(job.permissions.actions, "read");
|
|
assert.equal(job.permissions["pull-requests"], "write");
|
|
assert.equal(job.permissions.contents, undefined);
|
|
for (const [side, artifact] of [["capture", "explore-diagnostics"], ["report", "explore-report-diagnostics"]]) {
|
|
const step = job.steps.find(step => step.name === `Download ${side} failure diagnostic`);
|
|
assert.equal(step.if, `needs.${side}.result == 'failure'`);
|
|
assert.equal(step["continue-on-error"], true);
|
|
assert.equal(step.with.name, undefined);
|
|
assert.equal(step.with.pattern, `${artifact}-` + "${{ github.run_id }}-${{ github.run_attempt }}-*");
|
|
assert.equal(step.with.path, "${{ runner.temp }}/explore-failure/" + side);
|
|
assert.equal(step.with["run-id"], undefined, "download-artifact defaults to this run");
|
|
assert.equal(step.with.repository, undefined);
|
|
}
|
|
// A capture job that fails before it resolves the PR (its tool install, say) still gets its failure comment:
|
|
// the targets job already resolved and authorized the same PR.
|
|
const report = job.steps.find(step => step.name === "Report failure only on the current PR");
|
|
for (const [env, output] of [["PR_NUMBER", "pr_number"], ["HEAD_SHA", "head"], ["BASE_SHA", "base"]]) {
|
|
assert.equal(report.env[env], `\${{ needs.capture.outputs.${output} || needs.targets.outputs.${output} }}`);
|
|
assert.equal(workflow.jobs.targets.outputs[output], `\${{ steps.pr.outputs.${output} }}`);
|
|
}
|
|
});
|