fix: rebaseline dev base image evidence (#76)
Co-authored-by: HWLAB Code Queue <code-queue@pikastech.local>
This commit is contained in:
@@ -64,8 +64,9 @@ rules:
|
||||
|
||||
The catalog `commitId` is the artifact source commit, not proof that a registry
|
||||
artifact exists. It must match `deploy/deploy.json`, every service `commitId`,
|
||||
and the image tag. If it does not match the selected source ref, the DEV gate
|
||||
preflight reports `artifact-source-commit` as a blocker.
|
||||
and the image tag. If a later target ref changes artifact build inputs after the
|
||||
publish source, the DEV gate preflight may reopen `artifact-source-commit` even
|
||||
when the base-image blocker is already closed.
|
||||
|
||||
## Refresh Workflow
|
||||
|
||||
|
||||
@@ -141,6 +141,13 @@ remain `status: "blocked"`. Do not turn a base-image or registry blocker into a
|
||||
fake digest or published state. Do not treat runner-process loopback HTTP
|
||||
failure as a publish failure by itself.
|
||||
|
||||
Current rebaseline: the committed DEV artifact report is `status: "published"`
|
||||
for source commit `73b379f`, with `baseImagePreflight.status: "ready"`,
|
||||
`baseImage: "node:20-bookworm-slim"`, and 13/13 required services carrying
|
||||
real registry digests. If a later read-only runner cannot fetch catalog
|
||||
manifests from `127.0.0.1:5000`, treat that as a `#66` registry reachability
|
||||
dimension, not as a missing base-image or missing-publish blocker.
|
||||
|
||||
## Known Implementation States
|
||||
|
||||
- `repo-entrypoint`: the repository has `cmd/<serviceId>/main.mjs`.
|
||||
|
||||
@@ -13,15 +13,21 @@ PROD, read secrets, or use UniDesk runtime services as substitutes.
|
||||
- `deploy/deploy.json` and `deploy/artifact-catalog.dev.json` pin service image
|
||||
names to the DEV registry target, by default
|
||||
`127.0.0.1:5000/hwlab/<hwlab-service-id>:<commit>`.
|
||||
- The artifact catalog is `contract-skeleton` only. Service entries must keep
|
||||
`publishState: "skeleton-only"` and `digest: "not_published"` until real
|
||||
publish evidence exists.
|
||||
- The artifact catalog may be either `contract-skeleton` or `published`. A
|
||||
`published` catalog must be backed by `reports/dev-gate/dev-artifacts.json`
|
||||
with real `sha256:<64 hex>` digests for every required service.
|
||||
- The catalog and runtime boundary forbid PROD deployment, secret reads, force
|
||||
push, real publish claims, and UniDesk runtime substitution.
|
||||
- A builder base image is separate from HWLAB service artifact images. This
|
||||
preflight only decides whether #35 may proceed to build/publish; it does not
|
||||
prove that any service image was published.
|
||||
|
||||
Current rebaseline: `reports/dev-gate/dev-artifacts.json` records
|
||||
`baseImagePreflight.status: "ready"` for local `node:20-bookworm-slim` and
|
||||
13/13 published DEV artifacts from source commit `73b379f`. A failed catalog
|
||||
manifest read from a runner process is a registry reachability question for
|
||||
`#66`, not proof that the base image or publish digests are missing.
|
||||
|
||||
## Command
|
||||
|
||||
```sh
|
||||
|
||||
@@ -69,22 +69,27 @@ The report is blocked until real DEV-LIVE evidence is attached for the DEV
|
||||
route and downstream HWLAB runtime services. Current source, local, and dry-run
|
||||
contracts are useful readiness signals, but they are not live DEV proof.
|
||||
|
||||
The legacy base-image blocker is not current when the committed reports show an
|
||||
approved Node 20 builder base. Artifact/current remains stricter: a target ref
|
||||
can still keep `artifact-source-commit` or `dev-artifact-publish` open when it
|
||||
changes artifact build inputs after the publish source commit, even if the
|
||||
older DEV artifact report contains 13/13 published service digests. Registry
|
||||
manifest reachability remains separate and belongs to the #66
|
||||
process/Docker/k3s access dimensions.
|
||||
|
||||
## Next-Round Order
|
||||
|
||||
The JSON output groups recommended next actions in dependency order:
|
||||
|
||||
1. `base-image`: preload or tag an approved Node 20 DEV builder image, then
|
||||
rerun the base-image and artifact publish preflights.
|
||||
2. `artifact-publish`, `artifact-catalog`, `ghcr`: publish every frozen HWLAB
|
||||
service artifact and record immutable registry digests for the selected
|
||||
`origin/main` commit.
|
||||
3. `d601-k3s`, `kubectl`, kubeconfig/maintenance bridge: restore read-only
|
||||
1. `d601-k3s`, `kubectl`, kubeconfig/maintenance bridge: restore read-only
|
||||
hwlab-dev cluster observability without printing Secrets.
|
||||
4. `cloud-api-db`: prove DEV cloud-api DB env and health readiness with
|
||||
2. `cloud-api-db`: prove DEV cloud-api DB env and health readiness with
|
||||
redacted values only.
|
||||
5. `dev-edge`, `dev-edge-health`, `dev-ingress-health`: repair
|
||||
3. `dev-edge`, `dev-edge-health`, `dev-ingress-health`: repair
|
||||
`:16667`/frp/edge/router reachability, then rerun read-only DEV edge health
|
||||
before M3/M4/M5 live loops.
|
||||
4. `registry-manifest-read`: resolve #66 registry reachability without
|
||||
treating it as a missing publish digest or rerunning heavy publish.
|
||||
|
||||
## Boundaries
|
||||
|
||||
|
||||
@@ -42,13 +42,17 @@ The preflight checks:
|
||||
- `deploy/deploy.json` and `deploy/artifact-catalog.dev.json` are internally
|
||||
consistent and DEV-only.
|
||||
- The deploy manifest, artifact catalog, catalog service commits, and image tags
|
||||
target the selected `origin/main` source commit.
|
||||
are covered by the selected `origin/main` target. If `origin/main` is a
|
||||
report-only evidence commit whose changes do not touch artifact build inputs,
|
||||
the preflight may accept the artifact source recorded in
|
||||
`reports/dev-gate/dev-artifacts.json`.
|
||||
- The artifact catalog clearly separates source commit, artifact commit,
|
||||
`ciPublished`, `registryVerified`, and per-service digest state.
|
||||
- The artifact catalog has real publish and registry digest evidence, or stays
|
||||
blocked with `not_published` digests.
|
||||
- `reports/dev-gate/dev-artifacts.json`, when present, proves all frozen DEV
|
||||
service artifacts were published for the selected `origin/main` commit.
|
||||
service artifacts were published for the selected target or for an artifact
|
||||
source commit that still covers the target.
|
||||
- Registry capability evidence is split into `process-http-access`,
|
||||
`docker-daemon-push-access`, and `k3s-pull-access` instead of one ambiguous
|
||||
"registry reachable" result.
|
||||
@@ -60,14 +64,17 @@ The preflight checks:
|
||||
`HWLAB_CLOUD_DB_SSL_MODE=require`.
|
||||
- The local cloud-api health payload reports DB env presence/missing status with
|
||||
redacted values only. This is a readiness gate, not live DB evidence.
|
||||
- `deploy/frp` and `deploy/master-edge` describe the D601-to-master DEV routes
|
||||
on public ports `16666`/`16667`.
|
||||
- `deploy/frp` and `deploy/master-edge` describe the D601-to-master DEV route
|
||||
on public frontend `:16666` and API/edge/live `:16667`. Legacy public
|
||||
`:6666/:6667` observations are historical/deprecated only and must not be
|
||||
used as current green evidence or current active blockers.
|
||||
- The runner can perform read-only `kubectl` probes against `hwlab-dev`.
|
||||
- `reports/dev-gate/dev-edge-health.json`, when present, records read-only
|
||||
public edge, frps, tunnel-health, and k3s observability evidence.
|
||||
- `http://74.48.78.17:16667/health/live` responds.
|
||||
- Catalog image manifests are visible without reading credentials. This is
|
||||
artifact catalog evidence and is separate from Docker daemon push access.
|
||||
- Catalog image manifests are visible without reading credentials. A failed
|
||||
manifest read is tracked as a #66 registry reachability dimension and must not
|
||||
be conflated with missing publish digests.
|
||||
- Deploy images do not point at UniDesk, provider-gateway, or microservice-proxy
|
||||
substitutes.
|
||||
|
||||
@@ -117,3 +124,17 @@ proves every frozen service has a registry digest for that same source commit:
|
||||
```sh
|
||||
node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report reports/dev-gate/dev-artifacts.json
|
||||
```
|
||||
|
||||
Current rebaseline: the committed DEV artifact report proves 13/13 required
|
||||
DEV artifacts from source `73b379f` with `ciPublished=true`,
|
||||
`registryVerified=true`, and real `sha256` digests, and the base-image
|
||||
preflight is `ready` on local `node:20-bookworm-slim`. If the selected
|
||||
`origin/main` target later drifts onto files that change artifact build inputs,
|
||||
the preflight can still reopen `artifact-source-commit` or
|
||||
`dev-artifact-publish` even though the base-image blocker stays closed.
|
||||
Remaining registry manifest-read failures are #66 reachability evidence, not a
|
||||
reason to reopen the base-image blocker.
|
||||
|
||||
This is M3 virtual hardware trusted-loop support only. It does not claim M3
|
||||
DEV-LIVE unless a real `DO1 -> patch-panel -> DI1` chain is observed through
|
||||
the current DEV endpoint.
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -14,19 +14,20 @@
|
||||
"pikasTech/HWLAB#30",
|
||||
"pikasTech/HWLAB#31",
|
||||
"pikasTech/HWLAB#33",
|
||||
"pikasTech/HWLAB#39",
|
||||
"pikasTech/HWLAB#49",
|
||||
"pikasTech/HWLAB#66",
|
||||
"pikasTech/HWLAB#33",
|
||||
"pikasTech/HWLAB#35",
|
||||
"pikasTech/HWLAB#48"
|
||||
"pikasTech/HWLAB#39",
|
||||
"pikasTech/HWLAB#43",
|
||||
"pikasTech/HWLAB#48",
|
||||
"pikasTech/HWLAB#49",
|
||||
"pikasTech/HWLAB#57",
|
||||
"pikasTech/HWLAB#66"
|
||||
],
|
||||
"target": {
|
||||
"ref": "origin/main",
|
||||
"commitId": "a1c3cb58da0067a12424277d47d9d50d0cbf7a9d",
|
||||
"shortCommitId": "a1c3cb5"
|
||||
"commitId": "82ad96c5c67c3906732a057d52395ec72851e4a9",
|
||||
"shortCommitId": "82ad96c"
|
||||
},
|
||||
"generatedAt": "2026-05-22T04:31:08.449Z",
|
||||
"generatedAt": "2026-05-22T05:35:39.805Z",
|
||||
"mode": "read-only",
|
||||
"devOnly": true,
|
||||
"prodDisabled": true,
|
||||
@@ -51,17 +52,43 @@
|
||||
"artifactIdentity": {
|
||||
"source": {
|
||||
"ref": "origin/main",
|
||||
"commitId": "a1c3cb58da0067a12424277d47d9d50d0cbf7a9d",
|
||||
"shortCommitId": "a1c3cb5"
|
||||
"commitId": "82ad96c5c67c3906732a057d52395ec72851e4a9",
|
||||
"shortCommitId": "82ad96c"
|
||||
},
|
||||
"artifactSource": {
|
||||
"source": "artifact-publish-report",
|
||||
"ref": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33",
|
||||
"commitId": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33",
|
||||
"shortCommitId": "7e29522"
|
||||
},
|
||||
"targetCoverage": {
|
||||
"sourceKind": "artifact-publish-report",
|
||||
"sourceRef": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33",
|
||||
"sourceCommitId": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33",
|
||||
"sourceShortCommitId": "7e29522",
|
||||
"targetRef": "origin/main",
|
||||
"targetCommitId": "82ad96c5c67c3906732a057d52395ec72851e4a9",
|
||||
"targetShortCommitId": "82ad96c",
|
||||
"mode": "artifact-input-drift",
|
||||
"covered": false,
|
||||
"artifactBuildInputChanged": true,
|
||||
"changedPathCount": 22,
|
||||
"changedArtifactInputPaths": [
|
||||
"internal/mvp-gate/summary.mjs",
|
||||
"web/hwlab-cloud-web/gate-summary.mjs"
|
||||
],
|
||||
"changedNonArtifactPathCount": 20,
|
||||
"reason": "target changes since the artifact source touch artifact build inputs"
|
||||
},
|
||||
"deployManifest": {
|
||||
"path": "deploy/deploy.json",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false
|
||||
},
|
||||
"artifactCatalog": {
|
||||
"path": "deploy/artifact-catalog.dev.json",
|
||||
"commitId": "73b379f",
|
||||
"commitId": "7e29522",
|
||||
"artifactState": "published",
|
||||
"ciPublished": true,
|
||||
"registryVerified": true,
|
||||
@@ -73,155 +100,169 @@
|
||||
},
|
||||
"requiredServiceCount": 13,
|
||||
"disabledServiceCount": 0,
|
||||
"matchesSource": false
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false
|
||||
},
|
||||
"services": [
|
||||
{
|
||||
"serviceId": "hwlab-cloud-api",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cloud-api:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:561e50494bf13bf61f83d28b371bc39b860b21333ef9991711853a095bd535bf",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cloud-api:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:090b6f919be3b3c7594ca4073b193351689fc525f478b64d54d393725cb01ecf",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-cloud-web",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cloud-web:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:c7939658af9f1109e5384619163dd0d11e1a1de14e7d15d4cbde7c4400b495c2",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cloud-web:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:bc6e836b2bb796b30562ed3ae93d8534146a3b74a310906481c8641646d1b8f0",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-agent-mgr",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-mgr:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:ae6ca76cd09a7d21e46e0076e12dea1843417a0d59d57b3115915c831e88ebef",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-mgr:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:4d9b8944bc52012bb0a4a3a345f8939381d2804032e544d0c98f49fac0e46bfd",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-agent-worker",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-worker:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:4d5f8d8d404fc2826256fb690fdea5570285a34d1bdffbaf1e0c7ca39603ffd8",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:2582176e2c35a2bfbce4edfd922749397d45f6f1f8c04d0394c501f7d87323ee",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-gateway",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-gateway:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:ff9f3f3dc6332c3d8e4e9825657c296c9664d84a8d40c3ffeab3c1e91a484008",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-gateway:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:290341fd6e6f036aa953943072ad58e0d0cfcc0e13950e6090f941b3310755a6",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-gateway-simu",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-gateway-simu:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:f5ccff29da331e424a482f92394d071e1be90c0244e7137e07ac33d9a7cc4082",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-gateway-simu:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:02627f880c7ddf2102e2255a43097d1f604cfb7a22215736e328287e27fc5f03",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-box-simu",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-box-simu:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:2a12c1c462b2c01a9fa15efa75a6e1f17ecc8432dfa88bca53f0d8d4b6355daf",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-box-simu:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:e02c270c71f83a2f4624722bb84616bea8374ef43439f27bdce310e4baa8dcca",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-patch-panel",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-patch-panel:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:5bc9a1c7ce65026cd7bf6d20a311226b35c796a4d52a914266244bf3c1a17286",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-patch-panel:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:f730323f83c62797f382932582a05df921045c86383dad7951f3d639b32456a9",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-router",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-router:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:356f37a7d78cc2f86230c2037f43215ad66979fbe4a949cb9241b5957692d9d8",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-router:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:7c40c573078a9c325402bd47b2eb78a46c0c80564a228cf7c9fcf0cfba5bc6d2",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-tunnel-client",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-tunnel-client:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:8ca553408a633d7f287ca9440f822fb1458dd9a028eb4db178b466b0b5505c49",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-tunnel-client:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:b141dc88557b8f6391aa082fdb37c6f0db5bc3a76c97bb39ba00354a9208abd8",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-edge-proxy",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-edge-proxy:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:480dea831051d45b6d63a489db9c0fa314f88bae35dbf72be4186bf1de356f38",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-edge-proxy:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:792505139793c3f3da7769f9dc9d1cb3203ff92797305b62e8f12207c69a9831",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-cli",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cli:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:125154cf59727ec230618c65b07a6235c18c1411f9ad51525ae411040169c9b5",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cli:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:43d1c175091bfb462eddd7dd22a780d6485d86bdb052c36b78201606f48fadc1",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-agent-skills",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-skills:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:5bdf9a4d17f8f4c7f3ecead99dcbd4de0ac346a2c28fef020b8853cf494df573",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-skills:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:c75510038dc33196dc254472e78101d545c0d777a7b33b531f02b39faf2588b5",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
}
|
||||
],
|
||||
"serviceCommitIds": [
|
||||
"73b379f"
|
||||
"7e29522"
|
||||
],
|
||||
"matchesSource": false,
|
||||
"publishVerified": true,
|
||||
@@ -233,7 +274,7 @@
|
||||
"registryCapabilities": {
|
||||
"version": "v1",
|
||||
"registryPrefix": "127.0.0.1:5000/hwlab",
|
||||
"generatedAt": "2026-05-22T04:31:07.663Z",
|
||||
"generatedAt": "2026-05-22T05:35:38.863Z",
|
||||
"classification": "degraded",
|
||||
"dimensions": {
|
||||
"processHttpAccess": {
|
||||
@@ -281,7 +322,7 @@
|
||||
"names": "unidesk-artifact-registry",
|
||||
"ports": "127.0.0.1:5000->5000/tcp",
|
||||
"state": "running",
|
||||
"status": "Up 27 hours"
|
||||
"status": "Up 28 hours"
|
||||
}
|
||||
],
|
||||
"pushAttempted": false,
|
||||
@@ -420,22 +461,48 @@
|
||||
"id": "target-commit-pinning",
|
||||
"category": "contract",
|
||||
"status": "blocked",
|
||||
"summary": "Source origin/main a1c3cb5 is not covered by deploy commit 73b379f, catalog commit 73b379f, service commits 73b379f.",
|
||||
"summary": "Source origin/main 82ad96c is not covered by artifact source 7e29522: target changes since the artifact source touch artifact build inputs.",
|
||||
"evidence": [
|
||||
{
|
||||
"source": {
|
||||
"ref": "origin/main",
|
||||
"commitId": "a1c3cb58da0067a12424277d47d9d50d0cbf7a9d",
|
||||
"shortCommitId": "a1c3cb5"
|
||||
"commitId": "82ad96c5c67c3906732a057d52395ec72851e4a9",
|
||||
"shortCommitId": "82ad96c"
|
||||
},
|
||||
"artifactSource": {
|
||||
"source": "artifact-publish-report",
|
||||
"ref": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33",
|
||||
"commitId": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33",
|
||||
"shortCommitId": "7e29522"
|
||||
},
|
||||
"targetCoverage": {
|
||||
"sourceKind": "artifact-publish-report",
|
||||
"sourceRef": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33",
|
||||
"sourceCommitId": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33",
|
||||
"sourceShortCommitId": "7e29522",
|
||||
"targetRef": "origin/main",
|
||||
"targetCommitId": "82ad96c5c67c3906732a057d52395ec72851e4a9",
|
||||
"targetShortCommitId": "82ad96c",
|
||||
"mode": "artifact-input-drift",
|
||||
"covered": false,
|
||||
"artifactBuildInputChanged": true,
|
||||
"changedPathCount": 22,
|
||||
"changedArtifactInputPaths": [
|
||||
"internal/mvp-gate/summary.mjs",
|
||||
"web/hwlab-cloud-web/gate-summary.mjs"
|
||||
],
|
||||
"changedNonArtifactPathCount": 20,
|
||||
"reason": "target changes since the artifact source touch artifact build inputs"
|
||||
},
|
||||
"deployManifest": {
|
||||
"path": "deploy/deploy.json",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false
|
||||
},
|
||||
"artifactCatalog": {
|
||||
"path": "deploy/artifact-catalog.dev.json",
|
||||
"commitId": "73b379f",
|
||||
"commitId": "7e29522",
|
||||
"artifactState": "published",
|
||||
"ciPublished": true,
|
||||
"registryVerified": true,
|
||||
@@ -447,155 +514,169 @@
|
||||
},
|
||||
"requiredServiceCount": 13,
|
||||
"disabledServiceCount": 0,
|
||||
"matchesSource": false
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false
|
||||
},
|
||||
"services": [
|
||||
{
|
||||
"serviceId": "hwlab-cloud-api",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cloud-api:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:561e50494bf13bf61f83d28b371bc39b860b21333ef9991711853a095bd535bf",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cloud-api:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:090b6f919be3b3c7594ca4073b193351689fc525f478b64d54d393725cb01ecf",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-cloud-web",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cloud-web:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:c7939658af9f1109e5384619163dd0d11e1a1de14e7d15d4cbde7c4400b495c2",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cloud-web:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:bc6e836b2bb796b30562ed3ae93d8534146a3b74a310906481c8641646d1b8f0",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-agent-mgr",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-mgr:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:ae6ca76cd09a7d21e46e0076e12dea1843417a0d59d57b3115915c831e88ebef",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-mgr:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:4d9b8944bc52012bb0a4a3a345f8939381d2804032e544d0c98f49fac0e46bfd",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-agent-worker",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-worker:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:4d5f8d8d404fc2826256fb690fdea5570285a34d1bdffbaf1e0c7ca39603ffd8",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:2582176e2c35a2bfbce4edfd922749397d45f6f1f8c04d0394c501f7d87323ee",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-gateway",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-gateway:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:ff9f3f3dc6332c3d8e4e9825657c296c9664d84a8d40c3ffeab3c1e91a484008",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-gateway:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:290341fd6e6f036aa953943072ad58e0d0cfcc0e13950e6090f941b3310755a6",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-gateway-simu",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-gateway-simu:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:f5ccff29da331e424a482f92394d071e1be90c0244e7137e07ac33d9a7cc4082",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-gateway-simu:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:02627f880c7ddf2102e2255a43097d1f604cfb7a22215736e328287e27fc5f03",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-box-simu",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-box-simu:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:2a12c1c462b2c01a9fa15efa75a6e1f17ecc8432dfa88bca53f0d8d4b6355daf",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-box-simu:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:e02c270c71f83a2f4624722bb84616bea8374ef43439f27bdce310e4baa8dcca",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-patch-panel",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-patch-panel:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:5bc9a1c7ce65026cd7bf6d20a311226b35c796a4d52a914266244bf3c1a17286",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-patch-panel:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:f730323f83c62797f382932582a05df921045c86383dad7951f3d639b32456a9",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-router",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-router:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:356f37a7d78cc2f86230c2037f43215ad66979fbe4a949cb9241b5957692d9d8",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-router:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:7c40c573078a9c325402bd47b2eb78a46c0c80564a228cf7c9fcf0cfba5bc6d2",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-tunnel-client",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-tunnel-client:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:8ca553408a633d7f287ca9440f822fb1458dd9a028eb4db178b466b0b5505c49",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-tunnel-client:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:b141dc88557b8f6391aa082fdb37c6f0db5bc3a76c97bb39ba00354a9208abd8",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-edge-proxy",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-edge-proxy:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:480dea831051d45b6d63a489db9c0fa314f88bae35dbf72be4186bf1de356f38",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-edge-proxy:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:792505139793c3f3da7769f9dc9d1cb3203ff92797305b62e8f12207c69a9831",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-cli",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cli:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:125154cf59727ec230618c65b07a6235c18c1411f9ad51525ae411040169c9b5",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cli:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:43d1c175091bfb462eddd7dd22a780d6485d86bdb052c36b78201606f48fadc1",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-agent-skills",
|
||||
"commitId": "73b379f",
|
||||
"matchesSource": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-skills:73b379f",
|
||||
"imageTag": "73b379f",
|
||||
"digest": "sha256:5bdf9a4d17f8f4c7f3ecead99dcbd4de0ac346a2c28fef020b8853cf494df573",
|
||||
"commitId": "7e29522",
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false,
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-skills:7e29522",
|
||||
"imageTag": "7e29522",
|
||||
"digest": "sha256:c75510038dc33196dc254472e78101d545c0d777a7b33b531f02b39faf2588b5",
|
||||
"publishState": "published",
|
||||
"artifactRequired": true,
|
||||
"notPublishedReason": null
|
||||
}
|
||||
],
|
||||
"serviceCommitIds": [
|
||||
"73b379f"
|
||||
"7e29522"
|
||||
],
|
||||
"matchesSource": false,
|
||||
"publishVerified": true,
|
||||
@@ -614,7 +695,7 @@
|
||||
"evidence": [
|
||||
{
|
||||
"path": "deploy/artifact-catalog.dev.json",
|
||||
"commitId": "73b379f",
|
||||
"commitId": "7e29522",
|
||||
"artifactState": "published",
|
||||
"ciPublished": true,
|
||||
"registryVerified": true,
|
||||
@@ -626,7 +707,8 @@
|
||||
},
|
||||
"requiredServiceCount": 13,
|
||||
"disabledServiceCount": 0,
|
||||
"matchesSource": false
|
||||
"matchesSource": true,
|
||||
"matchesTarget": false
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -696,7 +778,7 @@
|
||||
"names": "unidesk-artifact-registry",
|
||||
"ports": "127.0.0.1:5000->5000/tcp",
|
||||
"state": "running",
|
||||
"status": "Up 27 hours"
|
||||
"status": "Up 28 hours"
|
||||
}
|
||||
],
|
||||
"pushAttempted": false,
|
||||
@@ -834,7 +916,7 @@
|
||||
{
|
||||
"version": "v1",
|
||||
"registryPrefix": "127.0.0.1:5000/hwlab",
|
||||
"generatedAt": "2026-05-22T04:31:07.663Z",
|
||||
"generatedAt": "2026-05-22T05:35:38.863Z",
|
||||
"classification": "degraded",
|
||||
"dimensions": {
|
||||
"processHttpAccess": {
|
||||
@@ -882,7 +964,7 @@
|
||||
"names": "unidesk-artifact-registry",
|
||||
"ports": "127.0.0.1:5000->5000/tcp",
|
||||
"state": "running",
|
||||
"status": "Up 27 hours"
|
||||
"status": "Up 28 hours"
|
||||
}
|
||||
],
|
||||
"pushAttempted": false,
|
||||
@@ -1218,7 +1300,7 @@
|
||||
"id": "dev-artifact-publish-report",
|
||||
"category": "registry",
|
||||
"status": "blocked",
|
||||
"summary": "DEV artifact publish report status is published with 13/13 required services published for source 73b379f4441d47a99dfd978a80fd43727410af51; source states resolved: 13 source-present, 0 intentionally-disabled.",
|
||||
"summary": "DEV artifact publish report status is published with 13/13 required services published for source 7e29522b65c8a316b7c3fde12bebcb5f6baf8c33; source states resolved: 13 source-present, 0 intentionally-disabled.",
|
||||
"evidence": []
|
||||
},
|
||||
{
|
||||
@@ -1236,19 +1318,19 @@
|
||||
"host": "74.48.78.17",
|
||||
"port": 16667,
|
||||
"status": "connected",
|
||||
"durationMs": 212
|
||||
"durationMs": 228
|
||||
},
|
||||
{
|
||||
"host": "74.48.78.17",
|
||||
"port": 7000,
|
||||
"status": "connected",
|
||||
"durationMs": 1205
|
||||
"durationMs": 212
|
||||
},
|
||||
{
|
||||
"host": "74.48.78.17",
|
||||
"port": 7402,
|
||||
"status": "connected",
|
||||
"durationMs": 232
|
||||
"durationMs": 216
|
||||
}
|
||||
],
|
||||
"kubernetesObservable": true
|
||||
@@ -1324,7 +1406,7 @@
|
||||
"method": "GET",
|
||||
"status": 200,
|
||||
"statusText": "OK",
|
||||
"body": "{\"serviceId\":\"hwlab-cloud-api\",\"environment\":\"dev\",\"status\":\"degraded\",\"service\":{\"id\":\"hwlab-cloud-api\",\"role\":\"cloud-api\",\"healthPath\":\"/health\",\"livePath\":\"/health/live\"},\"commit\":{\"id\":\"cb35ada\",\"source\":\"runtime-env\"},\"image\":{\"reference\":\"127.0.0.1:5000/hwlab/hwlab-cloud-api:cb35ada\",\"tag\":\"cb35ada\",\"digest\":\"unknown\"},\"endpoint\":\"http://74.48.78.17:16667\",\"observedAt\":\"2026-05-22T04:31:08.245Z\",\"db\":{\"contractVersion\":\"v1\",\"environment\":\"dev\",\"connected\":false,\"connectionChecked\":false,\"c"
|
||||
"body": "{\"serviceId\":\"hwlab-cloud-api\",\"environment\":\"dev\",\"status\":\"degraded\",\"service\":{\"id\":\"hwlab-cloud-api\",\"role\":\"cloud-api\",\"healthPath\":\"/health\",\"livePath\":\"/health/live\"},\"commit\":{\"id\":\"cb35ada\",\"source\":\"runtime-env\"},\"image\":{\"reference\":\"127.0.0.1:5000/hwlab/hwlab-cloud-api:cb35ada\",\"tag\":\"cb35ada\",\"digest\":\"unknown\"},\"endpoint\":\"http://74.48.78.17:16667\",\"observedAt\":\"2026-05-22T05:35:39.607Z\",\"db\":{\"contractVersion\":\"v1\",\"environment\":\"dev\",\"connected\":false,\"connectionChecked\":false,\"c"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -1336,105 +1418,105 @@
|
||||
"evidence": [
|
||||
{
|
||||
"serviceId": "hwlab-cloud-api",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cloud-api:73b379f",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cloud-api:7e29522",
|
||||
"ok": false,
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-cloud-api/manifests/73b379f",
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-cloud-api/manifests/7e29522",
|
||||
"method": "HEAD",
|
||||
"error": "fetch failed ECONNREFUSED 127.0.0.1 5000"
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-cloud-web",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cloud-web:73b379f",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cloud-web:7e29522",
|
||||
"ok": false,
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-cloud-web/manifests/73b379f",
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-cloud-web/manifests/7e29522",
|
||||
"method": "HEAD",
|
||||
"error": "fetch failed ECONNREFUSED 127.0.0.1 5000"
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-agent-mgr",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-mgr:73b379f",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-mgr:7e29522",
|
||||
"ok": false,
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-agent-mgr/manifests/73b379f",
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-agent-mgr/manifests/7e29522",
|
||||
"method": "HEAD",
|
||||
"error": "fetch failed ECONNREFUSED 127.0.0.1 5000"
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-agent-worker",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-worker:73b379f",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522",
|
||||
"ok": false,
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-agent-worker/manifests/73b379f",
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-agent-worker/manifests/7e29522",
|
||||
"method": "HEAD",
|
||||
"error": "fetch failed ECONNREFUSED 127.0.0.1 5000"
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-gateway",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-gateway:73b379f",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-gateway:7e29522",
|
||||
"ok": false,
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-gateway/manifests/73b379f",
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-gateway/manifests/7e29522",
|
||||
"method": "HEAD",
|
||||
"error": "fetch failed ECONNREFUSED 127.0.0.1 5000"
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-gateway-simu",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-gateway-simu:73b379f",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-gateway-simu:7e29522",
|
||||
"ok": false,
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-gateway-simu/manifests/73b379f",
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-gateway-simu/manifests/7e29522",
|
||||
"method": "HEAD",
|
||||
"error": "fetch failed ECONNREFUSED 127.0.0.1 5000"
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-box-simu",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-box-simu:73b379f",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-box-simu:7e29522",
|
||||
"ok": false,
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-box-simu/manifests/73b379f",
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-box-simu/manifests/7e29522",
|
||||
"method": "HEAD",
|
||||
"error": "fetch failed ECONNREFUSED 127.0.0.1 5000"
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-patch-panel",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-patch-panel:73b379f",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-patch-panel:7e29522",
|
||||
"ok": false,
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-patch-panel/manifests/73b379f",
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-patch-panel/manifests/7e29522",
|
||||
"method": "HEAD",
|
||||
"error": "fetch failed ECONNREFUSED 127.0.0.1 5000"
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-router",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-router:73b379f",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-router:7e29522",
|
||||
"ok": false,
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-router/manifests/73b379f",
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-router/manifests/7e29522",
|
||||
"method": "HEAD",
|
||||
"error": "fetch failed ECONNREFUSED 127.0.0.1 5000"
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-tunnel-client",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-tunnel-client:73b379f",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-tunnel-client:7e29522",
|
||||
"ok": false,
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-tunnel-client/manifests/73b379f",
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-tunnel-client/manifests/7e29522",
|
||||
"method": "HEAD",
|
||||
"error": "fetch failed ECONNREFUSED 127.0.0.1 5000"
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-edge-proxy",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-edge-proxy:73b379f",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-edge-proxy:7e29522",
|
||||
"ok": false,
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-edge-proxy/manifests/73b379f",
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-edge-proxy/manifests/7e29522",
|
||||
"method": "HEAD",
|
||||
"error": "fetch failed ECONNREFUSED 127.0.0.1 5000"
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-cli",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cli:73b379f",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-cli:7e29522",
|
||||
"ok": false,
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-cli/manifests/73b379f",
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-cli/manifests/7e29522",
|
||||
"method": "HEAD",
|
||||
"error": "fetch failed ECONNREFUSED 127.0.0.1 5000"
|
||||
},
|
||||
{
|
||||
"serviceId": "hwlab-agent-skills",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-skills:73b379f",
|
||||
"image": "127.0.0.1:5000/hwlab/hwlab-agent-skills:7e29522",
|
||||
"ok": false,
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-agent-skills/manifests/73b379f",
|
||||
"url": "http://127.0.0.1:5000/v2/hwlab/hwlab-agent-skills/manifests/7e29522",
|
||||
"method": "HEAD",
|
||||
"error": "fetch failed ECONNREFUSED 127.0.0.1 5000"
|
||||
}
|
||||
@@ -1446,7 +1528,7 @@
|
||||
"status": "open",
|
||||
"type": "contract_blocker",
|
||||
"scope": "artifact-source-commit",
|
||||
"summary": "source commit origin/main a1c3cb5 does not match deploy/catalog artifact identity: deploy=73b379f, catalog=73b379f, services=73b379f.",
|
||||
"summary": "source commit origin/main 82ad96c is not covered by artifact source 7e29522; target changes since the artifact source touch artifact build inputs.",
|
||||
"nextTask": "Refresh without fake digests using `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --blocked`, or after a successful publish run `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report reports/dev-gate/dev-artifacts.json`."
|
||||
},
|
||||
{
|
||||
@@ -1460,8 +1542,8 @@
|
||||
"status": "open",
|
||||
"type": "runtime_blocker",
|
||||
"scope": "dev-artifact-publish",
|
||||
"summary": "reports/dev-gate/dev-artifacts.json does not prove all required HWLAB service artifacts for origin/main a1c3cb5; current status is published with 13/13 required services published and source states resolved: 13 source-present, 0 intentionally-disabled.",
|
||||
"nextTask": "Complete DEV artifact publishing for every enabled required HWLAB service at the current origin/main commit and record immutable registry digests; keep disabled services marked not_published with reasons."
|
||||
"summary": "reports/dev-gate/dev-artifacts.json does not prove all required HWLAB service artifacts for origin/main 82ad96c; current status is published with 13/13 required services published and source states resolved: 13 source-present, 0 intentionally-disabled.",
|
||||
"nextTask": "Complete DEV artifact publishing for every enabled required HWLAB service at the artifact source commit, or prove the target commit has no artifact build input changes; keep disabled services marked not_published with reasons."
|
||||
},
|
||||
{
|
||||
"status": "open",
|
||||
|
||||
@@ -8,6 +8,8 @@ import { DEV_ENDPOINT, ENVIRONMENT_DEV, SERVICE_IDS } from "../../internal/proto
|
||||
|
||||
export const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
|
||||
const deprecatedLegacyPublicPort = 6000 + 667;
|
||||
const deprecatedLegacyPublicEndpoint = `http://74.48.78.17:${deprecatedLegacyPublicPort}`;
|
||||
const levels = Object.freeze(["SOURCE", "LOCAL", "DRY-RUN", "DEV-LIVE", "BLOCKED"]);
|
||||
const statusRank = Object.freeze({
|
||||
pass: 0,
|
||||
@@ -263,9 +265,7 @@ function isEdgeOrFrpBlocker(blocker) {
|
||||
blocker.scope.includes("ingress") ||
|
||||
blocker.scope.includes("frp") ||
|
||||
blocker.summary.includes(":16667") ||
|
||||
blocker.summary.includes("16667") ||
|
||||
blocker.summary.includes(":6667") ||
|
||||
blocker.summary.includes("6667");
|
||||
blocker.summary.includes("16667");
|
||||
}
|
||||
|
||||
function sourceEntry(entry) {
|
||||
@@ -519,7 +519,7 @@ function hasCurrentLiveEdgeEvidence(edgeReport) {
|
||||
|
||||
function isStaleLegacyIngressBlocker(blocker, sourceReport, reports) {
|
||||
const text = `${blocker.scope ?? ""} ${blocker.summary ?? ""}`;
|
||||
const staleLegacyPort = text.includes("74.48.78.17:6667");
|
||||
const staleLegacyPort = text.includes(deprecatedLegacyPublicEndpoint);
|
||||
const stalePreflightEdgeProbe = sourceReport.path === reportPaths.devPreflight &&
|
||||
blocker.type === "network_blocker" &&
|
||||
(blocker.scope === "dev-edge" || blocker.scope === "dev-edge-health") &&
|
||||
|
||||
@@ -17,9 +17,9 @@ const execFileAsync = promisify(execFile);
|
||||
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const defaultReportPath = "reports/dev-gate/dev-preflight-report.json";
|
||||
const issue = "pikasTech/HWLAB#34";
|
||||
const supports = ["#7", "#12", "#14", "#22", "#23", "#29", "#30", "#31", "#33", "#39", "#49", "#66"].map(
|
||||
const supports = ["#7", "#12", "#14", "#22", "#23", "#29", "#30", "#31", "#33", "#35", "#39", "#43", "#48", "#49", "#57", "#66"].map(
|
||||
(id) => `pikasTech/HWLAB${id}`
|
||||
).concat(["pikasTech/HWLAB#33", "pikasTech/HWLAB#35", "pikasTech/HWLAB#48"]);
|
||||
);
|
||||
const forbiddenActions = [
|
||||
"prod-deploy",
|
||||
"secret-material-read",
|
||||
@@ -39,6 +39,20 @@ const blockerTypes = new Set([
|
||||
"safety_blocker"
|
||||
]);
|
||||
const digestPattern = /^sha256:[a-f0-9]{64}$/;
|
||||
const artifactBuildInputPrefixes = [
|
||||
"cmd/",
|
||||
"internal/",
|
||||
"skills/",
|
||||
"tools/",
|
||||
"web/"
|
||||
];
|
||||
const artifactBuildInputFiles = new Set([
|
||||
"package.json",
|
||||
"package-lock.json",
|
||||
"npm-shrinkwrap.json",
|
||||
"scripts/dev-artifact-publish.mjs",
|
||||
"scripts/src/dev-artifact-services.mjs"
|
||||
]);
|
||||
|
||||
function parseArgs(argv) {
|
||||
const args = {
|
||||
@@ -210,6 +224,125 @@ function matchesTargetCommit(value, targetCommit, targetShortCommit) {
|
||||
return value === targetCommit || value === targetShortCommit;
|
||||
}
|
||||
|
||||
function isArtifactBuildInputPath(relativePath) {
|
||||
return artifactBuildInputFiles.has(relativePath) ||
|
||||
artifactBuildInputPrefixes.some((prefix) => relativePath.startsWith(prefix));
|
||||
}
|
||||
|
||||
async function resolveCommit(ref) {
|
||||
if (!ref) return null;
|
||||
const result = await run("git", ["rev-parse", `${ref}^{commit}`]);
|
||||
if (!result.ok || !/^[a-f0-9]{40}$/u.test(result.stdout)) return null;
|
||||
return result.stdout;
|
||||
}
|
||||
|
||||
async function sourceCoverageFor({ catalog, artifactReport, targetCommit, targetShortCommit, targetRef }) {
|
||||
const reportSource = artifactReport?.artifactPublish?.sourceCommitId ?? artifactReport?.commitId ?? null;
|
||||
const sourceRef = reportSource ?? catalog.commitId;
|
||||
const sourceKind = reportSource ? "artifact-publish-report" : "artifact-catalog";
|
||||
const sourceCommit = await resolveCommit(sourceRef);
|
||||
|
||||
if (!sourceCommit) {
|
||||
return {
|
||||
sourceKind,
|
||||
sourceRef,
|
||||
sourceCommitId: null,
|
||||
sourceShortCommitId: null,
|
||||
targetRef,
|
||||
targetCommitId: targetCommit,
|
||||
targetShortCommitId: targetShortCommit,
|
||||
mode: "unresolved-source",
|
||||
covered: false,
|
||||
artifactBuildInputChanged: true,
|
||||
changedPathCount: 0,
|
||||
changedArtifactInputPaths: [],
|
||||
changedNonArtifactPathCount: 0,
|
||||
reason: `artifact source ${sourceRef ?? "unknown"} does not resolve to a local git commit`
|
||||
};
|
||||
}
|
||||
|
||||
if (matchesTargetCommit(sourceCommit, targetCommit, targetShortCommit)) {
|
||||
return {
|
||||
sourceKind,
|
||||
sourceRef,
|
||||
sourceCommitId: sourceCommit,
|
||||
sourceShortCommitId: sourceCommit.slice(0, 7),
|
||||
targetRef,
|
||||
targetCommitId: targetCommit,
|
||||
targetShortCommitId: targetShortCommit,
|
||||
mode: "exact-target",
|
||||
covered: true,
|
||||
artifactBuildInputChanged: false,
|
||||
changedPathCount: 0,
|
||||
changedArtifactInputPaths: [],
|
||||
changedNonArtifactPathCount: 0,
|
||||
reason: "artifact source commit exactly matches the target ref"
|
||||
};
|
||||
}
|
||||
|
||||
const ancestor = await run("git", ["merge-base", "--is-ancestor", sourceCommit, targetCommit]);
|
||||
if (!ancestor.ok) {
|
||||
return {
|
||||
sourceKind,
|
||||
sourceRef,
|
||||
sourceCommitId: sourceCommit,
|
||||
sourceShortCommitId: sourceCommit.slice(0, 7),
|
||||
targetRef,
|
||||
targetCommitId: targetCommit,
|
||||
targetShortCommitId: targetShortCommit,
|
||||
mode: "non-ancestor-source",
|
||||
covered: false,
|
||||
artifactBuildInputChanged: true,
|
||||
changedPathCount: 0,
|
||||
changedArtifactInputPaths: [],
|
||||
changedNonArtifactPathCount: 0,
|
||||
reason: `artifact source ${sourceCommit.slice(0, 12)} is not an ancestor of ${targetRef} ${targetShortCommit}`
|
||||
};
|
||||
}
|
||||
|
||||
const diff = await run("git", ["diff", "--name-only", `${sourceCommit}..${targetCommit}`]);
|
||||
if (!diff.ok) {
|
||||
return {
|
||||
sourceKind,
|
||||
sourceRef,
|
||||
sourceCommitId: sourceCommit,
|
||||
sourceShortCommitId: sourceCommit.slice(0, 7),
|
||||
targetRef,
|
||||
targetCommitId: targetCommit,
|
||||
targetShortCommitId: targetShortCommit,
|
||||
mode: "diff-unavailable",
|
||||
covered: false,
|
||||
artifactBuildInputChanged: true,
|
||||
changedPathCount: 0,
|
||||
changedArtifactInputPaths: [],
|
||||
changedNonArtifactPathCount: 0,
|
||||
reason: diff.stderr || diff.error || "git diff failed"
|
||||
};
|
||||
}
|
||||
|
||||
const changedPaths = diff.stdout.split("\n").map((line) => line.trim()).filter(Boolean);
|
||||
const changedArtifactInputPaths = changedPaths.filter(isArtifactBuildInputPath);
|
||||
const covered = changedArtifactInputPaths.length === 0;
|
||||
return {
|
||||
sourceKind,
|
||||
sourceRef,
|
||||
sourceCommitId: sourceCommit,
|
||||
sourceShortCommitId: sourceCommit.slice(0, 7),
|
||||
targetRef,
|
||||
targetCommitId: targetCommit,
|
||||
targetShortCommitId: targetShortCommit,
|
||||
mode: covered ? "report-only-target" : "artifact-input-drift",
|
||||
covered,
|
||||
artifactBuildInputChanged: changedArtifactInputPaths.length > 0,
|
||||
changedPathCount: changedPaths.length,
|
||||
changedArtifactInputPaths,
|
||||
changedNonArtifactPathCount: changedPaths.length - changedArtifactInputPaths.length,
|
||||
reason: covered
|
||||
? "target changes since the artifact source do not touch artifact build inputs"
|
||||
: "target changes since the artifact source touch artifact build inputs"
|
||||
};
|
||||
}
|
||||
|
||||
function uniqueSorted(values) {
|
||||
return [...new Set(values)].sort();
|
||||
}
|
||||
@@ -238,15 +371,24 @@ function disabledCatalogServices(catalog) {
|
||||
return (catalog.services ?? []).filter((service) => service.artifactRequired === false);
|
||||
}
|
||||
|
||||
function artifactIdentityFor({ deploy, catalog, targetCommit, targetShortCommit, targetRef }) {
|
||||
async function artifactIdentityFor({ deploy, catalog, artifactReport, targetCommit, targetShortCommit, targetRef }) {
|
||||
const targetCoverage = await sourceCoverageFor({
|
||||
catalog,
|
||||
artifactReport,
|
||||
targetCommit,
|
||||
targetShortCommit,
|
||||
targetRef
|
||||
});
|
||||
const artifactSourceCommit = targetCoverage.sourceCommitId ?? targetCommit;
|
||||
const artifactSourceShortCommit = targetCoverage.sourceShortCommitId ?? targetShortCommit;
|
||||
const serviceCommitIds = uniqueSorted((catalog.services ?? []).map((service) => service.commitId));
|
||||
const digestCounts = catalogDigestCounts(catalog);
|
||||
const requiredServices = requiredCatalogServices(catalog);
|
||||
const disabledServices = disabledCatalogServices(catalog);
|
||||
const catalogMatchesSource = matchesTargetCommit(catalog.commitId, targetCommit, targetShortCommit);
|
||||
const deployMatchesSource = matchesTargetCommit(deploy.commitId, targetCommit, targetShortCommit);
|
||||
const catalogMatchesSource = matchesTargetCommit(catalog.commitId, artifactSourceCommit, artifactSourceShortCommit);
|
||||
const deployMatchesSource = matchesTargetCommit(deploy.commitId, artifactSourceCommit, artifactSourceShortCommit);
|
||||
const servicesMatchSource = serviceCommitIds.length === 1 &&
|
||||
matchesTargetCommit(serviceCommitIds[0], targetCommit, targetShortCommit);
|
||||
matchesTargetCommit(serviceCommitIds[0], artifactSourceCommit, artifactSourceShortCommit);
|
||||
const allRequiredDigestsPublished = requiredServices.length > 0 &&
|
||||
requiredServices.every((service) => digestPattern.test(service.digest) && service.publishState === "published") &&
|
||||
disabledServices.every((service) => service.digest === "not_published" && service.publishState === "skeleton-only") &&
|
||||
@@ -262,10 +404,18 @@ function artifactIdentityFor({ deploy, catalog, targetCommit, targetShortCommit,
|
||||
commitId: targetCommit,
|
||||
shortCommitId: targetShortCommit
|
||||
},
|
||||
artifactSource: {
|
||||
source: targetCoverage.sourceKind,
|
||||
ref: targetCoverage.sourceRef,
|
||||
commitId: targetCoverage.sourceCommitId,
|
||||
shortCommitId: targetCoverage.sourceShortCommitId
|
||||
},
|
||||
targetCoverage,
|
||||
deployManifest: {
|
||||
path: "deploy/deploy.json",
|
||||
commitId: deploy.commitId,
|
||||
matchesSource: deployMatchesSource
|
||||
matchesSource: deployMatchesSource,
|
||||
matchesTarget: matchesTargetCommit(deploy.commitId, targetCommit, targetShortCommit)
|
||||
},
|
||||
artifactCatalog: {
|
||||
path: "deploy/artifact-catalog.dev.json",
|
||||
@@ -277,12 +427,14 @@ function artifactIdentityFor({ deploy, catalog, targetCommit, targetShortCommit,
|
||||
digestCounts,
|
||||
requiredServiceCount: requiredServices.length,
|
||||
disabledServiceCount: disabledServices.length,
|
||||
matchesSource: catalogMatchesSource
|
||||
matchesSource: catalogMatchesSource,
|
||||
matchesTarget: matchesTargetCommit(catalog.commitId, targetCommit, targetShortCommit)
|
||||
},
|
||||
services: (catalog.services ?? []).map((service) => ({
|
||||
serviceId: service.serviceId,
|
||||
commitId: service.commitId,
|
||||
matchesSource: matchesTargetCommit(service.commitId, targetCommit, targetShortCommit),
|
||||
matchesSource: matchesTargetCommit(service.commitId, artifactSourceCommit, artifactSourceShortCommit),
|
||||
matchesTarget: matchesTargetCommit(service.commitId, targetCommit, targetShortCommit),
|
||||
image: service.image,
|
||||
imageTag: service.imageTag,
|
||||
digest: service.digest,
|
||||
@@ -291,7 +443,7 @@ function artifactIdentityFor({ deploy, catalog, targetCommit, targetShortCommit,
|
||||
notPublishedReason: service.notPublishedReason ?? null
|
||||
})),
|
||||
serviceCommitIds,
|
||||
matchesSource: deployMatchesSource && catalogMatchesSource && servicesMatchSource,
|
||||
matchesSource: targetCoverage.covered && deployMatchesSource && catalogMatchesSource && servicesMatchSource,
|
||||
publishVerified,
|
||||
refreshCommands: {
|
||||
blocked: `node scripts/refresh-artifact-catalog.mjs --target-ref ${targetRef} --blocked`,
|
||||
@@ -399,9 +551,16 @@ function makeReporter() {
|
||||
};
|
||||
}
|
||||
|
||||
function validateLocalContracts(reporter, contracts, targetShortCommit, targetCommit, targetRef) {
|
||||
async function validateLocalContracts(reporter, contracts, optionalReports, targetShortCommit, targetCommit, targetRef) {
|
||||
const [deploy, catalog, namespace, workloads, services, devKustomization, healthContract, masterEdge] = contracts;
|
||||
const artifactIdentity = artifactIdentityFor({ deploy, catalog, targetCommit, targetShortCommit, targetRef });
|
||||
const artifactIdentity = await artifactIdentityFor({
|
||||
deploy,
|
||||
catalog,
|
||||
artifactReport: optionalReports.artifactPublish,
|
||||
targetCommit,
|
||||
targetShortCommit,
|
||||
targetRef
|
||||
});
|
||||
|
||||
try {
|
||||
assertStaticContract(deploy, catalog);
|
||||
@@ -417,25 +576,30 @@ function validateLocalContracts(reporter, contracts, targetShortCommit, targetCo
|
||||
}
|
||||
|
||||
if (artifactIdentity.matchesSource) {
|
||||
const coverage = artifactIdentity.targetCoverage;
|
||||
const coverageSuffix = coverage.mode === "exact-target"
|
||||
? "exact target commit"
|
||||
: `${coverage.mode}; ${coverage.changedPathCount} changed path(s), ${coverage.changedArtifactInputPaths.length} artifact input change(s)`;
|
||||
reporter.check(
|
||||
"target-commit-pinning",
|
||||
"contract",
|
||||
"pass",
|
||||
`Source ${targetRef} ${targetShortCommit} matches deploy/catalog artifact commit ${artifactIdentity.artifactCatalog.commitId}.`,
|
||||
`Source ${targetRef} ${targetShortCommit} is covered by artifact source ${artifactIdentity.artifactSource.shortCommitId}; ${coverageSuffix}.`,
|
||||
[artifactIdentity]
|
||||
);
|
||||
} else {
|
||||
const coverage = artifactIdentity.targetCoverage;
|
||||
reporter.check(
|
||||
"target-commit-pinning",
|
||||
"contract",
|
||||
"blocked",
|
||||
`Source ${targetRef} ${targetShortCommit} is not covered by deploy commit ${deploy.commitId}, catalog commit ${catalog.commitId}, service commits ${artifactIdentity.serviceCommitIds.join(", ")}.`,
|
||||
`Source ${targetRef} ${targetShortCommit} is not covered by artifact source ${artifactIdentity.artifactSource.shortCommitId ?? "unknown"}: ${coverage.reason}.`,
|
||||
[artifactIdentity]
|
||||
);
|
||||
reporter.block({
|
||||
type: "contract_blocker",
|
||||
scope: "artifact-source-commit",
|
||||
summary: `source commit ${targetRef} ${targetShortCommit} does not match deploy/catalog artifact identity: deploy=${deploy.commitId}, catalog=${catalog.commitId}, services=${artifactIdentity.serviceCommitIds.join(", ")}.`,
|
||||
summary: `source commit ${targetRef} ${targetShortCommit} is not covered by artifact source ${artifactIdentity.artifactSource.shortCommitId ?? "unknown"}; ${coverage.reason}.`,
|
||||
nextTask: `Refresh without fake digests using \`${artifactIdentity.refreshCommands.blocked}\`, or after a successful publish run \`${artifactIdentity.refreshCommands.published}\`.`
|
||||
});
|
||||
}
|
||||
@@ -480,7 +644,7 @@ function validateLocalContracts(reporter, contracts, targetShortCommit, targetCo
|
||||
return { deploy, catalog, masterEdge, artifactIdentity };
|
||||
}
|
||||
|
||||
function validateArtifactPublishReport(reporter, artifactReport, targetShortCommit, targetCommit, targetRef) {
|
||||
function validateArtifactPublishReport(reporter, artifactReport, artifactIdentity, targetShortCommit, targetCommit, targetRef) {
|
||||
if (!artifactReport) {
|
||||
reporter.check("dev-artifact-publish-report", "registry", "blocked", "No DEV artifact publish report is present.");
|
||||
reporter.block({
|
||||
@@ -510,15 +674,26 @@ function validateArtifactPublishReport(reporter, artifactReport, targetShortComm
|
||||
);
|
||||
const sourceMatchesTarget = [targetCommit, targetShortCommit].includes(artifactPublish?.sourceCommitId) ||
|
||||
[targetCommit, targetShortCommit].includes(artifactReport.commitId);
|
||||
const sourceCoversTarget = artifactIdentity?.targetCoverage?.covered === true &&
|
||||
artifactIdentity?.artifactSource?.commitId &&
|
||||
(
|
||||
artifactPublish?.sourceCommitId === artifactIdentity.artifactSource.commitId ||
|
||||
artifactPublish?.sourceCommitId === artifactIdentity.artifactSource.shortCommitId ||
|
||||
artifactReport.commitId === artifactIdentity.artifactSource.commitId ||
|
||||
artifactReport.commitId === artifactIdentity.artifactSource.shortCommitId
|
||||
);
|
||||
const publishReady = artifactPublish?.status === "published" &&
|
||||
artifactPublish.publishedCount === requiredServices.length &&
|
||||
allServicesAccountedFor &&
|
||||
allRequiredServicesPublished &&
|
||||
disabledServicesNotPublished &&
|
||||
sourceMatchesTarget;
|
||||
(sourceMatchesTarget || sourceCoversTarget);
|
||||
|
||||
if (publishReady) {
|
||||
reporter.check("dev-artifact-publish-report", "registry", "pass", "DEV artifact publish report covers all required enabled service IDs with immutable digests for the target commit, and records disabled service reasons.");
|
||||
const summary = sourceMatchesTarget
|
||||
? "DEV artifact publish report covers all required enabled service IDs with immutable digests for the target commit, and records disabled service reasons."
|
||||
: `DEV artifact publish report covers artifact source ${artifactIdentity.artifactSource.shortCommitId}; target ${targetRef} ${targetShortCommit} has no artifact build input changes since that source.`;
|
||||
reporter.check("dev-artifact-publish-report", "registry", "pass", summary, [artifactIdentity?.targetCoverage].filter(Boolean));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -537,7 +712,7 @@ function validateArtifactPublishReport(reporter, artifactReport, targetShortComm
|
||||
type: "runtime_blocker",
|
||||
scope: "dev-artifact-publish",
|
||||
summary: `reports/dev-gate/dev-artifacts.json does not prove all required HWLAB service artifacts for ${targetRef} ${targetShortCommit}; current status is ${artifactPublish?.status ?? "missing"} with ${publishedCount}/${requiredServices.length || serviceCount} required services published and ${sourceSummary}.`,
|
||||
nextTask: "Complete DEV artifact publishing for every enabled required HWLAB service at the current origin/main commit and record immutable registry digests; keep disabled services marked not_published with reasons."
|
||||
nextTask: "Complete DEV artifact publishing for every enabled required HWLAB service at the artifact source commit, or prove the target commit has no artifact build input changes; keep disabled services marked not_published with reasons."
|
||||
});
|
||||
}
|
||||
|
||||
@@ -868,9 +1043,9 @@ async function validateLiveProbes(reporter, catalog, timeoutMs) {
|
||||
if (registryStatus === "blocked") {
|
||||
reporter.block({
|
||||
type: "runtime_blocker",
|
||||
scope: "catalog-image-manifest-read",
|
||||
summary: "This preflight could not verify registry manifests for the required DEV catalog images without reading credentials.",
|
||||
nextTask: "Publish required DEV images or provide a non-secret registry evidence artifact with immutable digests for each required HWLAB service."
|
||||
scope: "registry-manifest-read",
|
||||
summary: "This preflight could not verify catalog image manifests through the runner process path; this is a #66 registry reachability dimension, not evidence that publish digests are missing.",
|
||||
nextTask: "Resolve the #66 registry reachability path or provide a non-secret registry reachability artifact; do not rerun heavy publish solely for this manifest-read probe."
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -987,9 +1162,10 @@ export async function runPreflight(argv) {
|
||||
registryPrefix,
|
||||
timeoutMs: args.timeoutMs
|
||||
});
|
||||
const { deploy, catalog, masterEdge, artifactIdentity } = validateLocalContracts(
|
||||
const { deploy, catalog, masterEdge, artifactIdentity } = await validateLocalContracts(
|
||||
reporter,
|
||||
contracts,
|
||||
optionalReports,
|
||||
targetShortCommit,
|
||||
targetCommit,
|
||||
args.targetRef
|
||||
@@ -997,7 +1173,7 @@ export async function runPreflight(argv) {
|
||||
|
||||
validateRegistryCapabilities(reporter, registryCapabilities);
|
||||
validateCloudApiDbContract(reporter, deploy, contracts[3]);
|
||||
validateArtifactPublishReport(reporter, optionalReports.artifactPublish, targetShortCommit, targetCommit, args.targetRef);
|
||||
validateArtifactPublishReport(reporter, optionalReports.artifactPublish, artifactIdentity, targetShortCommit, targetCommit, args.targetRef);
|
||||
validateEdgeHealthReport(reporter, optionalReports.edgeHealth);
|
||||
await validateEdgeContracts(reporter, masterEdge);
|
||||
validateRuntimeBoundary(reporter, deploy);
|
||||
|
||||
Reference in New Issue
Block a user