Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
*.sh text eol=lf
*.repos text eol=lf
*.json text eol=lf
*.py text eol=lf
*.yml text eol=lf
/evidence/** -text
44 changes: 44 additions & 0 deletions .github/workflows/pinned-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Pinned rc.1 release

on:
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
pinned-release:
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: python -m pip install -r requirements-release.txt
- name: Regression and fault-injection tests
run: python -m unittest discover -s tests -v
- name: Fetch workspace release manifest from main
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: openAMRobot/openamrobot-manifest
ref: main
path: manifest-reference
persist-credentials: false
- name: Reject release manifest drift
run: python scripts/check_manifest_sync.py manifests/v2.0.0-rc.1.repos manifest-reference/releases/v2.0.0-rc.1.repos
- name: First independent fetch and build
run: python scripts/build_release.py --config release-config.rc1.json --input-dir input/first --output-dir dist/first --fetch
- name: Second independent fetch and build
run: python scripts/build_release.py --config release-config.rc1.json --input-dir input/second --output-dir dist/second --fetch
- name: Verify integrity and reproducibility
run: |
python scripts/validate_release.py dist/first/OpenAMRobot-v2.0.0-rc.1-source.zip
python scripts/validate_release.py dist/second/OpenAMRobot-v2.0.0-rc.1-source.zip
cmp dist/first/OpenAMRobot-v2.0.0-rc.1-source.zip dist/second/OpenAMRobot-v2.0.0-rc.1-source.zip
(cd dist/first && sha256sum -c OpenAMRobot-v2.0.0-rc.1-source.zip.sha256)
- uses: actions/upload-artifact@v4
with:
name: OpenAMRobot-v2.0.0-rc.1-candidate
path: dist/first/
152 changes: 152 additions & 0 deletions RC1_EVIDENCE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# OA-05 verification

Candidate snapshot date: 2026-10-19.
Base: `b9f4a9d2a1845ab50769693240a3050cf0f6d171`.
The PR head is recorded in the PR description after committing.

## Regression and fault injection

`python -m unittest discover -s tests -v`: **16 tests, 0 failures** on
Windows with Python 3.14 and Git 2.55.0.windows.5. Tests cover exact SHA fetch
arguments, fetched commit mismatch, submodule rejection, mutable refs,
duplicate keys, changed manifest bytes, changed cache bytes, fetched archive
checksum mismatch, incorrect archive commit, missing checksum coverage,
tampered output, extra output members, unsafe paths, executable/link modes,
ZIP metadata normalization, reproducible output and CLI dispatch.
The legacy v0.0.1 build and validator pass using eight fixture source archives.
Fixture tests establish packaging behavior, not component build acceptance.

Before-change regression: ran `scripts/build_release.py` from base `b9f4a9d`
against `release-config.rc1.json` in a temporary output directory. It exits 1
with `KeyError: 'components'`. The updated entry point accepts the same config.

## Independent real-source builds

Executed separately, each fetching all 14 repositories into a new temporary
Git repository and using separate source caches:

```sh
python scripts/build_release.py --config release-config.rc1.json --input-dir input/first --output-dir dist/first --fetch
python scripts/build_release.py --config release-config.rc1.json --input-dir input/second --output-dir dist/second --fetch
python scripts/validate_release.py dist/first/OpenAMRobot-v2.0.0-rc.1-source.zip
```

Both builds exit 0, each verifies **1,841 files**, and byte comparison using
Python `filecmp.cmp(..., shallow=False)` passes. The bundle is 231,082,934 bytes.

SHA-256 for both bundles:

```text
2f87bf21a99add7fb3aa37b2965943c4ac6fa390054476b5ea5293f6500fed41
```

The SHA inventory and commit provenance are inside each bundle; the external
`.zip.sha256` accompanies it. Generated ZIPs and source caches are not committed.
The new hosted workflow repeats two independent fetches/builds on Ubuntu 24.04
and uploads the validated candidate, without publishing a GitHub Release.

## Linux packaging check

Ran the following with the repository mounted at `/work` in the local
`ros:jazzy-ros-base` image (image ID
`sha256:c3706ef0a0aa45413c07803cf433602f543b22e45b4855f6fca955c2d8ecc4e8`):

```sh
python3 -m unittest discover -s tests -v
python3 scripts/build_release.py --config release-config.rc1.json --input-dir input/rc1 --output-dir dist/linux
python3 scripts/validate_release.py dist/linux/OpenAMRobot-v2.0.0-rc.1-source.zip
```

**16 tests, 0 failures**; build and validation exit 0. The Linux build uses
the verified source cache and verifies 1,841 files. Its bundle has the same
SHA-256 shown above as both independently fetched Windows builds. This proves
cross-platform packaging for this candidate; it is not a Linux source fetch
or ROS package compilation check.

## Not verified

Full Ubuntu/Jazzy workspace compilation, third-party build-time dependency
pinning, firmware builds, drivers on physical hardware and rc.1 acceptance
are outside this source-packaging verification. No hardware or safety claim
is made. Hosted CI status is reported separately from local test results.

## Integration and provenance

PR #9's navigation-install work and PR #8's release-model documentation were
inspected. This change preserves the legacy builder path and keeps the rc.1
procedure in a separate document. No assertion is made about inaccessible work.
The release-local manifest will be aligned with OA-39 after review; it includes
13 workspace repositories plus the release-only governance source.

Prepared with OpenAI Codex: implementation, candidate lock, tests, workflow
and documentation. No safety logic or third-party source was authored or
modified. Third-party source and licence notices remain in their exports;
tooling dependency and upstream licences are described in RC1_RELEASE.md.

## Rebase validation, 2026-10-24

Rebased onto main `c39eda70d8cf2e4f98ae09a51afc3a0750350a11` after navigation gate PR #9
merged as `0c9442fff722ce56567ebc106dc6ca38afcb9e3d` and release-model PR #8
merged. Pre-rebase head: `58ce4a24e6a1b9619332a59f44217fb1fd55c70b`.
The original source pins and source checksum lock are unchanged.

```sh
python -m unittest discover -s tests -v
python scripts/build_release.py --config release-config.rc1.json --input-dir input/rc1 --output-dir dist/rebase-20261024
python scripts/validate_release.py dist/rebase-20261024/OpenAMRobot-v2.0.0-rc.1-source.zip
```

**27 tests, zero failures**, including all 11 merged navigation gate/config/
provenance tests and 16 pinned-release tests. The real-source build from the
existing verified cache exits 0 and verifies 1,841 files. Its SHA-256 remains
`2f87bf21a99add7fb3aa37b2965943c4ac6fa390054476b5ea5293f6500fed41`.
No fresh network source fetch or physical/ROS package build is claimed by
this cached packaging run.

Conflict resolution retains main's evidence byte-preservation attributes,
archive ignores and release-model documentation. The merged navigation
manifest, navigation-only config, verifier scripts, workflow and compact
evidence are unchanged relative to main. Only rc.1 dispatch is added to the
archive-input builder; its navigation validation remains intact.

Fresh hosted check results on the new head are reported in PR #12. This rebase
is not a new rc.1 interfaces/package-version repin or final release selection.

## Fresh-fetch portability correction, 2026-10-24

The first rebased hosted run (40104847352) failed strictly on the interfaces
source checksum. The navigation gate on the same head passed (40104847340).
The cached build above did not exercise a fresh Linux export.

Investigation reproduced the cause: Windows `core.autocrlf=true` changed text
bytes during `git archive`. With the interfaces SHA unchanged, 59 exported
files differed only by CRLF versus LF. Git export now explicitly uses
`core.autocrlf=false` and `core.eol=lf`. The source lock was regenerated by
freshly fetching the same 14 exact SHAs; no version, component or repository
selection changed. Expected checksum checks remain strict.

Regression command:

```sh
python -m unittest discover -s tests -p test_pinned_release.py -k git_line_ending -v
```

Before the fix: 1 test fails because opposite host autocrlf defaults produce
different source hashes. After the fix: that test passes. The complete suite
then passes **28 tests, zero failures**, including all merged navigation tests.

Regenerated the reviewed candidate lock using a new output file:

```sh
python scripts/lock_release_sources.py --manifest manifests/v2.0.0-rc.1.repos --output release-config.rc1.lf.json --cache-dir input/rc1 --version 2.0.0-rc.1
```

Confirmed all config fields except the 14 source checksums are unchanged, then
replaced the old candidate lock. The rebuilt real-source bundle verifies
1,841 files and has SHA-256:

`2c494b1d090a3c525379d32585f483d9c685d606943657c1b64991190c11d227`.

This supersedes the earlier Windows-derived **candidate** bundle checksum;
no published release is changed. Fresh Linux two-fetch reproducibility and
navigation checks are rerun on the final head, with results linked in PR #12.
76 changes: 76 additions & 0 deletions RC1_RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Build the rc.1 candidate

`release-config.rc1.json` locks a release-local snapshot in
`manifests/v2.0.0-rc.1.repos`. Every repository uses a full commit SHA.
The snapshot includes the 13 workspace repositories and a separately pinned
`governance/.github` export, preserving the legacy release's governance input.
The configuration locks both the manifest bytes and each source archive with
SHA-256. The candidate is dated 2026-10-19; final component acceptance is pending.

## Build and verify

Requires Python 3.10 or newer, Git and network access to the pinned repositories:

```sh
python -m pip install -r requirements-release.txt
python -m unittest discover -s tests -v
python scripts/build_release.py --config release-config.rc1.json --input-dir input/first --output-dir dist/first --fetch
python scripts/build_release.py --config release-config.rc1.json --input-dir input/second --output-dir dist/second --fetch
python scripts/validate_release.py dist/first/OpenAMRobot-v2.0.0-rc.1-source.zip
python scripts/validate_release.py dist/second/OpenAMRobot-v2.0.0-rc.1-source.zip
cmp dist/first/OpenAMRobot-v2.0.0-rc.1-source.zip dist/second/OpenAMRobot-v2.0.0-rc.1-source.zip
(cd dist/first && sha256sum -c OpenAMRobot-v2.0.0-rc.1-source.zip.sha256)
```

On PowerShell, compare the two files using `Get-FileHash` instead of `cmp`.
`--fetch` uses `git fetch --depth=1 URL FULL_SHA`, verifies the fetched commit,
and exports it using `git archive`. No moving branch or main archive is used.
Omit `--fetch` to rebuild offline from the already verified source cache.
Missing cache entries or any checksum mismatch fail the build.

Source ZIPs are normalized before hashing: fixed date, sorted files, stored
compression, normalized executable/link modes and the exact commit as ZIP
comment. Git export explicitly sets `core.autocrlf=false` and `core.eol=lf`
so host line-ending defaults cannot change source bytes; repository attributes
still apply. The final ZIP uses the same fixed metadata, retains symlinks as links,
and contains no wall-clock build timestamp or machine-specific paths.
Submodules fail explicitly until represented by separate pinned entries.

## Outputs

- `OpenAMRobot-v2.0.0-rc.1-source.zip` and its external `.sha256` file.
- Inside the ZIP: checkout paths from the release manifest, `release.repos`,
`MANIFEST.json` with repository URLs, SHAs and source hashes, and
`checksums.sha256` covering every other file.

The rc.1 layout follows workspace paths rather than the numbered v0.0.1 layout.
The legacy configuration and its metadata retain their original behavior.
Validation checks every inventory entry and rejects extra or duplicate members
without extracting source symlinks. Checksums detect corruption; they are not
a cryptographic signature or proof of release approval.

## Refresh a candidate intentionally

Review the component SHAs first, then create a new manifest and a new lock:

```sh
python scripts/lock_release_sources.py --manifest manifests/next-candidate.repos --output release-config.next.json --cache-dir input/next --version 2.0.0-rc.1
```

Review both files in the same PR. The lock command refuses to overwrite an
existing configuration. Updating a checksum is an explicit source-selection
change, never an automatic fallback after a build failure.

## Dependencies and limitations

The tooling adds PyYAML 6.0.3 (MIT), from https://github.com/yaml/pyyaml.
The source snapshot includes upstream SLAMTEC sllidar_ros2 (package declares
BSD; see its retained upstream licence) and micro-ROS-Agent (Apache-2.0 with
upstream third-party notices). All original repository files and notices are
preserved by Git export; no upstream source is vendored into this builder repo.

This validates source packaging only. Ubuntu/Jazzy package builds, driver
operation, hardware tests, compiled binary reproducibility and upstream
build-time dependency downloads are outside OA-05 verification. Final rc.1
selection still depends on the other audit findings. No release is published
by the pull-request workflow; it uploads a candidate artifact for review.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
> For the SHA-pinned **v2.0.0-rc.1 candidate builder**, see [RC1_RELEASE.md](RC1_RELEASE.md).

# OpenAMRobot v0.0.1

For the pending navigation release-install gate, see
Expand Down
2 changes: 2 additions & 0 deletions RELEASE_PROCESS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
> For the SHA-pinned rc.1 candidate build procedure, see [RC1_RELEASE.md](RC1_RELEASE.md).

# OpenAMRobot Release Process

For navigation package pinning, clean install evidence, and candidate manifest
Expand Down
40 changes: 40 additions & 0 deletions STATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Release builder state

OA-05 adds a candidate v2.0.0-rc.1 source bundle from exact Git SHAs and a
reviewed SHA-256 source lock. The 2026-10-19 snapshot is for reproducibility
validation; it is not the final release selection or acceptance evidence.

The v0.0.1 archive-input path remains available. The rc.1 path uses the same
build and validation entry points and preserves workspace checkout paths.
Source archive checksums use canonical, uncompressed ZIPs produced from verified
Git commits. Output ZIP metadata and ordering are deterministic.

Integrated main at `c39eda7` on 2026-10-24 after PR #9 merged navigation
installation validation and PR #8 merged the release model. The existing
navigation gate, test configuration, source provenance and compact evidence
remain intact. The archive-input builder still rejects navigation evidence,
archive, pin, package-version and contract mismatches.

The original candidate source pins are unchanged by the rebase. Repinning to
the accepted interfaces contract/package version and final rc.1 component
selection remain separate release work. The release-local snapshot still
requires owner alignment with the workspace release manifest.

Fresh Linux CI exposed host-dependent Git archive line endings in the old
Windows-generated source lock. Export now fixes autocrlf/eol settings; the
source lock is regenerated from the same SHAs. A regression test checks that
opposite host autocrlf defaults produce the same source hash. Checksum
enforcement remains strict; the earlier cached-bundle hash is historical.

No safety implementation is changed. Source bundling does not validate package
builds, firmware, robot operation, physical safety or release readiness.
Upstream build-time downloads are not locked by this source bundle.

Prepared 2026-10-28: pinned-release CI now compares the complete repository
mapping with openamrobot-manifest main's releases/v2.0.0-rc.1.repos. Only
governance/.github is exempt; missing files, missing entries and changed URLs
or SHAs fail. The 19 October source pins and checksums are unchanged.
This gate requires manifest PRs #17 and #18 to land: #17 alone lacks the two
driver sources. Locally the #18 snapshot matches all 13 workspace entries;
the #17 snapshot correctly fails for both missing drivers. Hosted validation
of this new gate is pending publication and those upstream merges.
58 changes: 58 additions & 0 deletions manifests/v2.0.0-rc.1.repos
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Candidate snapshot: 2026-10-19. Not release acceptance.
repositories:
src/openamrobot-interfaces:
type: git
url: https://github.com/openAMRobot/openamrobot-interfaces.git
version: 87ab8a936c97ab55ee74b8988ca3d7659160ea6a
src/openamrobot-comm:
type: git
url: https://github.com/openAMRobot/openamrobot-comm.git
version: 1c552921cf05001ee8f43e899aa2f92882766f07
src/openamrobot-manipulation:
type: git
url: https://github.com/openAMRobot/openamrobot-manipulation.git
version: 095e6c7bbd270db6d21de9664a654bb37919a2eb
src/openamr-platform-sw:
type: git
url: https://github.com/openAMRobot/openamr-platform-sw.git
version: 8a7a5b136bfb3f144b57991455b378f6b3f4113c
src/openamr-upperbody-sw:
type: git
url: https://github.com/openAMRobot/openamr-upperbody-sw.git
version: f57e54cfc9e7f9536e94c52749502cc983fb908e
firmware/openamr-platform-fw:
type: git
url: https://github.com/openAMRobot/openamr-platform-fw.git
version: f96014daae614da4e1bf0c00376f1d9e5d41ae02
firmware/openamr-upperbody-fw:
type: git
url: https://github.com/openAMRobot/openamr-upperbody-fw.git
version: ba1a53f2a031cdbfbe4fa0f5f4d32ed7cdf4dbbb
hardware/openamr-platform-hw:
type: git
url: https://github.com/openAMRobot/openamr-platform-hw.git
version: 6c32fbabfd08491e74a9a2f601f1e14d07d44938
hardware/openamr-upperbody-hw:
type: git
url: https://github.com/openAMRobot/openamr-upperbody-hw.git
version: 6349ff2672c9e812655d3ae1d04c67130fb3cac7
ui/openamrobot-ui:
type: git
url: https://github.com/openAMRobot/openamrobot-ui.git
version: c5558ad5babdab30702c307a08fc94a6408c798c
docs/openamrobot-docs:
type: git
url: https://github.com/openAMRobot/openamrobot-docs.git
version: 95c6140e16866964a7d6fddd37e06cd382b7afae
src/sllidar_ros2:
type: git
url: https://github.com/Slamtec/sllidar_ros2.git
version: 34300099fadfc772965962dec837bf436706188f
src/micro_ros_agent:
type: git
url: https://github.com/micro-ROS/micro-ROS-Agent.git
version: 7c932329ad5591ef23942ef1962534258c16b000
governance/.github:
type: git
url: https://github.com/openAMRobot/.github.git
version: 9109d3e1a8fc07151e500e83b32b7ce6ccab6af6
Loading
Loading