Files
Meshtastic-Android/.github/workflows/docs-release.yml
T

171 lines
6.8 KiB
YAML

name: Docs Release
# Publishes release docs to the persistent gh-pages branch.
#
# promote.yml dispatches this on the tag after every open, closed and production
# promotion, because a tag created with GITHUB_TOKEN starts no workflow. The tag
# trigger covers a tag pushed by hand, and a manual run against a tag ref
# (re)publishes that version without cutting a new tag.
#
# Production tags (vX.Y.Z) own the site root and get a permanent /vX.Y.Z/ copy,
# plus a refreshed Dokka reference at /api/.
#
# Open- and closed-testing tags (vX.Y.Z-open.N / vX.Y.Z-closed.N) publish a
# per-tag snapshot at /vX.Y.Z-open.N/ only. They deliberately do NOT touch the
# root or /api/: the root belongs to production releases, and /api/ is an
# unversioned channel that docs-deploy.yml rebuilds from main every day.
#
# These per-tag prerelease directories accumulate during a version cycle and are
# reaped by post-release-cleanup.yml, which a production publish dispatches.
#
# The /main/ snapshot is owned by docs-deploy.yml and is left untouched here.
on:
push:
tags:
# Production plus the open/closed testing tracks. Internal builds are
# excluded: they are tagged many times per cycle and are not a channel we
# publish documentation for.
- 'v*.*.*'
- '!v*-internal.*'
workflow_dispatch:
permissions:
contents: write
concurrency:
group: pages
cancel-in-progress: false
jobs:
publish:
if: github.repository == 'meshtastic/Meshtastic-Android'
runs-on: ubuntu-26.04
timeout-minutes: 45
# actions: write is only for the cleanup dispatch; job permissions replace the
# workflow block, so contents: write is restated.
permissions:
contents: write
actions: write
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# Resolves the tag into: the docs version label (which becomes the
# published directory name) and whether this is a production release.
- name: Resolve Release Channel
id: version
run: |
set -euo pipefail
case "$GITHUB_REF" in
refs/tags/*) TAG="${GITHUB_REF#refs/tags/}" ;;
*)
echo "This workflow must run against a release tag ref (got $GITHUB_REF)." >&2
echo "For workflow_dispatch, select the tag under 'Use workflow from'." >&2
exit 1
;;
esac
if [[ "$TAG" =~ ^v([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then
echo "docs_version=${BASH_REMATCH[1]}" >> "$GITHUB_OUTPUT"
echo "is_production=true" >> "$GITHUB_OUTPUT"
echo "Production release: ${BASH_REMATCH[1]} -> / and /v${BASH_REMATCH[1]}/"
elif [[ "$TAG" =~ ^v([0-9]+\.[0-9]+\.[0-9]+-(open|closed)\.[0-9]+)$ ]]; then
echo "docs_version=${BASH_REMATCH[1]}" >> "$GITHUB_OUTPUT"
echo "is_production=false" >> "$GITHUB_OUTPUT"
echo "${BASH_REMATCH[2]}-testing prerelease -> /v${BASH_REMATCH[1]}/ only"
else
echo "Tag '$TAG' is not a publishable docs channel." >&2
echo "Expected vX.Y.Z, vX.Y.Z-open.N or vX.Y.Z-closed.N." >&2
exit 1
fi
- name: Gradle Setup
uses: ./.github/actions/gradle-setup
with:
gradle_encryption_key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
develocity_access_key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
# Dokka runs commonizeNativeDistribution, which reads ~/.konan.
cache_konan: 'true'
cache_robolectric: 'false'
- name: Setup Ruby
uses: ruby/setup-ruby@14594264cd68ce8a2345dd349bc3d138a4ef85c8 # v1.327.0
# With ruby-version unset this reads the root .ruby-version; the bundle is docs/Gemfile.
env:
BUNDLE_GEMFILE: docs/Gemfile
with:
bundler-cache: true
# Versioned docs (/vX.Y.Z/ or /vX.Y.Z-open.N/) — built for every channel.
- name: Build Versioned Docs
run: ./gradlew generateDocsBundle validateDocsBundle publishDocsSite -Pdocs.channel=release -Pdocs.version=${{ steps.version.outputs.docs_version }} -Pci=true
# Root site (/) — production releases only.
- name: Build Root Docs Site
if: steps.version.outputs.is_production == 'true'
run: ./gradlew publishDocsSite -Pdocs.channel=root -Pci=true
# The versioned source leaves build/_site/ first so the root site does not
# nest it. The Jekyll builds read only the generated sites and Dokka (the
# /api/ reference, production only) only the sources, so all three overlap.
- name: Build Jekyll Sites and Dokka
env:
DOCS_VERSION: ${{ steps.version.outputs.docs_version }}
IS_PRODUCTION: ${{ steps.version.outputs.is_production }}
run: |
set -euo pipefail
site_name="${GITHUB_REPOSITORY#*/}"
mv "build/_site/v${DOCS_VERSION}" build/v_temp
BUNDLE_GEMFILE=docs/Gemfile bundle exec jekyll build \
--source build/v_temp \
--destination build/jekyll_release \
--baseurl "/${site_name}/v${DOCS_VERSION}" &
release_pid=$!
root_pid=""
if [ "$IS_PRODUCTION" = "true" ]; then
BUNDLE_GEMFILE=docs/Gemfile bundle exec jekyll build \
--source build/_site \
--destination build/jekyll_root \
--baseurl "/${site_name}" &
root_pid=$!
./gradlew :dokkaGeneratePublicationHtml
fi
wait "$release_pid"
if [ -n "$root_pid" ]; then
wait "$root_pid"
fi
- name: Stage channels
id: stage
env:
DOCS_VERSION: ${{ steps.version.outputs.docs_version }}
IS_PRODUCTION: ${{ steps.version.outputs.is_production }}
run: |
set -euo pipefail
mkdir -p build/pages_staging
cp -r build/jekyll_release "build/pages_staging/v${DOCS_VERSION}"
channels="v${DOCS_VERSION}"
if [ "$IS_PRODUCTION" = "true" ]; then
cp -r build/jekyll_root build/pages_staging/root
cp -r build/dokka/html build/pages_staging/api
channels="root $channels api"
fi
echo "channels=$channels" >> "$GITHUB_OUTPUT"
- name: Publish to gh-pages
run: scripts/docs/publish-to-gh-pages.sh build/pages_staging ${{ steps.stage.outputs.channels }}
# The cleanup refuses to reap until /vX.Y.Z/ is on gh-pages, which the push above
# just made true. A dispatch is exempt from GITHUB_TOKEN's event suppression.
- name: Dispatch post-release cleanup
if: steps.version.outputs.is_production == 'true'
env:
GH_TOKEN: ${{ github.token }}
BASE_VERSION: ${{ steps.version.outputs.docs_version }}
run: gh workflow run post-release-cleanup.yml --ref main -f "base_version=$BASE_VERSION" -f confirm_deletion=true