Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions catalog/snippets/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The reusable build/publish workflow tasks a code-shipping repo runs. They are **
| --- | --- | --- |
| `build-release-task.yml` | Multi-target release orchestrator: get-version, validate-release, github-release plus per-target build jobs | D3, D4, D5, D6 |
| `get-version-task.yml` | NBGV version/tag computation (reusable) | D3 |
| `publish-plan-task.yml` | Single-source release-gate decision (publish? stable?) reused by every publish-release job | D4 |
| `build-executable-task.yml` | Console/executable per-runtime publish, aggregate to one release asset | D5, D6; section 6 Console walkthrough |
| `build-nugetlibrary-task.yml` | Build + `dotnet nuget push` (OIDC), upload release asset | D3.4, D4.4, D6; section 6 NuGet walkthrough |
| `build-pypilibrary-task.yml` | Build PyPI package; publish split to an OIDC job | D3.4, D4, D7.2; section 6 PyPI walkthrough |
Expand Down
84 changes: 84 additions & 0 deletions catalog/snippets/workflows/publish-plan-task.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: Publish plan task

# Single source of truth for the release-gate decision, reused by every publish-release.yml job so the policy
# lives here, not scattered across job `if:` conditions. A human PR merge never auto-publishes; a release is a
# deliberate dispatch, a bot (Dependabot/codegen) code-merge to main, or the Docker weekly schedule.
#
# Outputs:
# publish - 'true' when this run should publish: a bot-authored push (the codegen App merges every bot PR, so
# its identity - or dependabot[bot] - is the gate), a schedule, or a workflow_dispatch of main/develop.
# A human push (a merge/promotion to main) or a dispatch from any other branch is 'false'.
# stable - 'true' when the target branch is main (stable channel); main-only jobs gate on publish && stable.
# Both outputs are the strings 'true'/'false' - gate with == 'true'; a bare `if: ${{ needs.plan.outputs.publish }}`
# is always truthy (a non-empty string is truthy in an Actions expression).
#
# Shared across repo types: a library/package repo triggers only push + dispatch and uses `publish`; a
# Docker/wrapper repo also triggers the weekly schedule and gates main-only jobs on `stable`. A case a given
# caller never triggers (e.g. schedule for a library) is simply inert for it - expected of a single-source task.

on:
workflow_call:
inputs:
event_name:
description: The triggering event (github.event_name).
required: true
type: string
actor:
description: The actor that triggered the run (github.actor).
required: true
type: string
ref_name:
description: The short ref name (github.ref_name).
required: true
type: string
outputs:
publish:
description: "'true' when this run should publish."
value: ${{ jobs.plan.outputs.publish }}
stable:
description: "'true' when the target branch is main (stable channel)."
value: ${{ jobs.plan.outputs.stable }}

jobs:

plan:
name: Plan release job
runs-on: ubuntu-latest
outputs:
publish: ${{ steps.decide.outputs.publish }}
stable: ${{ steps.decide.outputs.stable }}

steps:

- name: Decide release plan step
id: decide
env:
EVENT: ${{ inputs.event_name }}
ACTOR: ${{ inputs.actor }}
REF: ${{ inputs.ref_name }}
run: |
set -euo pipefail
publish=false
case "$EVENT" in
workflow_dispatch)
# A human release: only the long-lived branches publish (a stray feature-branch dispatch is a no-op).
[[ "$REF" == "main" || "$REF" == "develop" ]] && publish=true
;;
schedule)
# Docker weekly refresh (main-only by schedule config).
publish=true
;;
Comment thread
ptr727 marked this conversation as resolved.
push)
# A human merge never auto-publishes; only a bot merge to main does. The codegen App merges every
# Dependabot/codegen PR, so github.actor is its identity (dependabot[bot] allowed defensively). The
# ref==main guard keeps the task self-contained even if a caller's push trigger is not main-only.
if [[ "$REF" == "main" ]] && { [[ "$ACTOR" == "ptr727-codegen[bot]" ]] || [[ "$ACTOR" == "dependabot[bot]" ]]; }; then
publish=true
fi
;;
esac
stable=false
[[ "$REF" == "main" ]] && stable=true
echo "publish=$publish" >> "$GITHUB_OUTPUT"
echo "stable=$stable" >> "$GITHUB_OUTPUT"
echo "Release plan: event=$EVENT actor=$ACTOR ref=$REF -> publish=$publish stable=$stable"