From 393ae9ade8a830ae12598b514929b1135caf0065 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 18 Oct 2026 07:25:14 +0000 Subject: [PATCH] feat: reusable workflow call-techdocs (build TechDocs in CI, publish to MinIO) Builds a repo's Backstage TechDocs with the techdocs Dagger module (v0.138.0): the entity is read from catalog-info.yaml, the site is generated and exported, and with publish: true uploaded to an S3/MinIO bucket for a Backstage running techdocs.builder: external. PRs call it with publish: false, so a broken mkdocs.yml fails the PR. Defaults to the dagger-labda runners, which reach the lab MinIO; a private CA comes in as a PEM input. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_013V2i6bap7BGa4ZMJRjBEAP --- .github/workflows/call-techdocs.yaml | 129 +++++++++++++++++++++++++++ README.md | 29 ++++++ 2 files changed, 158 insertions(+) create mode 100644 .github/workflows/call-techdocs.yaml diff --git a/.github/workflows/call-techdocs.yaml b/.github/workflows/call-techdocs.yaml new file mode 100644 index 0000000..78334fa --- /dev/null +++ b/.github/workflows/call-techdocs.yaml @@ -0,0 +1,129 @@ +--- +# Builds a repository's Backstage TechDocs with the techdocs Dagger module and, +# with publish: true, uploads them to S3/MinIO for a Backstage running +# techdocs.builder: external (see github.com/stuttgart-things/dagger/techdocs). +# +# Call it on pull requests with publish: false -- a broken mkdocs.yml or nav +# then fails the PR instead of showing an empty Docs tab later -- and on main +# with publish: true. +name: TechDocs (Dagger) +on: + workflow_call: + inputs: + runs-on: + # Self-hosted: the lab MinIO is not reachable from GitHub-hosted runners. + default: dagger-labda + type: string + publish: + default: false + type: boolean + description: "Upload the site; false only builds it (PR check)." + source-dir: + default: "." + type: string + description: "Directory of mkdocs.yml, relative to the repository root." + catalog-file: + default: "catalog-info.yaml" + type: string + description: "Catalog file the entity (namespace/kind/name) is read from." + entity: + default: "" + type: string + description: "//; overrides catalog-file." + bucket: + default: "techdocs" + type: string + endpoint: + default: "" + type: string + description: "S3 endpoint, e.g. https://minio.. Required with publish." + ca-cert: + default: "" + type: string + description: "PEM CA certificate for an endpoint signed by a private CA (not a secret)." + dagger-module: + default: "github.com/stuttgart-things/dagger/techdocs@v0.138.0" + type: string + dagger-version: + default: "0.21.10" + type: string + secrets: + TECHDOCS_S3_ACCESS_KEY: + required: false + TECHDOCS_S3_SECRET_KEY: + required: false + +permissions: + contents: read + +jobs: + techdocs: + name: TechDocs ${{ inputs.publish && 'build + publish' || 'build' }} + runs-on: ${{ inputs.runs-on }} + env: + MODULE: ${{ inputs.dagger-module }} + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Install Dagger CLI + run: | + curl -fsSL https://dl.dagger.io/dagger/install.sh \ + | BIN_DIR=$HOME/.local/bin DAGGER_VERSION="${{ inputs.dagger-version }}" sh + echo "$HOME/.local/bin" >> "$GITHUB_PATH" + + # Which path Backstage will read the docs under. Resolved on PRs too, so + # a catalog-info.yaml without (or with two) techdocs-ref fails early. + - name: Entity + id: entity + env: + ENTITY: ${{ inputs.entity }} + CATALOG_FILE: ${{ inputs.catalog-file }} + run: | + set -euo pipefail + if [[ -z "$ENTITY" ]]; then + ENTITY=$(dagger call -m "$MODULE" entity --src . --catalog-file "$CATALOG_FILE" | tr -d '[:space:]') + fi + echo "entity=$ENTITY" >> "$GITHUB_OUTPUT" + echo "Entity: $ENTITY" + + - name: Build + env: + SOURCE_DIR: ${{ inputs.source-dir }} + run: | + set -euo pipefail + dagger call -m "$MODULE" generate --src . --source-dir "$SOURCE_DIR" \ + export --path ./techdocs-site + test -f ./techdocs-site/techdocs_metadata.json + + # Uploads the site the Build step exported: built once, published as + # built. + - name: Publish + if: ${{ inputs.publish }} + env: + TECHDOCS_S3_ACCESS_KEY: ${{ secrets.TECHDOCS_S3_ACCESS_KEY }} + TECHDOCS_S3_SECRET_KEY: ${{ secrets.TECHDOCS_S3_SECRET_KEY }} + ENTITY: ${{ steps.entity.outputs.entity }} + BUCKET: ${{ inputs.bucket }} + ENDPOINT: ${{ inputs.endpoint }} + CA_CERT: ${{ inputs.ca-cert }} + run: | + set -euo pipefail + [[ -n "$ENDPOINT" ]] || { echo "::error::publish needs inputs.endpoint"; exit 1; } + [[ -n "$TECHDOCS_S3_ACCESS_KEY" && -n "$TECHDOCS_S3_SECRET_KEY" ]] \ + || { echo "::error::publish needs secrets TECHDOCS_S3_ACCESS_KEY and TECHDOCS_S3_SECRET_KEY"; exit 1; } + + ca_args=() + if [[ -n "$CA_CERT" ]]; then + printf '%s\n' "$CA_CERT" > "$RUNNER_TEMP/techdocs-ca.crt" + ca_args=(--ca-cert "$RUNNER_TEMP/techdocs-ca.crt") + fi + + dagger call -m "$MODULE" publish \ + --site ./techdocs-site \ + --entity "$ENTITY" \ + --bucket "$BUCKET" \ + --endpoint "$ENDPOINT" \ + --access-key env:TECHDOCS_S3_ACCESS_KEY \ + --secret-key env:TECHDOCS_S3_SECRET_KEY \ + "${ca_args[@]}" diff --git a/README.md b/README.md index 6a52b35..61c0312 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,35 @@ matrix in the caller to cover multiple modules. +
TECHDOCS (BUILD IN CI, PUBLISH TO MINIO) + +Builds Backstage TechDocs with the [techdocs Dagger module](https://github.com/stuttgart-things/dagger/tree/main/techdocs). +PRs only build (a broken `mkdocs.yml` fails the PR); `main` publishes to the +bucket a Backstage with `techdocs.builder: external` reads. The entity path is +read from `catalog-info.yaml` (the entity carrying `backstage.io/techdocs-ref`). + +```yaml +on: + pull_request: + paths: ["docs/**", "mkdocs.yml", "catalog-info.yaml"] + push: + branches: [main] + paths: ["docs/**", "mkdocs.yml", "catalog-info.yaml"] + +jobs: + techdocs: + uses: stuttgart-things/github-workflow-templates/.github/workflows/call-techdocs.yaml@main + with: + publish: ${{ github.event_name == 'push' }} + endpoint: https://minio.sthings-platform.4sthings.tiab.ssc.sva.de + ca-cert: ${{ vars.TECHDOCS_CA_CERT }} # PEM, only for a private CA + secrets: + TECHDOCS_S3_ACCESS_KEY: ${{ secrets.TECHDOCS_S3_ACCESS_KEY }} + TECHDOCS_S3_SECRET_KEY: ${{ secrets.TECHDOCS_S3_SECRET_KEY }} +``` + +
+ ## ACTIONS
SEND MESSAGE TO HOMERUN