From 3a50b691f72c882f8eb4c5b375925e95944a831d Mon Sep 17 00:00:00 2001 From: tryingET <260287438+tryingET@users.noreply.github.com> Date: Tue, 18 Aug 2026 13:45:13 +0200 Subject: [PATCH 1/9] test: add deterministic comparison recording harness --- test/behavioralComparison/record.mjs | 99 ++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 test/behavioralComparison/record.mjs diff --git a/test/behavioralComparison/record.mjs b/test/behavioralComparison/record.mjs new file mode 100644 index 0000000..29de2dc --- /dev/null +++ b/test/behavioralComparison/record.mjs @@ -0,0 +1,99 @@ +#!/usr/bin/env node + +import assert from 'node:assert'; +import { spawnSync } from 'node:child_process'; +import { cp, mkdir, mkdtemp, readFile, readdir, rm, writeFile } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { dirname, join, resolve } from 'node:path'; + +const [targetRepositoryArg, variant, outputFileArg] = process.argv.slice(2); +if (!targetRepositoryArg || !variant || !outputFileArg) { + console.error('usage: record.mjs '); + process.exit(2); +} +if (!['control', 'before', 'after'].includes(variant)) { + console.error(`unknown variant: ${variant}`); + process.exit(2); +} + +const targetRepository = resolve(targetRepositoryArg); +const outputFile = resolve(outputFileArg); +const appmapNode = join(targetRepository, 'bin', 'appmap-node.js'); +const fixtureDir = await mkdtemp(join(tmpdir(), 'appmap-pr-comparison-')); + +async function findAppMaps(directory) { + const matches = []; + const visit = async (current) => { + for (const entry of await readdir(current, { withFileTypes: true })) { + const path = join(current, entry.name); + if (entry.isDirectory()) await visit(path); + else if (entry.name.endsWith('.appmap.json')) matches.push(path); + } + }; + await visit(directory); + return matches; +} + +function fixtureSource(selectedVariant) { + const authorizationCall = + selectedVariant === 'after' + ? ` +function authorize(request) { + return request.userId > 0; +} +` + : ''; + const authorizationUse = selectedVariant === 'after' ? 'authorize(request);' : ''; + + return ` +function parseRequest() { + return { userId: 42 }; +} +${authorizationCall} +function loadUser(request) { + return { id: request.userId, role: 'reader' }; +} + +const request = parseRequest(); +${authorizationUse} +const user = loadUser(request); +console.log(user.id); +`; +} + +try { + await writeFile( + join(fixtureDir, 'appmap.yml'), + `name: appmap-pr-comparison\nlanguage: javascript\nappmap_dir: tmp/appmap\npackages:\n - path: .\n exclude:\n - node_modules\n` + ); + await writeFile(join(fixtureDir, 'index.mjs'), fixtureSource(variant)); + + const result = spawnSync(process.execPath, [appmapNode, 'index.mjs'], { + cwd: fixtureDir, + env: { + ...process.env, + APPMAP_RECORDER_PROCESS_ALWAYS: 'true', + TZ: 'UTC', + }, + stdio: 'inherit', + }); + assert.equal(result.status, 0, `appmap-node exited with status ${result.status}`); + + const maps = await findAppMaps(join(fixtureDir, 'tmp')); + const processMaps = []; + for (const path of maps) { + const appmap = JSON.parse(await readFile(path, 'utf8')); + if (appmap.metadata?.recorder?.type === 'process') processMaps.push(path); + } + assert.equal( + processMaps.length, + 1, + `expected one process AppMap, found ${processMaps.length}: ${maps.join(', ')}` + ); + + await mkdir(dirname(outputFile), { recursive: true }); + await cp(processMaps[0], outputFile); + console.log(`Recorded ${variant} behavior to ${outputFile}`); +} finally { + await rm(fixtureDir, { recursive: true, force: true }); +} From 4ba9714f713c109eedbc1a1d18913387337a8a10 Mon Sep 17 00:00:00 2001 From: tryingET <260287438+tryingET@users.noreply.github.com> Date: Tue, 18 Aug 2026 13:45:35 +0200 Subject: [PATCH 2/9] test: validate comparison dogfood artifacts --- test/behavioralComparison/validate.mjs | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 test/behavioralComparison/validate.mjs diff --git a/test/behavioralComparison/validate.mjs b/test/behavioralComparison/validate.mjs new file mode 100644 index 0000000..d0204cc --- /dev/null +++ b/test/behavioralComparison/validate.mjs @@ -0,0 +1,45 @@ +#!/usr/bin/env node + +import assert from 'node:assert'; +import { readFile, writeFile } from 'node:fs/promises'; + +const [controlFile, demoFile, summaryFile] = process.argv.slice(2); +if (!controlFile || !demoFile || !summaryFile) { + console.error('usage: validate.mjs '); + process.exit(2); +} + +const control = JSON.parse(await readFile(controlFile, 'utf8')); +const demo = JSON.parse(await readFile(demoFile, 'utf8')); + +for (const bundle of [control, demo]) { + assert.equal(bundle.kind, 'appmap.sequence-comparison'); + assert.equal(bundle.schemaVersion, 1); + assert(bundle.base?.actors && bundle.base?.rootActions); + assert(bundle.head?.actors && bundle.head?.rootActions); + assert(bundle.diff?.actors && bundle.diff?.rootActions); + assert(Array.isArray(bundle.changes)); +} + +assert.equal( + control.changes.length, + 0, + `control recording drifted unexpectedly: ${JSON.stringify(control.changes, null, 2)}` +); +assert(demo.changes.length > 0, 'demo comparison should contain a visible behavioral change'); +assert( + demo.changes.some( + (change) => change.kind === 'added' && String(change.name).toLowerCase().includes('authorize') + ), + `expected an added authorize call: ${JSON.stringify(demo.changes, null, 2)}` +); + +const summary = `# AppMap PR comparison dogfood\n\n` + + `- Control scenario: **no runtime drift** across the base and PR builds.\n` + + `- Visual scenario: **${demo.changes.length} semantic change(s)** detected.\n` + + `- Added authorization call: **confirmed**.\n` + + `- Artifact: download \`appmap-pr-comparison\` and open either ` + + `\`*.compare.diff.sequence.json\` file with the companion VS Code extension PR.\n`; + +await writeFile(summaryFile, summary); +console.log(summary); From a6803c697822b014e1c95e9f7191ab1906adec9f Mon Sep 17 00:00:00 2001 From: tryingET <260287438+tryingET@users.noreply.github.com> Date: Tue, 18 Aug 2026 13:46:39 +0200 Subject: [PATCH 3/9] ci: dogfood before and after AppMap comparison --- .../workflows/appmap-comparison-dogfood.yml | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 .github/workflows/appmap-comparison-dogfood.yml diff --git a/.github/workflows/appmap-comparison-dogfood.yml b/.github/workflows/appmap-comparison-dogfood.yml new file mode 100644 index 0000000..b0d1ea8 --- /dev/null +++ b/.github/workflows/appmap-comparison-dogfood.yml @@ -0,0 +1,170 @@ +name: Dogfood AppMap PR comparison + +on: + push: + branches: + - 'agent/**' + pull_request: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: appmap-comparison-${{ github.ref }} + cancel-in-progress: true + +jobs: + comparison-bundle: + name: Record and compare base/head behavior + runs-on: ubuntu-latest + steps: + - name: Check out base revision + uses: actions/checkout@v6 + with: + ref: ${{ github.event.pull_request.base.sha || github.event.repository.default_branch }} + path: base + fetch-depth: 1 + persist-credentials: false + + - name: Check out head revision + uses: actions/checkout@v6 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + path: head + fetch-depth: 1 + persist-credentials: false + + - name: Check out comparison CLI prototype + uses: actions/checkout@v6 + with: + repository: tryingET/appmap-js + ref: agent/sequence-comparison-bundle + path: appmap-js + fetch-depth: 1 + persist-credentials: false + + - uses: actions/setup-node@v6 + with: + node-version: 22 + + - name: Install and build both appmap-node revisions + shell: bash + run: | + set -euo pipefail + corepack enable + (cd base && yarn install --immutable && yarn prepack) + (cd head && yarn install --immutable && yarn prepack) + + - name: Record control and visual scenarios + shell: bash + run: | + set -euo pipefail + mkdir -p comparison/appmaps + node head/test/behavioralComparison/record.mjs base control comparison/appmaps/control-base.appmap.json + node head/test/behavioralComparison/record.mjs head control comparison/appmaps/control-head.appmap.json + node head/test/behavioralComparison/record.mjs base before comparison/appmaps/demo-base.appmap.json + node head/test/behavioralComparison/record.mjs head after comparison/appmaps/demo-head.appmap.json + + - name: Build comparison CLI + shell: bash + run: | + set -euo pipefail + corepack enable + cd appmap-js + yarn install --immutable + yarn build + + - name: Sanitize recordings and build portable comparison bundles + shell: bash + run: | + set -euo pipefail + CLI="node appmap-js/packages/cli/built/cli.js" + BASE_SHA="$(git -C base rev-parse HEAD)" + HEAD_SHA="$(git -C head rev-parse HEAD)" + + $CLI sanitize comparison/appmaps/*.appmap.json + + $CLI sequence-diagram-compare \ + comparison/appmaps/control-base.appmap.json \ + comparison/appmaps/control-head.appmap.json \ + --scenario appmap-node-control \ + --base-revision "$BASE_SHA" \ + --head-revision "$HEAD_SHA" \ + --output-file comparison/control.compare.diff.sequence.json + + $CLI sequence-diagram-compare \ + comparison/appmaps/demo-base.appmap.json \ + comparison/appmaps/demo-head.appmap.json \ + --scenario added-authorization-call \ + --base-revision "$BASE_SHA" \ + --head-revision "$HEAD_SHA" \ + --output-file comparison/authorization.compare.diff.sequence.json + + - name: Verify dogfood result + shell: bash + run: | + node head/test/behavioralComparison/validate.mjs \ + comparison/control.compare.diff.sequence.json \ + comparison/authorization.compare.diff.sequence.json \ + comparison/summary.md + cat comparison/summary.md >> "$GITHUB_STEP_SUMMARY" + + - name: Upload interactive comparison artifact + uses: actions/upload-artifact@v6 + with: + name: appmap-pr-comparison + path: comparison + retention-days: 14 + if-no-files-found: error + + vscode-viewer: + name: Build and exercise comparison viewer + runs-on: ubuntu-latest + steps: + - name: Check out VS Code comparison prototype + uses: actions/checkout@v6 + with: + repository: tryingET/vscode-appland + ref: agent/sequence-comparison-editor + fetch-depth: 1 + persist-credentials: false + + - uses: actions/setup-node@v6 + with: + node-version: 18 + cache: yarn + + - name: Install, typecheck, and compile + run: | + corepack enable + yarn install --immutable + yarn pretest + yarn compile + + - name: Prepare Electron integration environment + run: | + yarn test:precache + yarn download-tools + + - name: Open a comparison bundle in the extension host + shell: bash + run: | + export XDG_RUNTIME_DIR=/run/user/$(id -u) + export DBUS_SESSION_BUS_ADDRESS=unix:path=$XDG_RUNTIME_DIR/bus + sudo mkdir -p "$XDG_RUNTIME_DIR" + sudo chown "$(id -u):$(id -g)" "$XDG_RUNTIME_DIR" + dbus-daemon --session --address="$DBUS_SESSION_BUS_ADDRESS" --fork --nopidfile + xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- \ + yarn test:integration test/integration/appmapEditor/openSequenceComparison.test.ts + + - name: Package dogfood VSIX + run: yarn vsce package --out appmap-comparison-dogfood.vsix + + - name: Upload comparison viewer + uses: actions/upload-artifact@v6 + with: + name: appmap-comparison-vsix + path: appmap-comparison-dogfood.vsix + retention-days: 14 + if-no-files-found: error From 321fe0319d86cb90c95534104d258a5d057515e8 Mon Sep 17 00:00:00 2001 From: tryingET <260287438+tryingET@users.noreply.github.com> Date: Tue, 18 Aug 2026 14:00:13 +0200 Subject: [PATCH 4/9] ci: verify comparison publisher in dogfood chain --- .../workflows/appmap-comparison-dogfood.yml | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.github/workflows/appmap-comparison-dogfood.yml b/.github/workflows/appmap-comparison-dogfood.yml index b0d1ea8..35bdde4 100644 --- a/.github/workflows/appmap-comparison-dogfood.yml +++ b/.github/workflows/appmap-comparison-dogfood.yml @@ -168,3 +168,26 @@ jobs: path: appmap-comparison-dogfood.vsix retention-days: 14 if-no-files-found: error + + review-publisher: + name: Verify review artifact publisher + runs-on: ubuntu-latest + steps: + - name: Check out review-action comparison publisher + uses: actions/checkout@v6 + with: + repository: tryingET/review-action + ref: agent/upload-comparison-artifact + fetch-depth: 1 + persist-credentials: false + + - name: Run offline action harness + run: test/run.sh + + - name: Validate comparison skill contract is present + shell: bash + run: | + set -euo pipefail + test -s test/fixtures/skills-src/appmap-comparison/SKILL.md + grep -q 'appmap-comparison' scripts/install-skills.sh + grep -q 'upload-comparison-artifact' action.yml From 7458e4b5eb9e5318e8e0ac057e2bce2e748c65c5 Mon Sep 17 00:00:00 2001 From: tryingET <260287438+tryingET@users.noreply.github.com> Date: Tue, 18 Aug 2026 14:02:50 +0200 Subject: [PATCH 5/9] ci: open the generated bundle in the dogfood viewer --- .../workflows/appmap-comparison-dogfood.yml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/appmap-comparison-dogfood.yml b/.github/workflows/appmap-comparison-dogfood.yml index 35bdde4..1516d18 100644 --- a/.github/workflows/appmap-comparison-dogfood.yml +++ b/.github/workflows/appmap-comparison-dogfood.yml @@ -120,6 +120,7 @@ jobs: vscode-viewer: name: Build and exercise comparison viewer + needs: comparison-bundle runs-on: ubuntu-latest steps: - name: Check out VS Code comparison prototype @@ -130,6 +131,21 @@ jobs: fetch-depth: 1 persist-credentials: false + - name: Download the generated comparison bundle + uses: actions/download-artifact@v8 + with: + name: appmap-pr-comparison + path: dogfood-comparison + + - name: Install the generated bundle as the editor test fixture + shell: bash + run: | + set -euo pipefail + target="test/fixtures/workspaces/project-diagram-diff/data/diff/minitest/Users_edit_unsuccessful_edit.compare.diff.sequence.json" + mkdir -p "$(dirname "$target")" + cp dogfood-comparison/authorization.compare.diff.sequence.json "$target" + printf 'authorize\n' > "$target.expect" + - uses: actions/setup-node@v6 with: node-version: 18 @@ -147,7 +163,7 @@ jobs: yarn test:precache yarn download-tools - - name: Open a comparison bundle in the extension host + - name: Open the generated comparison bundle in the extension host shell: bash run: | export XDG_RUNTIME_DIR=/run/user/$(id -u) From c74590fbd9c0fa874dd8c8b340cb3dcfcff395b5 Mon Sep 17 00:00:00 2001 From: tryingET <260287438+tryingET@users.noreply.github.com> Date: Wed, 19 Aug 2026 08:18:03 +0200 Subject: [PATCH 6/9] test: validate the frozen comparison contract --- test/behavioralComparison/validate.mjs | 35 +++++++++++++++++++------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/test/behavioralComparison/validate.mjs b/test/behavioralComparison/validate.mjs index d0204cc..350c5e3 100644 --- a/test/behavioralComparison/validate.mjs +++ b/test/behavioralComparison/validate.mjs @@ -13,12 +13,21 @@ const control = JSON.parse(await readFile(controlFile, 'utf8')); const demo = JSON.parse(await readFile(demoFile, 'utf8')); for (const bundle of [control, demo]) { - assert.equal(bundle.kind, 'appmap.sequence-comparison'); + assert.equal(bundle.kind, 'appmap.comparison'); assert.equal(bundle.schemaVersion, 1); - assert(bundle.base?.actors && bundle.base?.rootActions); - assert(bundle.head?.actors && bundle.head?.rootActions); - assert(bundle.diff?.actors && bundle.diff?.rootActions); + assert.equal(bundle.capabilities?.views?.sequence, 1); + assert(bundle.scenario?.id); + assert(bundle.recordings?.base && bundle.recordings?.head); + assert(bundle.views?.sequence?.base?.actors && bundle.views.sequence.base.rootActions); + assert(bundle.views?.sequence?.head?.actors && bundle.views.sequence.head.rootActions); + assert(bundle.views?.sequence?.diff?.actors && bundle.views.sequence.diff.rootActions); + assert(Array.isArray(bundle.views.sequence.alignment?.actorOrder)); assert(Array.isArray(bundle.changes)); + assert.equal(new Set(bundle.changes.map((change) => change.id)).size, bundle.changes.length); + bundle.changes.forEach((change) => { + assert.match(change.id, /^chg_[0-9a-f]{20}(?:_[1-9][0-9]*)?$/); + assert(change.views?.sequence); + }); } assert.equal( @@ -28,18 +37,26 @@ assert.equal( ); assert(demo.changes.length > 0, 'demo comparison should contain a visible behavioral change'); assert( - demo.changes.some( - (change) => change.kind === 'added' && String(change.name).toLowerCase().includes('authorize') - ), + demo.changes.some((change) => { + const name = change.details?.name; + const searchable = [change.summary, name?.before, name?.after] + .filter(Boolean) + .join(' ') + .toLowerCase(); + return change.kind === 'call-added' && searchable.includes('authorize'); + }), `expected an added authorize call: ${JSON.stringify(demo.changes, null, 2)}` ); -const summary = `# AppMap PR comparison dogfood\n\n` + +const summary = + `# AppMap PR comparison dogfood\n\n` + + `- Contract: **appmap.comparison schema v1**.\n` + `- Control scenario: **no runtime drift** across the base and PR builds.\n` + `- Visual scenario: **${demo.changes.length} semantic change(s)** detected.\n` + `- Added authorization call: **confirmed**.\n` + + `- Change IDs: **deterministic, non-positional hashes**.\n` + `- Artifact: download \`appmap-pr-comparison\` and open either ` + `\`*.compare.diff.sequence.json\` file with the companion VS Code extension PR.\n`; await writeFile(summaryFile, summary); -console.log(summary); +console.log(summary); \ No newline at end of file From dc804038e166b561ceb320f92c6102c55ab9d272 Mon Sep 17 00:00:00 2001 From: tryingET <260287438+tryingET@users.noreply.github.com> Date: Wed, 19 Aug 2026 08:22:51 +0200 Subject: [PATCH 7/9] ci: run comparison contract and producer tests --- .github/workflows/appmap-comparison-dogfood.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/appmap-comparison-dogfood.yml b/.github/workflows/appmap-comparison-dogfood.yml index 1516d18..4046361 100644 --- a/.github/workflows/appmap-comparison-dogfood.yml +++ b/.github/workflows/appmap-comparison-dogfood.yml @@ -66,7 +66,7 @@ jobs: node head/test/behavioralComparison/record.mjs base before comparison/appmaps/demo-base.appmap.json node head/test/behavioralComparison/record.mjs head after comparison/appmaps/demo-head.appmap.json - - name: Build comparison CLI + - name: Build and test comparison contract shell: bash run: | set -euo pipefail @@ -74,6 +74,8 @@ jobs: cd appmap-js yarn install --immutable yarn build + yarn workspace @appland/models test comparison --runInBand + yarn workspace @appland/appmap test sequenceDiagramCompare --runInBand - name: Sanitize recordings and build portable comparison bundles shell: bash @@ -206,4 +208,4 @@ jobs: set -euo pipefail test -s test/fixtures/skills-src/appmap-comparison/SKILL.md grep -q 'appmap-comparison' scripts/install-skills.sh - grep -q 'upload-comparison-artifact' action.yml + grep -q 'upload-comparison-artifact' action.yml \ No newline at end of file From 5276ee5c3e0be4126de7700be98a55f482250fb5 Mon Sep 17 00:00:00 2001 From: tryingET <260287438+tryingET@users.noreply.github.com> Date: Wed, 19 Aug 2026 08:52:13 +0200 Subject: [PATCH 8/9] test(comparison): enforce the frozen change-id grammar --- test/behavioralComparison/validate.mjs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test/behavioralComparison/validate.mjs b/test/behavioralComparison/validate.mjs index 350c5e3..948d3d1 100644 --- a/test/behavioralComparison/validate.mjs +++ b/test/behavioralComparison/validate.mjs @@ -11,6 +11,7 @@ if (!controlFile || !demoFile || !summaryFile) { const control = JSON.parse(await readFile(controlFile, 'utf8')); const demo = JSON.parse(await readFile(demoFile, 'utf8')); +const changeIdPattern = /^chg_[0-9a-f]{20}(?:_[2-9][0-9]*|_[1-9][0-9]+)?$/; for (const bundle of [control, demo]) { assert.equal(bundle.kind, 'appmap.comparison'); @@ -25,8 +26,13 @@ for (const bundle of [control, demo]) { assert(Array.isArray(bundle.changes)); assert.equal(new Set(bundle.changes.map((change) => change.id)).size, bundle.changes.length); bundle.changes.forEach((change) => { - assert.match(change.id, /^chg_[0-9a-f]{20}(?:_[1-9][0-9]*)?$/); + assert.match(change.id, changeIdPattern); assert(change.views?.sequence); + const references = [change.views.sequence.base, change.views.sequence.head] + .filter(Boolean) + .flatMap((reference) => [reference.eventIds, reference.elementIds]) + .filter(Boolean); + assert(references.length > 0, `change ${change.id} has no navigable sequence reference`); }); } @@ -55,8 +61,9 @@ const summary = `- Visual scenario: **${demo.changes.length} semantic change(s)** detected.\n` + `- Added authorization call: **confirmed**.\n` + `- Change IDs: **deterministic, non-positional hashes**.\n` + + `- Structural changes without events: **retained through element IDs**.\n` + `- Artifact: download \`appmap-pr-comparison\` and open either ` + `\`*.compare.diff.sequence.json\` file with the companion VS Code extension PR.\n`; await writeFile(summaryFile, summary); -console.log(summary); \ No newline at end of file +console.log(summary); From 166ce2797f17346e4a978748a34639b8abfe023c Mon Sep 17 00:00:00 2001 From: tryingET <260287438+tryingET@users.noreply.github.com> Date: Wed, 19 Aug 2026 09:02:45 +0200 Subject: [PATCH 9/9] ci(comparison): pin and publish the frozen schema-v1 contract --- .../workflows/appmap-comparison-dogfood.yml | 81 +++++++++++++++---- 1 file changed, 64 insertions(+), 17 deletions(-) diff --git a/.github/workflows/appmap-comparison-dogfood.yml b/.github/workflows/appmap-comparison-dogfood.yml index 4046361..f9d15f2 100644 --- a/.github/workflows/appmap-comparison-dogfood.yml +++ b/.github/workflows/appmap-comparison-dogfood.yml @@ -14,6 +14,12 @@ concurrency: group: appmap-comparison-${{ github.ref }} cancel-in-progress: true +env: + COMPARISON_CLI_SHA: aab690a5c4c01802551993718b508718c1139c11 + COMPARISON_VIEWER_SHA: cfd3a0fef35b016cb0af20ee02ae46fd35414069 + COMPARISON_REVIEW_ACTION_SHA: 67060904f03c0c8a1492e610f845eefd29e53a78 + COMPARISON_SKILLS_SHA: 167db8d4b7eb56086c74a9ef9ffe7b2d3c8ab627 + jobs: comparison-bundle: name: Record and compare base/head behavior @@ -35,11 +41,11 @@ jobs: fetch-depth: 1 persist-credentials: false - - name: Check out comparison CLI prototype + - name: Check out frozen comparison CLI contract uses: actions/checkout@v6 with: repository: tryingET/appmap-js - ref: agent/sequence-comparison-bundle + ref: ${{ env.COMPARISON_CLI_SHA }} path: appmap-js fetch-depth: 1 persist-credentials: false @@ -72,6 +78,7 @@ jobs: set -euo pipefail corepack enable cd appmap-js + test "$(git rev-parse HEAD)" = "$COMPARISON_CLI_SHA" yarn install --immutable yarn build yarn workspace @appland/models test comparison --runInBand @@ -103,19 +110,41 @@ jobs: --head-revision "$HEAD_SHA" \ --output-file comparison/authorization.compare.diff.sequence.json - - name: Verify dogfood result + - name: Verify and publish the frozen contract with the artifact shell: bash run: | + set -euo pipefail node head/test/behavioralComparison/validate.mjs \ comparison/control.compare.diff.sequence.json \ comparison/authorization.compare.diff.sequence.json \ comparison/summary.md + + mkdir -p comparison/contract/examples + cp appmap-js/packages/models/schema/comparison.schema.json comparison/contract/ + cp appmap-js/packages/models/schema/README.md comparison/contract/ + cp appmap-js/packages/models/schema/CHANGELOG.md comparison/contract/ + cp appmap-js/packages/models/schema/examples/*.json comparison/contract/examples/ + + BASE_SHA="$(git -C base rev-parse HEAD)" + HEAD_SHA="$(git -C head rev-parse HEAD)" + cat > comparison/contract-lock.json <> "$GITHUB_STEP_SUMMARY" - name: Upload interactive comparison artifact uses: actions/upload-artifact@v6 with: - name: appmap-pr-comparison + name: appmap-pr-comparison-schema-v1 path: comparison retention-days: 14 if-no-files-found: error @@ -125,18 +154,21 @@ jobs: needs: comparison-bundle runs-on: ubuntu-latest steps: - - name: Check out VS Code comparison prototype + - name: Check out pinned VS Code comparison viewer uses: actions/checkout@v6 with: repository: tryingET/vscode-appland - ref: agent/sequence-comparison-editor + ref: ${{ env.COMPARISON_VIEWER_SHA }} fetch-depth: 1 persist-credentials: false + - name: Verify the pinned viewer revision + run: test "$(git rev-parse HEAD)" = "$COMPARISON_VIEWER_SHA" + - name: Download the generated comparison bundle uses: actions/download-artifact@v8 with: - name: appmap-pr-comparison + name: appmap-pr-comparison-schema-v1 path: dogfood-comparison - name: Install the generated bundle as the editor test fixture @@ -177,13 +209,13 @@ jobs: yarn test:integration test/integration/appmapEditor/openSequenceComparison.test.ts - name: Package dogfood VSIX - run: yarn vsce package --out appmap-comparison-dogfood.vsix + run: yarn vsce package --out appmap-comparison-schema-v1-dogfood.vsix - name: Upload comparison viewer uses: actions/upload-artifact@v6 with: - name: appmap-comparison-vsix - path: appmap-comparison-dogfood.vsix + name: appmap-comparison-schema-v1-vsix + path: appmap-comparison-schema-v1-dogfood.vsix retention-days: 14 if-no-files-found: error @@ -191,21 +223,36 @@ jobs: name: Verify review artifact publisher runs-on: ubuntu-latest steps: - - name: Check out review-action comparison publisher + - name: Check out pinned review-action publisher uses: actions/checkout@v6 with: repository: tryingET/review-action - ref: agent/upload-comparison-artifact + ref: ${{ env.COMPARISON_REVIEW_ACTION_SHA }} + path: review-action + fetch-depth: 1 + persist-credentials: false + + - name: Check out pinned comparison skill + uses: actions/checkout@v6 + with: + repository: tryingET/skills + ref: ${{ env.COMPARISON_SKILLS_SHA }} + path: comparison-skills fetch-depth: 1 persist-credentials: false - name: Run offline action harness - run: test/run.sh + run: | + test "$(git -C review-action rev-parse HEAD)" = "$COMPARISON_REVIEW_ACTION_SHA" + test "$(git -C comparison-skills rev-parse HEAD)" = "$COMPARISON_SKILLS_SHA" + (cd review-action && test/run.sh) - - name: Validate comparison skill contract is present + - name: Validate publisher and skill contract shell: bash run: | set -euo pipefail - test -s test/fixtures/skills-src/appmap-comparison/SKILL.md - grep -q 'appmap-comparison' scripts/install-skills.sh - grep -q 'upload-comparison-artifact' action.yml \ No newline at end of file + test -s comparison-skills/appmap-comparison/SKILL.md + grep -q 'appmap.comparison' comparison-skills/appmap-comparison/SKILL.md + grep -q 'elementIds' comparison-skills/appmap-comparison/SKILL.md + grep -q 'appmap-comparison' review-action/scripts/install-skills.sh + grep -q 'upload-comparison-artifact' review-action/action.yml