Skip to content

Commit 7fe004d

Browse files
authored
feat: show build identity in About screens (#103595)
* feat: show build identity in About screens * chore: leave root changelog to release automation * fix: translate Control UI About build details
1 parent 1f3ea6f commit 7fe004d

139 files changed

Lines changed: 4971 additions & 563 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/android-release.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ jobs:
6363
github-token: ${{ github.token }}
6464

6565
- name: Validate release approval and target
66+
id: release_approval
6667
env:
6768
APPROVAL_PATH: ${{ runner.temp }}/android-release-approval/approval.json
6869
DIRECT_RELEASE_RECOVERY: ${{ inputs.direct_release_recovery && 'true' || 'false' }}
@@ -105,7 +106,7 @@ jobs:
105106
exit 1
106107
fi
107108
108-
release_json="$(gh release view "${RELEASE_TAG}" --repo "${GITHUB_REPOSITORY}" --json tagName,isDraft,isPrerelease,assets,url)"
109+
release_json="$(gh release view "${RELEASE_TAG}" --repo "${GITHUB_REPOSITORY}" --json tagName,isDraft,isPrerelease,createdAt,assets,url)"
109110
if [[ "$(printf '%s' "${release_json}" | jq -r '.tagName')" != "${RELEASE_TAG}" ]]; then
110111
echo "GitHub release tag does not match ${RELEASE_TAG}." >&2
111112
exit 1
@@ -118,6 +119,9 @@ jobs:
118119
echo "Normal Android promotion requires the target GitHub release to remain a draft." >&2
119120
exit 1
120121
fi
122+
release_created_at="$(printf '%s' "${release_json}" | jq -er '.createdAt')"
123+
build_timestamp="$(date -u -d "${release_created_at}" +%Y-%m-%dT%H:%M:%SZ)"
124+
echo "build_timestamp=${build_timestamp}" >> "${GITHUB_OUTPUT}"
121125
unexpected_assets="$(printf '%s' "${release_json}" | jq -r '[.assets[]? | select(.name | startswith("OpenClaw-Android")) | .name] | join(", ")')"
122126
if [[ -n "${unexpected_assets}" ]]; then
123127
echo "Target release already contains Android assets: ${unexpected_assets}. Immutable recovery accepts them only after rebuilding identical bytes." >&2
@@ -247,7 +251,9 @@ jobs:
247251
248252
- name: Prepare and verify signed Android APK
249253
env:
254+
GIT_COMMIT: ${{ inputs.release_target_sha }}
250255
GH_TOKEN: ${{ github.token }}
256+
OPENCLAW_BUILD_TIMESTAMP: ${{ steps.release_approval.outputs.build_timestamp }}
251257
RELEASE_TAG: ${{ inputs.tag }}
252258
run: |
253259
set -euo pipefail

.github/workflows/docker-release.yml

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,36 @@ jobs:
8787
fi
8888
echo "Docker Hub publishing configured for ${DOCKERHUB_IMAGE}."
8989
90+
resolve_build_provenance:
91+
needs: [approve_manual_backfill, validate_publish_config]
92+
if: ${{ always() && needs.validate_publish_config.result == 'success' && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
93+
runs-on: ubuntu-24.04
94+
permissions:
95+
contents: read
96+
outputs:
97+
built_at: ${{ steps.build_provenance.outputs.built_at }}
98+
source_sha: ${{ steps.build_provenance.outputs.source_sha }}
99+
steps:
100+
- name: Checkout selected source
101+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
102+
with:
103+
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.sha }}
104+
fetch-depth: 0
105+
106+
- name: Resolve shared build provenance
107+
id: build_provenance
108+
shell: bash
109+
run: |
110+
set -euo pipefail
111+
echo "source_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
112+
echo "built_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_OUTPUT"
113+
90114
# KEEP THIS WORKFLOW ON GITHUB-HOSTED RUNNERS.
91115
# DO NOT MOVE IT BACK TO BLACKSMITH WITHOUT RE-VALIDATING TAG BUILDS AND BACKFILLS.
92116
# Build amd64 image. Default and slim tags point to the same slim runtime.
93117
build-amd64:
94-
needs: [approve_manual_backfill, validate_publish_config]
95-
if: ${{ always() && needs.validate_publish_config.result == 'success' && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
118+
needs: [approve_manual_backfill, validate_publish_config, resolve_build_provenance]
119+
if: ${{ always() && needs.validate_publish_config.result == 'success' && needs.resolve_build_provenance.result == 'success' && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
96120
# WARNING: DO NOT REVERT THIS TO A BLACKSMITH RUNNER WITHOUT RE-VALIDATING TAG BACKFILLS.
97121
runs-on: ubuntu-24.04
98122
permissions:
@@ -105,7 +129,7 @@ jobs:
105129
- name: Checkout
106130
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
107131
with:
108-
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
132+
ref: ${{ needs.resolve_build_provenance.outputs.source_sha }}
109133
fetch-depth: 0
110134

111135
- &buildkit_prepull_step
@@ -189,18 +213,20 @@ jobs:
189213
id: labels
190214
shell: bash
191215
env:
216+
BUILD_TIMESTAMP: ${{ needs.resolve_build_provenance.outputs.built_at }}
217+
SOURCE_SHA: ${{ needs.resolve_build_provenance.outputs.source_sha }}
192218
SOURCE_REF: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
193219
run: |
194220
set -euo pipefail
195-
source_sha="$(git rev-parse HEAD)"
221+
source_sha="${SOURCE_SHA}"
196222
version="${source_sha}"
197223
if [[ "${SOURCE_REF}" == "refs/heads/main" ]]; then
198224
version="main"
199225
fi
200226
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
201227
version="${SOURCE_REF#refs/tags/v}"
202228
fi
203-
created="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
229+
created="${BUILD_TIMESTAMP}"
204230
{
205231
echo "value<<EOF"
206232
echo "org.opencontainers.image.revision=${source_sha}"
@@ -219,6 +245,8 @@ jobs:
219245
cache-from: type=gha,scope=docker-release-amd64
220246
cache-to: type=gha,mode=max,scope=docker-release-amd64
221247
build-args: |
248+
GIT_COMMIT=${{ needs.resolve_build_provenance.outputs.source_sha }}
249+
OPENCLAW_BUILD_TIMESTAMP=${{ needs.resolve_build_provenance.outputs.built_at }}
222250
OPENCLAW_EXTENSIONS=diagnostics-otel,codex
223251
tags: ${{ steps.tags.outputs.value }}
224252
labels: ${{ steps.labels.outputs.value }}
@@ -239,6 +267,8 @@ jobs:
239267
type=gha,scope=docker-release-browser-amd64
240268
cache-to: type=gha,mode=max,scope=docker-release-browser-amd64
241269
build-args: |
270+
GIT_COMMIT=${{ needs.resolve_build_provenance.outputs.source_sha }}
271+
OPENCLAW_BUILD_TIMESTAMP=${{ needs.resolve_build_provenance.outputs.built_at }}
242272
OPENCLAW_EXTENSIONS=diagnostics-otel,codex
243273
OPENCLAW_INSTALL_BROWSER=1
244274
tags: ${{ steps.tags.outputs.browser }}
@@ -313,8 +343,8 @@ jobs:
313343
314344
# Build arm64 image. Default and slim tags point to the same slim runtime.
315345
build-arm64:
316-
needs: [approve_manual_backfill, validate_publish_config]
317-
if: ${{ always() && needs.validate_publish_config.result == 'success' && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
346+
needs: [approve_manual_backfill, validate_publish_config, resolve_build_provenance]
347+
if: ${{ always() && needs.validate_publish_config.result == 'success' && needs.resolve_build_provenance.result == 'success' && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
318348
# WARNING: DO NOT REVERT THIS TO A BLACKSMITH RUNNER WITHOUT RE-VALIDATING TAG BACKFILLS.
319349
runs-on: ubuntu-24.04-arm
320350
permissions:
@@ -327,7 +357,7 @@ jobs:
327357
- name: Checkout
328358
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
329359
with:
330-
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
360+
ref: ${{ needs.resolve_build_provenance.outputs.source_sha }}
331361
fetch-depth: 0
332362

333363
- *buildkit_prepull_step
@@ -392,18 +422,20 @@ jobs:
392422
id: labels
393423
shell: bash
394424
env:
425+
BUILD_TIMESTAMP: ${{ needs.resolve_build_provenance.outputs.built_at }}
426+
SOURCE_SHA: ${{ needs.resolve_build_provenance.outputs.source_sha }}
395427
SOURCE_REF: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
396428
run: |
397429
set -euo pipefail
398-
source_sha="$(git rev-parse HEAD)"
430+
source_sha="${SOURCE_SHA}"
399431
version="${source_sha}"
400432
if [[ "${SOURCE_REF}" == "refs/heads/main" ]]; then
401433
version="main"
402434
fi
403435
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
404436
version="${SOURCE_REF#refs/tags/v}"
405437
fi
406-
created="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
438+
created="${BUILD_TIMESTAMP}"
407439
{
408440
echo "value<<EOF"
409441
echo "org.opencontainers.image.revision=${source_sha}"
@@ -422,6 +454,8 @@ jobs:
422454
cache-from: type=gha,scope=docker-release-arm64
423455
cache-to: type=gha,mode=max,scope=docker-release-arm64
424456
build-args: |
457+
GIT_COMMIT=${{ needs.resolve_build_provenance.outputs.source_sha }}
458+
OPENCLAW_BUILD_TIMESTAMP=${{ needs.resolve_build_provenance.outputs.built_at }}
425459
OPENCLAW_EXTENSIONS=diagnostics-otel,codex
426460
tags: ${{ steps.tags.outputs.value }}
427461
labels: ${{ steps.labels.outputs.value }}
@@ -442,6 +476,8 @@ jobs:
442476
type=gha,scope=docker-release-browser-arm64
443477
cache-to: type=gha,mode=max,scope=docker-release-browser-arm64
444478
build-args: |
479+
GIT_COMMIT=${{ needs.resolve_build_provenance.outputs.source_sha }}
480+
OPENCLAW_BUILD_TIMESTAMP=${{ needs.resolve_build_provenance.outputs.built_at }}
445481
OPENCLAW_EXTENSIONS=diagnostics-otel,codex
446482
OPENCLAW_INSTALL_BROWSER=1
447483
tags: ${{ steps.tags.outputs.browser }}
@@ -516,7 +552,7 @@ jobs:
516552
517553
# Create multi-platform manifests
518554
create-manifest:
519-
needs: [approve_manual_backfill, validate_publish_config, build-amd64, build-arm64]
555+
needs: [approve_manual_backfill, validate_publish_config, resolve_build_provenance, build-amd64, build-arm64]
520556
if: ${{ always() && needs.validate_publish_config.result == 'success' && needs.build-amd64.result == 'success' && needs.build-arm64.result == 'success' && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
521557
# WARNING: DO NOT REVERT THIS TO A BLACKSMITH RUNNER WITHOUT RE-VALIDATING TAG BACKFILLS.
522558
runs-on: ubuntu-24.04
@@ -527,7 +563,7 @@ jobs:
527563
- name: Checkout
528564
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
529565
with:
530-
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
566+
ref: ${{ needs.resolve_build_provenance.outputs.source_sha }}
531567
fetch-depth: 0
532568

533569
- name: Login to GitHub Container Registry
@@ -654,7 +690,7 @@ jobs:
654690
fi
655691
656692
verify-attestations:
657-
needs: [create-manifest]
693+
needs: [resolve_build_provenance, create-manifest]
658694
if: ${{ always() && needs.create-manifest.result == 'success' }}
659695
runs-on: ubuntu-24.04
660696
permissions:
@@ -664,6 +700,7 @@ jobs:
664700
- name: Checkout
665701
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
666702
with:
703+
ref: ${{ needs.resolve_build_provenance.outputs.source_sha }}
667704
fetch-depth: 1
668705

669706
- *buildkit_prepull_step
@@ -704,9 +741,7 @@ jobs:
704741
dockerhub_arm64_refs=()
705742
browser_supported=0
706743
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
707-
tag="${SOURCE_REF#refs/tags/}"
708-
git fetch --depth=1 origin "refs/tags/${tag}:refs/tags/${tag}"
709-
if git show "${SOURCE_REF}:Dockerfile" | grep -q '^ARG OPENCLAW_INSTALL_BROWSER'; then
744+
if grep -q '^ARG OPENCLAW_INSTALL_BROWSER' Dockerfile; then
710745
browser_supported=1
711746
fi
712747
elif grep -q '^ARG OPENCLAW_INSTALL_BROWSER' Dockerfile; then

Dockerfile

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ RUN set -eux; \
102102
find /app/node_modules -name "matrix-sdk-crypto*.node" 2>/dev/null | grep -q . || \
103103
(echo "ERROR: matrix-sdk-crypto native addon missing after retries" >&2 && exit 1)
104104

105+
# Public source provenance supplied by release automation or local setup. Keep
106+
# these after the dependency layer so a new timestamp does not invalidate install.
107+
ARG GIT_COMMIT=""
108+
ARG OPENCLAW_BUILD_TIMESTAMP=""
109+
ENV GIT_COMMIT=${GIT_COMMIT} \
110+
OPENCLAW_BUILD_TIMESTAMP=${OPENCLAW_BUILD_TIMESTAMP}
111+
105112
COPY . .
106113

107114
# Normalize extension paths now so runtime COPY preserves safe modes
@@ -122,13 +129,18 @@ RUN pnpm_config_verify_deps_before_run=false pnpm canvas:a2ui:bundle || \
122129
echo "/* A2UI bundle unavailable in this build */" > extensions/canvas/src/host/a2ui/a2ui.bundle.js && \
123130
echo "stub" > extensions/canvas/src/host/a2ui/.bundle.hash && \
124131
rm -rf vendor/a2ui apps/shared/OpenClawKit/Tools/CanvasA2UI)
125-
RUN if printf '%s\n' "$OPENCLAW_EXTENSIONS" | tr ',' ' ' | tr ' ' '\n' | grep -qx 'qa-lab'; then \
126-
export OPENCLAW_BUILD_PRIVATE_QA=1 OPENCLAW_ENABLE_PRIVATE_QA_CLI=1; \
127-
fi && \
128-
OPENCLAW_RUN_NODE_SKIP_DTS_BUILD="$OPENCLAW_DOCKER_BUILD_SKIP_DTS" OPENCLAW_TSDOWN_MAX_OLD_SPACE_MB="$OPENCLAW_DOCKER_BUILD_TSDOWN_MAX_OLD_SPACE_MB" NODE_OPTIONS="$OPENCLAW_DOCKER_BUILD_NODE_OPTIONS" pnpm_config_verify_deps_before_run=false pnpm build:docker
129132
# Force pnpm for UI build (Bun may fail on ARM/Synology architectures)
130133
ENV OPENCLAW_PREFER_PNPM=1
131-
RUN pnpm_config_verify_deps_before_run=false pnpm ui:build
134+
RUN set -eu; \
135+
if [ -z "$OPENCLAW_BUILD_TIMESTAMP" ]; then \
136+
OPENCLAW_BUILD_TIMESTAMP="$(date -u +%Y-%m-%dT%H:%M:%SZ)"; \
137+
export OPENCLAW_BUILD_TIMESTAMP; \
138+
fi; \
139+
if printf '%s\n' "$OPENCLAW_EXTENSIONS" | tr ',' ' ' | tr ' ' '\n' | grep -qx 'qa-lab'; then \
140+
export OPENCLAW_BUILD_PRIVATE_QA=1 OPENCLAW_ENABLE_PRIVATE_QA_CLI=1; \
141+
fi; \
142+
OPENCLAW_RUN_NODE_SKIP_DTS_BUILD="$OPENCLAW_DOCKER_BUILD_SKIP_DTS" OPENCLAW_TSDOWN_MAX_OLD_SPACE_MB="$OPENCLAW_DOCKER_BUILD_TSDOWN_MAX_OLD_SPACE_MB" NODE_OPTIONS="$OPENCLAW_DOCKER_BUILD_NODE_OPTIONS" pnpm_config_verify_deps_before_run=false pnpm build:docker; \
143+
pnpm_config_verify_deps_before_run=false pnpm ui:build
132144
RUN if printf '%s\n' "$OPENCLAW_EXTENSIONS" | tr ',' ' ' | tr ' ' '\n' | grep -qx 'qa-lab'; then \
133145
pnpm_config_verify_deps_before_run=false pnpm qa:lab:build && \
134146
mkdir -p dist/extensions/qa-lab/web && \

0 commit comments

Comments
 (0)