2121# `docs/engineering/RELEASE_PLANE.md`.
2222#
2323# This workflow supersedes the stop-gap
24- # `evo-device-audio/.github/workflows/publish-core-binaries.yml`
25- # per ADR-0032 and ADR-0033.
24+ # `evo-device-audio/.github/workflows/publish-core-binaries.yml`:
25+ # evo-core publishes its own binaries from this workflow, signed
26+ # with the framework release signing key, so distributions no
27+ # longer cross-build the framework binaries on their own behalf.
2628
2729name : publish
2830
@@ -100,6 +102,7 @@ jobs:
100102 cross build --release --target ${{ matrix.target }} -p evo --bin evo
101103 cross build --release --target ${{ matrix.target }} -p evo-plugin-tool --bin evo-plugin-tool
102104 cross build --release --target ${{ matrix.target }} -p evo-example-echo --bin echo-wire
105+ cross build --release --target ${{ matrix.target }} -p evo-example-factory --bin factory-wire
103106
104107 - name : Host-build evo-plugin-tool (used to sign and pack bundles)
105108 run : |
@@ -143,6 +146,28 @@ jobs:
143146 sha256sum "$dst" | awk '{print $1}' > "$dst.sha256"
144147 done
145148
149+ # Reference systemd unit. Architecture-independent file
150+ # shipped alongside the binaries so operators / packaging
151+ # tooling can locate it from the same release directory the
152+ # binary came from. The framework does not install it; per
153+ # BOUNDARY.md packaging is distribution-owned. This is the
154+ # canonical baseline a distribution copies into its own
155+ # tree.
156+ DIST_DIR="$STAGE_DIR/dist/systemd"
157+ mkdir -p "$DIST_DIR"
158+ cp dist/systemd/evo.service.example "$DIST_DIR/evo.service.example"
159+ cp dist/systemd/README.md "$DIST_DIR/README.md"
160+ AUX_SERVICE_SHA=$(sha256sum "$DIST_DIR/evo.service.example" \
161+ | awk '{print $1}')
162+ AUX_README_SHA=$(sha256sum "$DIST_DIR/README.md" \
163+ | awk '{print $1}')
164+
165+ # The manifest carries each auxiliary file's path AND its
166+ # sha256 digest. The manifest's own signature
167+ # (`build-info.sig`) transitively covers the auxiliary
168+ # file integrity: a consumer that verifies the manifest
169+ # signature and then re-hashes each auxiliary path can
170+ # detect tampering without per-file signatures.
146171 {
147172 echo "schema_version = 0"
148173 echo "kind = \"core-binaries\""
@@ -151,6 +176,14 @@ jobs:
151176 echo "binaries = [\"evo\", \"evo-plugin-tool\"]"
152177 echo "built_at = \"$(date -u +%FT%TZ)\""
153178 echo "publisher = \"${PUBLISHER}\""
179+ echo
180+ echo "[[auxiliary]]"
181+ echo "path = \"dist/systemd/evo.service.example\""
182+ echo "sha256 = \"${AUX_SERVICE_SHA}\""
183+ echo
184+ echo "[[auxiliary]]"
185+ echo "path = \"dist/systemd/README.md\""
186+ echo "sha256 = \"${AUX_README_SHA}\""
154187 } > "$STAGE_DIR/build-info.toml"
155188
156189 openssl pkeyutl -sign \
@@ -165,7 +198,7 @@ jobs:
165198 TARGET : ${{ matrix.target }}
166199 run : |
167200 set -e
168- # Production-shaped OOP plugin bundle reference (ADR-0033 D25) .
201+ # Production-shaped OOP plugin bundle reference.
169202 # Per-arch bundle directory: manifest.toml + plugin.bin + manifest.sig
170203 # then packed as <name>-<version>-<target>.tar.gz.
171204 STAGE=/tmp/stage
@@ -188,6 +221,37 @@ jobs:
188221
189222 ls -la "${BUNDLE_OUT_DIR}"
190223
224+ - name : Stage, sign, and pack the factory OOP bundle for ${{ matrix.target }}
225+ env :
226+ TARGET : ${{ matrix.target }}
227+ run : |
228+ set -e
229+ # Reference factory plugin bundle. Mirrors the echo-bundle
230+ # stanza above; bundle layout is identical
231+ # (manifest.toml + plugin.bin + manifest.sig packed as
232+ # <name>-<version>-<target>.tar.gz). Acceptance tests
233+ # admit this bundle to validate the factory-instance
234+ # codepath end-to-end on real hardware.
235+ STAGE=/tmp/stage
236+ BUNDLE_NAME="org.evo.example.factory"
237+ BUNDLE_VERSION="0.1.0"
238+ BUNDLE_DIR_NAME="${BUNDLE_NAME}-${BUNDLE_VERSION}-${TARGET}"
239+ BUNDLE_DIR="${STAGE}/bundles-work/${BUNDLE_DIR_NAME}"
240+ mkdir -p "${BUNDLE_DIR}"
241+
242+ cp crates/evo-example-factory/manifest.oop.toml "${BUNDLE_DIR}/manifest.toml"
243+ cp "target/${TARGET}/release/factory-wire" "${BUNDLE_DIR}/plugin.bin"
244+ chmod 755 "${BUNDLE_DIR}/plugin.bin"
245+
246+ /tmp/host-evo-plugin-tool sign "${BUNDLE_DIR}" --key /tmp/key.pem
247+
248+ BUNDLE_OUT_DIR="${STAGE}/bundles/${BUNDLE_NAME}/${TARGET}"
249+ mkdir -p "${BUNDLE_OUT_DIR}"
250+ /tmp/host-evo-plugin-tool pack "${BUNDLE_DIR}" \
251+ --out "${BUNDLE_OUT_DIR}/${BUNDLE_DIR_NAME}.tar.gz"
252+
253+ ls -la "${BUNDLE_OUT_DIR}"
254+
191255 - name : Wipe signing key from runner
192256 if : always()
193257 run : |
0 commit comments