# CI and releases (docs/milestones/R1.md). # A push to main: the host tests, with their coverage of lib/, and the README's badges # published to the branch `badges`. # A pull request: the same tests and coverage, then the release firmware and the Debug Build. # A branch's pushes run nothing by themselves: its pull request runs, once. # A tag v*: all of it, then a Gitea release with the signed Update File. # Run by hand: the release of a tag that exists already (the ones from before CI). # # The job runs in a plain Python image, as scripts/ci.sh does on a developer's machine, with the # toolchains in a Docker volume the runner allows (container.valid_volumes: roro9stack-pio): that # volume is the cache. No JavaScript actions, so the image needs no Node: the checkout is git. name: CI on: push: branches: [main] # other branches are tested by their pull request: one run, not two tags: ['v*'] # A change that touches nothing but the site and the documents it is built from runs the Site # workflow only (a tag always runs this one: Gitea doesn't apply path filters to tags). paths-ignore: ['site/**', 'docs/**', 'README.md', 'CONTEXT.md'] pull_request: paths-ignore: ['site/**', 'docs/**', 'README.md', 'CONTEXT.md'] workflow_dispatch: inputs: tag: description: An existing tag to build and publish as a release required: true jobs: build: runs-on: ubuntu # A pull request from a fork would run someone else's code on our runner: not without us (Q154). if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository container: image: python:3.12-slim volumes: - roro9stack-pio:/pio env: PLATFORMIO_CORE_DIR: /pio RORO_NO_DOCKER: 1 steps: - name: Tools run: | apt-get update -qq apt-get install -y -qq --no-install-recommends git build-essential openssl >/dev/null pip install -q --no-cache-dir --root-user-action=ignore platformio gcovr pio --version; df -h /pio | tail -1; ls /pio | head - name: Check out run: | find . -mindepth 1 -maxdepth 1 -exec rm -rf {} + git config --global --add safe.directory '*' git init -q . git remote add origin "${{ github.server_url }}/${{ github.repository }}.git" git fetch -q --tags origin '+refs/heads/*:refs/remotes/origin/*' '+refs/pull/*/head:refs/remotes/pull/*' git checkout -q --detach "${{ github.sha }}" git describe --tags --always - name: Host tests, and their coverage of lib/ if: github.event_name != 'workflow_dispatch' run: scripts/coverage.sh - name: The release firmware and the Debug Build if: github.event_name == 'pull_request' || github.ref_type == 'tag' run: scripts/ci.sh builds # The README's badges are files on a branch of their own, replaced at each push to main and # at each tag (the release badge says which tag is the latest) - name: Publish the badges if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref_type == 'tag') env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} run: | rm -rf /tmp/badges && mkdir /tmp/badges cp .pio/coverage/coverage.svg .pio/coverage/summary.json /tmp/badges/ scripts/coverage_badge.py --plain release "$(git describe --tags --abbrev=0)" /tmp/badges/release.svg cd /tmp/badges git init -q -b badges . git add . git -c user.name="roro9stack CI" -c user.email="ci@git.twis.la" commit -q -m "Coverage of ${{ github.ref_name }} at ${{ github.sha }}" git push -q --force "$(echo "${{ github.server_url }}" | sed "s#://#://ci:${GITEA_TOKEN}@#")/${{ github.repository }}.git" badges - name: Which release id: release run: | if [ "${{ github.event_name }}" = workflow_dispatch ]; then echo "tag=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" elif [ "${{ github.ref_type }}" = tag ]; then echo "tag=${{ github.ref_name }}" >> "$GITHUB_OUTPUT" fi - name: Build and sign the release if: steps.release.outputs.tag != '' env: OTA_SIGNING_KEY: ${{ secrets.OTA_SIGNING_KEY }} run: | # The sources of the tag in a clone of their own; the tools are this commit's. rm -rf /tmp/release-src dist git clone -q . /tmp/release-src git -C /tmp/release-src checkout -q --detach "refs/tags/${{ steps.release.outputs.tag }}" # The key exists as a file only while this step runs, in a container that goes with the job. umask 077 export RORO_OTA_KEY="$(mktemp)" trap 'rm -f "$RORO_OTA_KEY"' EXIT printf '%s\n' "$OTA_SIGNING_KEY" > "$RORO_OTA_KEY" umask 022 scripts/release_build.sh /tmp/release-src dist - name: Publish the release if: steps.release.outputs.tag != '' env: GITEA_API: ${{ github.server_url }}/api/v1 GITEA_REPO: ${{ github.repository }} GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} run: scripts/release_publish.py dist