Skip to content

Commit 243e6dd

Browse files
authored
Preserve the Brew Bubbles 2.2.3 PlatformIO build (#66)
* Preserve Brew Bubbles 2.2.3 release artifacts * Add reproducible offline PlatformIO build * Add CI for preserved PlatformIO build * Update preservation CI actions
1 parent b5ab998 commit 243e6dd

14 files changed

Lines changed: 613 additions & 0 deletions
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: Preserve PlatformIO 2.2.3
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches:
7+
- preserve-platformio-build
8+
paths:
9+
- ".github/workflows/preserve-platformio-2.2.3.yml"
10+
- "preserved/2.2.3/**"
11+
pull_request:
12+
paths:
13+
- ".github/workflows/preserve-platformio-2.2.3.yml"
14+
- "preserved/2.2.3/**"
15+
16+
permissions:
17+
contents: read
18+
19+
jobs:
20+
offline-reconstruction:
21+
runs-on: ubuntu-24.04
22+
timeout-minutes: 30
23+
24+
steps:
25+
- name: Check out complete repository history
26+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
27+
with:
28+
fetch-depth: 0
29+
30+
- name: Download preserved external assets
31+
env:
32+
GH_TOKEN: ${{ github.token }}
33+
run: |
34+
mkdir external-assets
35+
gh release download 2.2.3-build-preservation \
36+
--repo "$GITHUB_REPOSITORY" \
37+
--pattern "*.tar.gz" \
38+
--dir external-assets
39+
40+
- name: Run network-disabled reconstruction
41+
run: |
42+
preserved/2.2.3/build/build-offline.sh \
43+
external-assets \
44+
"$RUNNER_TEMP/reconstructed-2.2.3"
45+
46+
- name: Upload reconstructed outputs
47+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
48+
with:
49+
name: brew-bubbles-2.2.3-reconstructed
50+
path: ${{ runner.temp }}/reconstructed-2.2.3/
51+
if-no-files-found: error
52+
retention-days: 14

preserved/2.2.3/SHA256SUMS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
08becff15e539e207205b779a1c0fc8bd6320683762fca8a003e6f8610365709 firmware.bin
2+
529498dc4eae9c24c537891ac019b685dcbfd85e854316547b88796b11bffdda littlefs.bin
3+
13203bec47ca42896b11aa65ad525eae75f43c2e24252b2b7c7978ac67d676b8 source-2.2.3.tar.gz
4+
0090bb367361e15553181e792e4b674a1848791f6bb2538687a7b825ce1888ae flash-procedure.md
5+
388b0d5f93b1c14366ba323a758333a0a07bdf6938eeb54a702704ad6e9b0298 build-manifest.txt

preserved/2.2.3/build-manifest.txt

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
Brew Bubbles preservation manifest
2+
==================================
3+
4+
Release: 2.2.3
5+
Release URL: https://github.com/lbussy/brew-bubbles/releases/tag/2.2.3
6+
Release source commit:
7+
e6ef7c2dbbb77c74b7d83dc42bed159a5f17eecf
8+
9+
Release source commit metadata:
10+
commit=e6ef7c2dbbb77c74b7d83dc42bed159a5f17eecf
11+
author_date=2021-02-21T09:58:17-06:00
12+
commit_date=2021-02-21T09:58:17-06:00
13+
subject=Fix NTP with lwIP 1.4
14+
15+
Hardware target: Wemos D1 Mini / ESP8266
16+
Flash capacity: 4 MB / 32 Mbit
17+
Firmware address: 0x000000
18+
LittleFS address: 0x300000
19+
Upload speed: 460800
20+
Serial monitor speed: 74880
21+
22+
Archived artifact checksums:
23+
08becff15e539e207205b779a1c0fc8bd6320683762fca8a003e6f8610365709 firmware.bin
24+
529498dc4eae9c24c537891ac019b685dcbfd85e854316547b88796b11bffdda littlefs.bin
25+
13203bec47ca42896b11aa65ad525eae75f43c2e24252b2b7c7978ac67d676b8 source-2.2.3.tar.gz
26+
27+
Repository PlatformIO configuration at release:
28+
; PlatformIO Project Configuration File
29+
;
30+
; Build options: build flags, source filter
31+
; Upload options: custom upload port, speed and extra flags
32+
; Library options: dependencies, extra library storages
33+
; Advanced options: extra scripting
34+
;
35+
; Please visit documentation for the other options and examples
36+
; https://docs.platformio.org/page/projectconf.html
37+
38+
[common_env_data]
39+
upload_speed = 460800 ; 921600 // MacBook can't handle the heat!
40+
monitor_speed = 74880
41+
monitor_filters =
42+
; esp8266_exception_decoder
43+
; log2file
44+
framework = arduino
45+
platform = espressif8266
46+
build_unflags =
47+
build_flags =
48+
!python tools/git_rev.py
49+
-D PIO_SRC_TAG=2.2.3Beta
50+
-D BAUD=${common_env_data.monitor_speed}
51+
; -D DEBUG_ESP_PORT=Serial
52+
; -D DEBUG_ESP_WIFI
53+
; -D DEBUG_ESP_HTTP_UPDATE
54+
; -D DEBUG_ESP_HTTP_CLIENT
55+
; -D DEBUG_ESP_UPDATE
56+
; -D DEBUG_ESP_OTA
57+
; -D DEBUG_ESP_OOM
58+
; -include "umm_malloc/umm_malloc_cfg.h"
59+
; -D DEBUG_ESP_CORE
60+
; -D PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY ; v2 Lower Memory (default)
61+
; -D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH ; v2 Higher Bandwidth
62+
; -D PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH ; v2 Lower Memory (no features)
63+
; -D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH ; v2 Higher Bandwidth (no features)
64+
; -D PIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_LOW_MEMORY ; v2 IPv6 Lower Memory
65+
; -D PIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH ; v2 IPv6 Higher Bandwidth
66+
-D PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH ; v1.4 Higher Bandwidth (Needed because of stream errors getting Filesystem OTA)
67+
extra_scripts = ; pre:python tools\name_firmware.py
68+
lib_deps =
69+
ArduinoJson
70+
https://github.com/lbussy/OneWire.git
71+
https://github.com/lbussy/DS18B20.git
72+
https://github.com/lbussy/Arduino-Log.git
73+
https://github.com/lbussy/ESPAsyncTCP
74+
https://github.com/lbussy/ESPAsyncWebServer.git
75+
https://github.com/lbussy/AsyncWiFiManager.git
76+
https://github.com/lbussy/asyncHTTPrequest.git
77+
https://github.com/lbussy/CircularBuffer.git
78+
https://github.com/lbussy/LCBUrl.git
79+
https://github.com/lbussy/esptelnet.git
80+
khoih-prog/ESP_WiFiManager
81+
https://github.com/lbussy/ThingSpeak
82+
monitor_filters =
83+
; esp8266_exception_decoder
84+
; log2file
85+
build_type = release ; Cannot use debug with Wemos D1
86+
87+
[env:d1_mini]
88+
board_build.filesystem = littlefs
89+
upload_speed = ${common_env_data.upload_speed}
90+
monitor_speed = ${common_env_data.monitor_speed}
91+
framework = ${common_env_data.framework}
92+
platform = ${common_env_data.platform}
93+
build_unflags = ${common_env_data.build_unflags}
94+
build_flags =
95+
${common_env_data.build_flags}
96+
-D USE_LITTLEFS
97+
extra_scripts = ${common_env_data.extra_scripts}
98+
lib_deps = ${common_env_data.lib_deps}
99+
monitor_filters = ${common_env_data.monitor_filters}
100+
build_type = ${common_env_data.build_type}
101+
board = d1_mini

preserved/2.2.3/build/Dockerfile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
FROM python@sha256:18b8bae1ea34d6c9cef6f29833c9d0913cea3d5c6d98a1bd2db2037348473450
2+
3+
RUN apt-get update \
4+
&& apt-get install --yes --no-install-recommends \
5+
ca-certificates \
6+
git \
7+
&& rm -rf /var/lib/apt/lists/*
8+
9+
COPY requirements.txt /tmp/requirements.txt
10+
11+
RUN python -m pip install --no-cache-dir \
12+
pip==23.3.2 \
13+
setuptools==69.0.3 \
14+
wheel==0.42.0 \
15+
&& python -m pip install --no-cache-dir \
16+
--requirement /tmp/requirements.txt \
17+
&& rm /tmp/requirements.txt
18+
19+
RUN python --version \
20+
&& git --version \
21+
&& pio --version
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
9481635058deca814ed9283f3e284ea1345638d3f2e813517bb56e66e75414e4 brew-bubbles-pio-historical-5.1.0-linux-amd64.tar.gz
2+
8859a979dbec041094505f7bc62d2cbf0bebec3f01814cedb34d02218d79bce4 brew-bubbles-2.2.3-offline-cache-linux-amd64.tar.gz

preserved/2.2.3/build/README.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Brew Bubbles 2.2.3 Build Preservation
2+
3+
This directory preserves a controlled reconstruction of the Brew Bubbles 2.2.3
4+
PlatformIO build environment.
5+
6+
## Canonical release artifacts
7+
8+
The authoritative flash artifacts are stored one directory above:
9+
10+
- `firmware.bin`
11+
- `littlefs.bin`
12+
- `SHA256SUMS`
13+
- `flash-procedure.md`
14+
- `build-manifest.txt`
15+
- `source-2.2.3.tar.gz`
16+
17+
Always use those canonical binaries when restoring a device.
18+
19+
## Source provenance limitation
20+
21+
The released firmware identifies its source as:
22+
23+
- commit `6362a76`
24+
- branch `master`
25+
- version `2.2.3`
26+
27+
Commit `6362a76` is not present in the surviving repository history, tags,
28+
remote references, or recoverable local Git objects. An exact source rebuild of
29+
the released firmware is therefore not currently possible.
30+
31+
This reconstruction uses the closest surviving public pre-release source:
32+
33+
- commit `3beff558e54862332a419fd5431d5ed59dd25a05`
34+
- branch identity `devel`
35+
36+
Its firmware is deterministic but is not byte-identical to the canonical
37+
release firmware.
38+
39+
Expected reconstructed firmware SHA-256:
40+
41+
`cfd41b647268a70c71090f621a44ad50d968a7cfba6dc5370d9849f59bf85f01`
42+
43+
## Preserved environment
44+
45+
- Host container architecture: `linux/amd64`
46+
- Python: 3.8.18
47+
- PlatformIO Core: 5.1.0
48+
- Espressif8266 platform: 2.6.3
49+
- Arduino ESP8266 core: 2.7.4
50+
- Xtensa GCC: 4.8.2
51+
- ArduinoJson: 6.17.3
52+
53+
All Git-based libraries are pinned to full commit IDs in `platformio.ini`.
54+
55+
## External assets
56+
57+
The complete environment requires two release assets:
58+
59+
- `brew-bubbles-pio-historical-5.1.0-linux-amd64.tar.gz`
60+
- `brew-bubbles-2.2.3-offline-cache-linux-amd64.tar.gz`
61+
62+
Their hashes are recorded in `EXTERNAL-ASSETS.sha256`.
63+
They are published in the
64+
[2.2.3 build-preservation release](https://github.com/lbussy/brew-bubbles/releases/tag/2.2.3-build-preservation).
65+
66+
The container archive preserves Python, Git, PlatformIO Core, and the Debian
67+
userspace. The offline-cache archive preserves the compiler, framework,
68+
PlatformIO platform, filesystem tools, SCons reconstruction, and all library
69+
checkouts.
70+
71+
## Offline reconstruction
72+
73+
Docker is required. Run from any location:
74+
75+
```sh
76+
preserved/2.2.3/build/build-offline.sh \
77+
/path/to/downloaded/release-assets \
78+
/path/to/output-directory
79+
```
80+
81+
The script:
82+
83+
1. verifies both external assets;
84+
2. loads the preserved container image when needed;
85+
3. checks out the historical reconstruction source;
86+
4. restores the complete offline package set;
87+
5. disables container networking;
88+
6. builds firmware and LittleFS;
89+
7. verifies the deterministic firmware checksum;
90+
8. unpacks LittleFS and compares every contained file with the canonical image.
91+
92+
## LittleFS reproducibility
93+
94+
Repeated `mklittlefs` runs produce different container-image bytes even when
95+
all contained files are identical. Therefore, the generated `littlefs.bin`
96+
checksum is not used as the reconstruction invariant.
97+
98+
The build instead unpacks both images and compares the path and SHA-256 of every
99+
contained file. The canonical `littlefs.bin` remains the image to use for device
100+
restoration.
101+
102+
## Container reconstruction
103+
104+
`Dockerfile`, `requirements.txt`, and `container-manifest.txt` document how the
105+
container was assembled. The saved container archive is authoritative because
106+
future availability of the historical Debian and Python dependencies cannot be
107+
assumed.
108+
109+
## Continuous integration
110+
111+
The `Preserve PlatformIO 2.2.3` GitHub Actions workflow downloads the published
112+
archives, verifies them, and runs the reconstruction with container networking
113+
disabled. It requires complete Git history because the reconstruction checks
114+
out historical source commit `3beff558e54862332a419fd5431d5ed59dd25a05`.

0 commit comments

Comments
 (0)