status-update #2037
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: Deploy Docs | |
| on: | |
| push: | |
| branches: [main] | |
| schedule: | |
| - cron: "0 */6 * * *" # Every 6 hours | |
| workflow_dispatch: | |
| repository_dispatch: | |
| types: [status-update] | |
| permissions: | |
| contents: write | |
| pages: write | |
| id-token: write | |
| concurrency: | |
| group: "pages" | |
| cancel-in-progress: false | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/create-github-app-token@v3 | |
| id: app-token | |
| with: | |
| app-id: ${{ secrets.APP_ID }} | |
| private-key: ${{ secrets.APP_PRIVATE_KEY }} | |
| owner: daemonless | |
| - uses: actions/checkout@v6 | |
| with: | |
| path: daemonless-io | |
| - uses: actions/checkout@v6 | |
| with: | |
| repository: daemonless/daemonless | |
| token: ${{ steps.app-token.outputs.token }} | |
| path: daemonless | |
| - uses: actions/checkout@v6 | |
| with: | |
| repository: daemonless/dbuild | |
| path: dbuild | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Install dependencies | |
| run: | | |
| cd daemonless-io | |
| pip install -r requirements.txt | |
| - name: Fetch repositories | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| cd daemonless-io | |
| make fetch | |
| - name: Generate documentation | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| cd daemonless-io | |
| make generate | |
| - name: Commit generated changes | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | |
| run: | | |
| # Commit to daemonless-io (Nav, Status, and Placeholder config) | |
| cd daemonless-io | |
| git config user.name "daemonless-bot[bot]" | |
| git config user.email "3247603+daemonless-bot[bot]@users.noreply.github.com" | |
| # Generated files (zensical.toml, docs/index.md, docs/images/index.md, | |
| # docs/status.md, docs/daemonless-versions.json) are NOT committed — | |
| # `make generate` rebuilds them and `make build` deploys them, so | |
| # committing them back only causes rebase conflicts. Source of truth | |
| # is the templates under scripts/templates/ (e.g. zensical.toml.j2). | |
| git add -f placeholder-plugin.yaml | |
| git rm --ignore-unmatch mkdocs.yaml | |
| git diff --staged --quiet || git commit -m "Update generated docs and status [skip ci]" | |
| git push | |
| # Commit to daemonless/daemonless (Org README) | |
| cd ../daemonless | |
| git config user.name "daemonless-bot[bot]" | |
| git config user.email "3247603+daemonless-bot[bot]@users.noreply.github.com" | |
| git add README.md | |
| git diff --staged --quiet || git commit -m "Update Org README from daemonless-io [skip ci]" | |
| git push | |
| - name: Build site | |
| run: | | |
| cd daemonless-io | |
| make build | |
| - name: Upload artifact | |
| uses: actions/upload-pages-artifact@v4 | |
| with: | |
| path: daemonless-io/site/ | |
| deploy: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.deployment.outputs.page_url }} | |
| steps: | |
| - name: Deploy to GitHub Pages | |
| id: deployment | |
| uses: actions/deploy-pages@v5 | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Check for outdated images | |
| id: check | |
| env: | |
| DISCORD_WEBHOOK: ${{ secrets.DISCORD_VERSION_WEBHOOK }} | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set +e | |
| # This job does a plain checkout; daemonless-versions.json is gitignored | |
| # and only generated in the build job, so fetch it here before comparing. | |
| curl -sL https://raw.githubusercontent.com/daemonless/daemonless/main/daemonless-versions.json \ | |
| -o daemonless-versions.json | |
| python3 scripts/compare-versions.py > /tmp/versions.json 2>/dev/null | |
| EXIT=$? | |
| set -e | |
| COUNT=$(jq '.summary.outdated_count // 0' /tmp/versions.json 2>/dev/null || echo 0) | |
| if [ "$EXIT" -eq 0 ] || [ -z "$DISCORD_WEBHOOK" ] || [ ! -s /tmp/versions.json ] || [ "$COUNT" -eq 0 ]; then | |
| echo "should_notify=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # Signature of the outdated SET (name+tag+versions). Same set => same sig => | |
| # we only ping Discord once per distinct state instead of every rebuild. | |
| SIG=$(jq -S -c '[.outdated[] | {name, updates: [.updates[] | {tag, deployed, available}]}] | sort_by(.name)' \ | |
| /tmp/versions.json | sha256sum | cut -d' ' -f1) | |
| mkdir -p .vc-state | |
| echo "$SIG" > .vc-state/sig | |
| echo "should_notify=true" >> "$GITHUB_OUTPUT" | |
| echo "sig=$SIG" >> "$GITHUB_OUTPUT" | |
| echo "count=$COUNT" >> "$GITHUB_OUTPUT" | |
| # Cache acts as a dedup ledger: a hit means we've already announced this exact | |
| # outdated set, so skip the Discord ping. | |
| - name: Check if already announced | |
| id: dedup | |
| if: steps.check.outputs.should_notify == 'true' | |
| uses: actions/cache/restore@v4 | |
| with: | |
| path: .vc-state | |
| key: version-check-${{ steps.check.outputs.sig }} | |
| - name: Notify Discord on outdated images | |
| if: steps.check.outputs.should_notify == 'true' && steps.dedup.outputs.cache-hit != 'true' | |
| env: | |
| DISCORD_WEBHOOK: ${{ secrets.DISCORD_VERSION_WEBHOOK }} | |
| run: | | |
| DESCRIPTION=$(jq -r ' | |
| [.outdated[] as $item | | |
| (.base_names[$item.name] // $item.name) as $base | | |
| "**[\($item.name)](https://daemonless.io/images/\($item.name))**: " + | |
| ($item.updates | map( | |
| "[\(.tag)](https://github.com/daemonless/\($base)/actions/workflows/build.yaml) `\(.deployed) → \(.available)`" | |
| ) | join(", "))] | join("\n") | |
| ' /tmp/versions.json) | |
| curl -s -X POST "$DISCORD_WEBHOOK" \ | |
| -H "Content-Type: application/json" \ | |
| -d "$(jq -n \ | |
| --arg desc "$DESCRIPTION" \ | |
| --arg count "${{ steps.check.outputs.count }}" \ | |
| '{embeds: [{title: "🔄 \($count) outdated image(s)", description: $desc, color: 16744272}]}')" | |
| - name: Mark outdated set as announced | |
| if: steps.check.outputs.should_notify == 'true' && steps.dedup.outputs.cache-hit != 'true' | |
| uses: actions/cache/save@v4 | |
| with: | |
| path: .vc-state | |
| key: version-check-${{ steps.check.outputs.sig }} | |
| - name: Ping IndexNow | |
| run: | | |
| curl -s -X POST "https://api.indexnow.org/indexnow" \ | |
| -H "Content-Type: application/json" \ | |
| -d '{ | |
| "host": "daemonless.io", | |
| "key": "9165b253e91b4c86a023f24a2335428b", | |
| "keyLocation": "https://daemonless.io/9165b253e91b4c86a023f24a2335428b.txt", | |
| "urlList": [ | |
| "https://daemonless.io/", | |
| "https://daemonless.io/status/", | |
| "https://daemonless.io/images/", | |
| "https://daemonless.io/guides/quick-start/", | |
| "https://daemonless.io/guides/dbuild/", | |
| "https://daemonless.io/community/", | |
| "https://daemonless.io/philosophy/" | |
| ] | |
| }' |