8.4 KiB
HWLAB DEV Artifact Publish
scripts/dev-artifact-publish.mjs is the DEV-only build and publish path for
D601 local/internal registry artifacts. It does not deploy workloads, read
secrets, enable PROD, or push to GHCR/Docker Hub/other third-party registries.
Scope
- Environment:
dev. - Namespace:
hwlab-dev. - Default registry prefix:
127.0.0.1:5000/hwlab. - Base image: resolved by
scripts/preflight-dev-base-image.mjsfromHWLAB_DEV_BASE_IMAGE, a localnode:20-*Docker image, or a local HWLAB base tag such as127.0.0.1:5000/hwlab/hwlab-dev-base:node20-bookworm-slim. There is no base-image pull or third-party fallback during publish; the build runs with--pull=false. - Node runtime dependencies are installed from the source
package.jsonandpackage-lock.jsoninside the DEV image build withnpm ci --omit=dev --ignore-scriptswhen the lockfile is present. This includes the Postgrespgdriver required by the durable cloud-api runtime adapter. - Image tag: first seven characters of the Git commit used as build source.
- Required image labels:
hwlab.pikastech.local/repohwlab.pikastech.local/commithwlab.pikastech.local/service-idhwlab.pikastech.local/environment=dev
Commands
Static check:
node --check scripts/preflight-dev-base-image.mjs
node --check scripts/src/dev-base-image-preflight.mjs
node --check scripts/src/dev-artifact-services.mjs
node --check scripts/src/registry-capabilities.mjs
node --check scripts/dev-artifact-publish.mjs
node --check scripts/refresh-artifact-catalog.mjs
Base image preflight:
node scripts/preflight-dev-base-image.mjs
Preflight and report generation:
node scripts/dev-artifact-publish.mjs --preflight
Build only:
node scripts/dev-artifact-publish.mjs --build
Build and publish to the D601 local/internal registry:
node scripts/dev-artifact-publish.mjs --publish
Daily Cloud Web source validation does not require ignored dist/ to exist:
node web/hwlab-cloud-web/scripts/check.mjs
For hwlab-cloud-web, the build/publish path refreshes and verifies the static
bundle before image build:
node web/hwlab-cloud-web/scripts/build.mjs
node scripts/dev-artifact-publish.mjs --publish --services hwlab-cloud-web --report reports/dev-gate/dev-artifacts-hwlab-cloud-web-<tag>.json
The runtime wrapper serves /app/web/hwlab-cloud-web/dist before the source
directory. If dist is stale, a newly tagged image can still serve old HTML,
CSS, and JavaScript. A publish for Cloud Web is not valid until the image has
fresh dist evidence. build.mjs regenerates dist and verifies every
runtime file and route alias matches source. dev-artifact-publish.mjs
re-runs that build/freshness gate and records
artifactPublish.services[].distFreshness for hwlab-cloud-web before the
Docker build. check.mjs remains a clean-checkout source contract and must not
fail only because ignored dist/ is absent.
Use --registry-prefix only for another localhost/private/internal D601
registry prefix. The script rejects third-party registry hosts and any prefix
that names PROD. Use --base-image only to override HWLAB_DEV_BASE_IMAGE with
an approved local image for that run.
Report
The script writes reports/dev-gate/dev-artifacts.json. The file is kept in the
existing DEV gate report envelope for compatibility with
scripts/validate-dev-gate-report.mjs, while the artifactPublish object is
the HWLAB#35-specific publish record.
Each service record contains:
serviceIdimageimageTagdigestdistFreshnessforhwlab-cloud-webbuild/publish runspublishEnabledartifactRequiredartifactScopenotPublishedReasonruntimeKindimplementationStatesourceStateentrypoint
The report also carries artifactPublish.serviceInventory and
artifactPublish.publishPlan. serviceInventory is the resolved frozen service
list with enabled/disabled state. publishPlan is the machine-readable v2 plan:
source commit, image tag, per-service registry target, image reference, digest
placeholder or real digest, registry capability evidence, and the reason a
service was not published.
The report also includes artifactPublish.registryCapabilities, split into
three dimensions:
process-http-access: runner-process HTTP access to the registry/v2/endpoint. This is diagnostic only. A failedhttp://127.0.0.1:5000/v2/fetch from the runner process isdegraded, not proof that Docker publish failed.docker-daemon-push-access: Docker daemon view of the local/internal registry target. This is the publish-path capability and is the only registry capability that blocks--publishbefore a push attempt.k3s-pull-access: read-only k3s view ofhwlab-devimage pull state. This is the deploy-path capability and does not prove or disprove Docker daemon push access.
digest is only set to a registry digest after docker push succeeds and the
push output contains a sha256:<64 hex> digest. If the push succeeds but no
digest is observable, the service remains published_unverified_digest,
digest stays not_published, and the report carries a blocker. The script
records blockers instead of claiming a publish when build, push, digest
observation, base image, registry, contract, or safety checks fail.
After a fully successful publish, update the catalog from the report:
node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report reports/dev-gate/dev-artifacts.json
If publish remains blocked, refresh only commit/tag identity and keep digests blocked:
node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --blocked
Before any later DEV apply review, run the read-only artifact/runtime guard so artifact evidence is not mistaken for deployed runtime evidence:
node scripts/artifact-runtime-readiness-guard.mjs --target-ref origin/main --check --no-report --expect-blocked
The guard must remain blocked until the target commit, publish report, artifact
catalog, desired-state files, Cloud API /health/live, and Cloud Web
:16666/health/live all report the same identity. It does not publish, deploy,
restart services, mutate Kubernetes, touch PROD, or read secrets.
The report also includes artifactPublish.baseImagePreflight with the image
source, local tag, local image ID, publishUsable gate, blockers, and next
steps. It also carries recommendation, provision, and blockedReport
objects so the blocked report includes the exact blocker, expected image tag,
recommended HWLAB_DEV_BASE_IMAGE value, and preload commands. When that
preflight is blocked, artifact publish is blocked and no build or push is
attempted.
If the D601 builder has no approved Node 20 base image, or the selected DEV
registry is not reachable from the Docker daemon publish path, the report must
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.
Committed DEV artifact reports are evidence snapshots and may lag the deploy
desired-state files. Use scripts/deploy-desired-state-plan.mjs to see whether
the report source matches the desired-state commit, then refresh the catalog
from a publish report only when that report proves the same target source
commit. 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 hascmd/<serviceId>/main.mjs.static-web-wrapper: the cloud web static files are packaged behind a small health/static-file wrapper.repo-bundle: the image packages repository-owned skill artifacts.library-only: the repository has library code but no executable package bin.missing-runtime-entrypoint: the image is only a health placeholder and is not a real service implementation.
Known Source States
source-present: the service remains in the MVP artifact catalog and has a repository-owned source path or entrypoint conclusion.intentionally-disabled: the service is explicitly out of the MVP artifact publish set until it is given source. It must not remain a vague blocker.
Runtime implementation blockers do not fake a service implementation. They are recorded as the next minimum work needed after artifact publication.