chore: release v0.6.2-beta #9
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and Release | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| workflow_dispatch: | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| strategy: | |
| matrix: | |
| env: [wt32-sc01-plus] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Cache PlatformIO | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cache/pip | |
| ~/.platformio/.cache | |
| key: ${{ runner.os }}-pio-${{ hashFiles('**/platformio.ini') }} | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Install PlatformIO | |
| run: pip install --upgrade platformio | |
| - name: Build ${{ matrix.env }} | |
| run: pio run -e ${{ matrix.env }} | |
| - name: Read version from app_config.h | |
| id: version | |
| run: | | |
| # FW_VERSION moved out of main.cpp into app_config.h during the | |
| # refactor. The old grep silently returned an empty string, which | |
| # would have produced a release named "SpoolmanScale " with an empty | |
| # version in manifest.json instead of failing. | |
| VERSION=$(grep '#define FW_VERSION' src/app_config.h | sed 's/.*"\(.*\)"/\1/') | |
| if [ -z "$VERSION" ]; then | |
| echo "::error::FW_VERSION not found in src/app_config.h" | |
| exit 1 | |
| fi | |
| # Only on a tag push. A manual workflow_dispatch run has a branch | |
| # name in GITHUB_REF_NAME and must not be held to this. | |
| if [ "$GITHUB_REF_TYPE" = "tag" ] && [ "$VERSION" != "$GITHUB_REF_NAME" ]; then | |
| echo "::error::Tag $GITHUB_REF_NAME does not match FW_VERSION $VERSION" | |
| exit 1 | |
| fi | |
| echo "Building $VERSION" | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| - name: Refuse a tag that is not newer than what is published | |
| if: github.ref_type == 'tag' | |
| run: | | |
| # The check above only compares the tag against FW_VERSION, so two | |
| # matching but too low numbers pass it. Since the firmware now | |
| # compares itself against version.json, a tag ranking below the | |
| # published one would put a red dot on every device and offer them a | |
| # downgrade. The ranking must stay identical to | |
| # src/services/version_compare.cpp. | |
| python3 - "${{ steps.version.outputs.version }}" <<'PY' | |
| import json, re, sys | |
| def rank(v): | |
| if not v: | |
| return -1 | |
| m = re.search(r"(\d+)\.(\d+)\.(\d+)", v) | |
| if not m: | |
| return -1 | |
| major, minor, patch = (int(g) for g in m.groups()) | |
| beta = 999 # no "beta" in the tag: final release | |
| b = v.find("beta") | |
| if b != -1: | |
| beta = 0 # "-beta": the public release | |
| m2 = re.match(r"\.(\d+)", v[b + 4:]) | |
| if m2: | |
| beta = int(m2.group(1)) | |
| return major * 10**9 + minor * 10**6 + patch * 10**3 + beta | |
| tag = sys.argv[1] | |
| try: | |
| with open("version.json") as f: | |
| data = json.load(f) | |
| except FileNotFoundError: | |
| print("no version.json yet, nothing to compare against") | |
| sys.exit(0) | |
| published = max((data.get("stable") or "", data.get("prerelease") or ""), | |
| key=rank) | |
| if rank(tag) <= rank(published): | |
| print(f"::error::Tag {tag} does not rank above the published " | |
| f"{published}. Every device would be offered a downgrade.") | |
| sys.exit(1) | |
| print(f"{tag} ranks above {published}, ok") | |
| PY | |
| - name: Prepare binaries | |
| run: | | |
| VERSION=${{ steps.version.outputs.version }} | |
| cp .pio/build/${{ matrix.env }}/bootloader.bin webflasher/bootloader.bin | |
| cp .pio/build/${{ matrix.env }}/partitions.bin webflasher/partitions.bin | |
| cp .pio/build/${{ matrix.env }}/firmware.bin webflasher/SpoolmanScale.bin | |
| cp .pio/build/${{ matrix.env }}/firmware.bin SpoolmanScale_${VERSION}.bin | |
| - name: Update manifest.json + index.html | |
| run: | | |
| VERSION=${{ steps.version.outputs.version }} | |
| sed -i "s/\"version\": \".*\"/\"version\": \"$VERSION\"/" manifest.json | |
| sed -i "s/Firmware v[0-9]*\.[0-9]*\.[0-9]*-beta/Firmware $VERSION/" index.html | |
| - name: Update version.json | |
| run: | | |
| # Read by the firmware's background update check. Deliberately a | |
| # static file on Pages rather than api.github.com: that API allows | |
| # 60 requests per hour and IP, which users behind carrier grade NAT | |
| # share, and its release list runs to over a hundred kilobytes. | |
| # | |
| # A tag carrying a beta counter (v0.6.0-beta.3) is an internal build | |
| # and only ever lands in "prerelease". A public tag (v0.6.0-beta) | |
| # updates both, so devices with pre-releases switched off see it too. | |
| VERSION=${{ steps.version.outputs.version }} | |
| python3 - "$VERSION" <<'PY' | |
| import json, re, sys | |
| version = sys.argv[1] | |
| data = { | |
| "stable": "", | |
| "prerelease": "", | |
| "url": "https://github.com/Niko11111/SpoolmanScale/releases/latest", | |
| } | |
| try: | |
| with open("version.json") as f: | |
| data.update(json.load(f)) | |
| except FileNotFoundError: | |
| pass | |
| data["prerelease"] = version | |
| if not re.search(r"-beta\.\d+$", version): | |
| data["stable"] = version | |
| with open("version.json", "w") as f: | |
| json.dump(data, f, indent=2) | |
| f.write("\n") | |
| print("version.json:", data) | |
| PY | |
| - name: Commit webflasher + manifest + index + version | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add webflasher/bootloader.bin webflasher/partitions.bin webflasher/SpoolmanScale.bin manifest.json index.html version.json | |
| git diff --cached --quiet || git commit -m "CI: update webflasher + manifest + index + version for ${{ steps.version.outputs.version }}" | |
| git pull origin main --rebase | |
| git push origin HEAD:main | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: SpoolmanScale ${{ steps.version.outputs.version }} | |
| # Only internal builds carrying a beta counter are pre-releases. | |
| # A public tag has to become the real "latest", because the update | |
| # button downloads from releases/latest/download/ and that path skips | |
| # pre-releases. Marked wrong, the device would announce the new | |
| # version and then install the previous binary. | |
| prerelease: ${{ contains(github.ref_name, '-beta.') }} | |
| files: | | |
| webflasher/SpoolmanScale.bin | |
| SpoolmanScale_${{ steps.version.outputs.version }}.bin | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |