ci: nightly develop build published to github.io firmware-nightly/ (#10957)
Adds a scheduled (09:00 UTC) run of the CI build off develop that does everything a workflow_dispatch build does except create a GitHub release. Instead it refreshes a single, stable firmware-nightly/ folder on meshtastic.github.io with the current develop build, leaving that folder's hand-maintained release_notes.md untouched so it can be edited manually. On a nightly run (the schedule, or a manual nightly=true dispatch) only the firmware build + gather-artifacts + the new publish-nightly job run; the tests/docker/wasm/macOS/debian-src/size jobs and the three release jobs are skipped, so no release or tag is created. publish-nightly downloads the per-board artifacts, generates the firmware-<version>.json release manifest and an index.json version pointer (read by the web-flasher), then publishes to firmware-nightly/ via the same peaceiris/actions-gh-pages action used for releases. keep_files:false is scoped to destination_dir, so it clears stale nightly binaries while leaving sibling release folders untouched; the hand-maintained release_notes.md is fetched and carried forward first (fail-closed) so it is never clobbered.
This commit is contained in:
@@ -26,7 +26,19 @@ on:
|
|||||||
- "**.md"
|
- "**.md"
|
||||||
#- "**.yml"
|
#- "**.yml"
|
||||||
|
|
||||||
|
schedule:
|
||||||
|
# Nightly develop build, published to meshtastic.github.io firmware-nightly/ (no GitHub release).
|
||||||
|
# Scheduled runs execute on the default branch (develop). 09:00 UTC avoids the 00:00 tests
|
||||||
|
# and 02:00 daily_packaging crons.
|
||||||
|
- cron: 0 9 * * * # Nightly develop build/publish (default branch is develop)
|
||||||
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
# trunk-ignore(checkov/CKV_GHA_7): intentional manual-test switch for the nightly publish path
|
||||||
|
nightly:
|
||||||
|
description: "Nightly mode: build + publish develop to github.io firmware-nightly/ (skips creating a GitHub release)"
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
permissions: read-all
|
permissions: read-all
|
||||||
|
|
||||||
@@ -85,7 +97,7 @@ jobs:
|
|||||||
# Runs on GitHub-hosted runners so checks don't compete with builds for the
|
# Runs on GitHub-hosted runners so checks don't compete with builds for the
|
||||||
# self-hosted 'arctastic' pool (which builds use).
|
# self-hosted 'arctastic' pool (which builds use).
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.event_name != 'workflow_dispatch' && github.repository == 'meshtastic/firmware' }}
|
if: ${{ github.event_name != 'workflow_dispatch' && github.repository == 'meshtastic/firmware' && github.event_name != 'schedule' && github.event.inputs.nightly != 'true' }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v7
|
- uses: actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
@@ -110,7 +122,7 @@ jobs:
|
|||||||
platform: ${{ matrix.build.platform }}
|
platform: ${{ matrix.build.platform }}
|
||||||
|
|
||||||
build-debian-src:
|
build-debian-src:
|
||||||
if: github.repository == 'meshtastic/firmware'
|
if: ${{ github.repository == 'meshtastic/firmware' && github.event_name != 'schedule' && github.event.inputs.nightly != 'true' }}
|
||||||
uses: ./.github/workflows/build_debian_src.yml
|
uses: ./.github/workflows/build_debian_src.yml
|
||||||
with:
|
with:
|
||||||
series: UNRELEASED
|
series: UNRELEASED
|
||||||
@@ -118,6 +130,7 @@ jobs:
|
|||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
MacOS:
|
MacOS:
|
||||||
|
if: ${{ github.event_name != 'schedule' && github.event.inputs.nightly != 'true' }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -139,7 +152,7 @@ jobs:
|
|||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
test-native:
|
test-native:
|
||||||
if: ${{ !contains(github.ref_name, 'event/') && github.repository == 'meshtastic/firmware' }}
|
if: ${{ !contains(github.ref_name, 'event/') && github.repository == 'meshtastic/firmware' && github.event_name != 'schedule' && github.event.inputs.nightly != 'true' }}
|
||||||
permissions: # Needed for dorny/test-reporter.
|
permissions: # Needed for dorny/test-reporter.
|
||||||
contents: read
|
contents: read
|
||||||
actions: read
|
actions: read
|
||||||
@@ -147,6 +160,7 @@ jobs:
|
|||||||
uses: ./.github/workflows/test_native.yml
|
uses: ./.github/workflows/test_native.yml
|
||||||
|
|
||||||
build-wasm:
|
build-wasm:
|
||||||
|
if: ${{ github.event_name != 'schedule' && github.event.inputs.nightly != 'true' }}
|
||||||
# Build the WebAssembly portduino node ([env:native-wasm]) as part of normal CI,
|
# Build the WebAssembly portduino node ([env:native-wasm]) as part of normal CI,
|
||||||
# like the other platforms. It's a dedicated job (not a row in the `build`
|
# like the other platforms. It's a dedicated job (not a row in the `build`
|
||||||
# matrix) because its artifact is meshnode.{mjs,wasm} - not a flashable
|
# matrix) because its artifact is meshnode.{mjs,wasm} - not a flashable
|
||||||
@@ -155,6 +169,7 @@ jobs:
|
|||||||
uses: ./.github/workflows/build_portduino_wasm.yml
|
uses: ./.github/workflows/build_portduino_wasm.yml
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
|
if: ${{ github.event_name != 'schedule' && github.event.inputs.nightly != 'true' }}
|
||||||
permissions: # Needed for pushing to GHCR.
|
permissions: # Needed for pushing to GHCR.
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
@@ -255,7 +270,7 @@ jobs:
|
|||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
firmware-size-report:
|
firmware-size-report:
|
||||||
if: github.repository == 'meshtastic/firmware'
|
if: ${{ github.repository == 'meshtastic/firmware' && github.event_name != 'schedule' && github.event.inputs.nightly != 'true' }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -379,6 +394,7 @@ jobs:
|
|||||||
# exceeds its static RAM (.data+.bss) or flash budget. Kept separate from
|
# exceeds its static RAM (.data+.bss) or flash budget. Kept separate from
|
||||||
# firmware-size-report, which is informational and continue-on-error.
|
# firmware-size-report, which is informational and continue-on-error.
|
||||||
size-budget-gate:
|
size-budget-gate:
|
||||||
|
if: ${{ github.event_name != 'schedule' && github.event.inputs.nightly != 'true' }}
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
actions: read
|
actions: read
|
||||||
@@ -407,7 +423,7 @@ jobs:
|
|||||||
permissions: # Needed for 'gh release upload'.
|
permissions: # Needed for 'gh release upload'.
|
||||||
contents: write
|
contents: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' && github.repository == 'meshtastic/firmware' }}
|
if: ${{ github.event_name == 'workflow_dispatch' && github.repository == 'meshtastic/firmware' && github.event.inputs.nightly != 'true' }}
|
||||||
outputs:
|
outputs:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
needs:
|
needs:
|
||||||
@@ -516,7 +532,7 @@ jobs:
|
|||||||
- rp2350
|
- rp2350
|
||||||
- stm32
|
- stm32
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' && github.repository == 'meshtastic/firmware'}}
|
if: ${{ github.event_name == 'workflow_dispatch' && github.repository == 'meshtastic/firmware' && github.event.inputs.nightly != 'true' }}
|
||||||
needs: [release-artifacts, version]
|
needs: [release-artifacts, version]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -568,7 +584,7 @@ jobs:
|
|||||||
|
|
||||||
publish-firmware:
|
publish-firmware:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.nightly != 'true' }}
|
||||||
needs: [release-firmware, version]
|
needs: [release-firmware, version]
|
||||||
env:
|
env:
|
||||||
targets: |-
|
targets: |-
|
||||||
@@ -620,3 +636,78 @@ jobs:
|
|||||||
user_email: github-actions[bot]@users.noreply.github.com
|
user_email: github-actions[bot]@users.noreply.github.com
|
||||||
commit_message: ${{ needs.version.outputs.long }}
|
commit_message: ${{ needs.version.outputs.long }}
|
||||||
enable_jekyll: true
|
enable_jekyll: true
|
||||||
|
|
||||||
|
# Nightly publish: refresh the single, stable firmware-nightly/ folder on
|
||||||
|
# meshtastic.github.io with the current develop build. Runs on the cron schedule
|
||||||
|
# (or a manual nightly=true dispatch) and never creates a GitHub release. The
|
||||||
|
# folder's release_notes.md is maintained by hand and deliberately left untouched.
|
||||||
|
publish-nightly:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
if: ${{ (github.event_name == 'schedule' || github.event.inputs.nightly == 'true') && github.repository == 'meshtastic/firmware' }}
|
||||||
|
needs: [setup, version, gather-artifacts]
|
||||||
|
env:
|
||||||
|
targets: |-
|
||||||
|
esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,rp2350,stm32
|
||||||
|
steps:
|
||||||
|
- name: Get firmware artifacts
|
||||||
|
uses: actions/download-artifact@v8
|
||||||
|
with:
|
||||||
|
pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }}
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./stage
|
||||||
|
|
||||||
|
- name: Generate Release manifest
|
||||||
|
run: |
|
||||||
|
jq -n --arg ver "${{ needs.version.outputs.long }}" --argjson targets ${{ toJson(needs.setup.outputs.all) }} '{
|
||||||
|
"version": $ver,
|
||||||
|
"targets": $targets
|
||||||
|
}' > ./stage/firmware-${{ needs.version.outputs.long }}.json
|
||||||
|
|
||||||
|
- name: Generate nightly pointer
|
||||||
|
run: |
|
||||||
|
jq -n \
|
||||||
|
--arg ver "${{ needs.version.outputs.long }}" \
|
||||||
|
--arg sha "${{ github.sha }}" \
|
||||||
|
'{version: $ver, id: ("v" + $ver), title: ("Meshtastic Firmware " + $ver + " Nightly"), commit: $sha}' \
|
||||||
|
> ./stage/index.json
|
||||||
|
|
||||||
|
- name: Preserve manually-maintained release notes
|
||||||
|
# firmware-nightly/release_notes.md is edited by hand. Carry the current
|
||||||
|
# copy into ./stage so the keep_files:false publish (which refreshes the
|
||||||
|
# folder and clears stale nightly binaries) does not drop it. Seed a
|
||||||
|
# placeholder on the first run (404); fail closed on any other error so a
|
||||||
|
# transient fetch failure never clobbers the notes.
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
url=https://raw.githubusercontent.com/meshtastic/meshtastic.github.io/master/firmware-nightly/release_notes.md
|
||||||
|
code=$(curl -sSL -o ./stage/release_notes.md -w '%{http_code}' --retry 5 --retry-all-errors "$url" || echo 000)
|
||||||
|
if [ "$code" = "200" ]; then
|
||||||
|
echo "Preserved existing release_notes.md"
|
||||||
|
elif [ "$code" = "404" ]; then
|
||||||
|
echo "No existing release_notes.md; seeding placeholder"
|
||||||
|
printf '# Nightly (develop)\n\nAutomated nightly build from the `develop` branch. Edit these notes by hand.\n' > ./stage/release_notes.md
|
||||||
|
else
|
||||||
|
echo "Unexpected HTTP $code fetching release_notes.md; refusing to publish to avoid clobbering manual notes"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For diagnostics
|
||||||
|
- name: Display structure of files to publish
|
||||||
|
run: ls -lR ./stage
|
||||||
|
|
||||||
|
- name: Publish nightly to meshtastic.github.io
|
||||||
|
uses: peaceiris/actions-gh-pages@v4
|
||||||
|
with:
|
||||||
|
deploy_key: ${{ secrets.DIST_PAGES_DEPLOY_KEY }}
|
||||||
|
external_repository: meshtastic/meshtastic.github.io
|
||||||
|
publish_branch: master
|
||||||
|
publish_dir: ./stage
|
||||||
|
# keep_files:false is scoped to destination_dir, so this refreshes only
|
||||||
|
# firmware-nightly/ (clearing stale nightly binaries) while sibling
|
||||||
|
# release folders stay untouched; release_notes.md is carried in above.
|
||||||
|
destination_dir: firmware-nightly
|
||||||
|
keep_files: false
|
||||||
|
user_name: github-actions[bot]
|
||||||
|
user_email: github-actions[bot]@users.noreply.github.com
|
||||||
|
commit_message: Nightly ${{ needs.version.outputs.long }}
|
||||||
|
enable_jekyll: true
|
||||||
|
|||||||
Reference in New Issue
Block a user