diff --git a/.github/workflows/docs-deploy-on-release.yml b/.github/workflows/docs-deploy-on-release.yml new file mode 100644 index 0000000..0592609 --- /dev/null +++ b/.github/workflows/docs-deploy-on-release.yml @@ -0,0 +1,34 @@ +name: Docs Deploy On Release + +on: + release: + types: [published, edited, deleted] + +permissions: + actions: write + contents: read + +concurrency: + group: docs-release-relay-${{ github.event.release.tag_name }} + cancel-in-progress: true + +jobs: + relay: + runs-on: ubuntu-latest + steps: + - name: Dispatch Docs Deploy on main + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} + TAG: ${{ github.event.release.tag_name }} + ACTION: ${{ github.event.action }} + run: | + set -euo pipefail + gh api \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + "repos/${REPO}/actions/workflows/docs-deploy.yml/dispatches" \ + -f ref=main \ + -f "inputs[full_reconcile]=false" \ + -f "inputs[release_tag]=${TAG}" \ + -f "inputs[release_action]=${ACTION}" diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml index 82bf315..1b698da 100644 --- a/.github/workflows/docs-deploy.yml +++ b/.github/workflows/docs-deploy.yml @@ -3,11 +3,6 @@ name: Docs Deploy on: push: branches: [main] - release: - types: [published, edited, deleted] - workflow_run: - workflows: ["Version Docs on Tag"] - types: [completed] workflow_dispatch: inputs: full_reconcile: @@ -15,6 +10,14 @@ on: required: false default: false type: boolean + release_tag: + description: 'Optional release tag for incremental changelog sync (for release relay)' + required: false + type: string + release_action: + description: 'Optional release action (published, edited, deleted) for incremental sync' + required: false + type: string permissions: contents: read @@ -27,7 +30,6 @@ concurrency: jobs: build: - if: github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' runs-on: ubuntu-latest steps: diff --git a/scripts/build-changelog-feed.mjs b/scripts/build-changelog-feed.mjs index 16683b3..fdac8a6 100644 --- a/scripts/build-changelog-feed.mjs +++ b/scripts/build-changelog-feed.mjs @@ -86,6 +86,15 @@ async function fetchGitHubReleases() { return out; } +async function fetchGitHubReleaseByTag(tagName) { + const url = `https://api.github.com/repos/${REPO}/releases/tags/${encodeURIComponent(tagName)}`; + try { + return await fetchJson(url, { auth: true }); + } catch { + return null; + } +} + async function readEventPayload() { const eventPath = process.env.GITHUB_EVENT_PATH; if (!eventPath) return null; @@ -185,6 +194,36 @@ async function buildState() { return { entries: applyBodyPath(sortEntries(manifest)), bodies, mode: 'incremental-upsert' }; } + const dispatchInputs = payload?.inputs; + const dispatchTag = String(dispatchInputs?.release_tag || '').trim(); + const dispatchAction = String(dispatchInputs?.release_action || '').trim().toLowerCase(); + + if (eventName === 'workflow_dispatch' && dispatchTag) { + if (dispatchAction === 'deleted') { + const mutable = isMutable(manifest, dispatchTag); + if (mutable) { + const next = manifest.filter((entry) => entry.tag_name !== dispatchTag); + bodies.delete(dispatchTag); + return { entries: applyBodyPath(sortEntries(next)), bodies, mode: 'incremental-delete' }; + } + return { entries: applyBodyPath(manifest), bodies, mode: 'incremental-delete-skipped' }; + } + + const release = await fetchGitHubReleaseByTag(dispatchTag); + if (release && !release.draft) { + const incoming = toManifestEntry(release); + const existingIdx = manifest.findIndex((entry) => entry.tag_name === dispatchTag); + const mutable = isMutable(manifest, dispatchTag); + if (existingIdx === -1 || mutable || existingIdx < MUTABLE_COUNT) { + if (existingIdx >= 0) manifest.splice(existingIdx, 1); + manifest.push(incoming); + bodies.set(dispatchTag, toBodyRecord(release)); + } + } + + return { entries: applyBodyPath(sortEntries(manifest)), bodies, mode: 'incremental-upsert' }; + } + return { entries: applyBodyPath(manifest), bodies, mode: 'mirror' }; }