Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
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
84 changes: 84 additions & 0 deletions .github/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.
#
Comment thread
ptr727 marked this conversation as resolved.
# 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
;;
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
Comment thread
ptr727 marked this conversation as resolved.
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"
52 changes: 30 additions & 22 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
name: Publish project release action

# Branch-scoped self-publisher: a push to main or develop, or a manual dispatch, publishes that branch.
# Publisher. A human PR merge never auto-publishes; a release is a deliberate dispatch or a bot merge to main.
#
# - Trigger: a push that changes a shipped input (the on.push.paths inclusion list below - library source,
# embedded data, version floor, build configuration, or package versions), or a workflow_dispatch.
# - Inclusion-only: add a path to that list when a new input starts affecting the shipped package. Package versions
# (Directory.Packages.props) ARE listed: a NuGet package cannot be rebuilt on a cadence (a version can't be
# re-pushed), so a dependency bump must republish to keep the package's declared dependencies current - this
# closes the stale/vulnerable-dependency window. GitHub Actions bumps are not listed (they do not ship in
# the package), so an Actions Dependabot bump does not republish (a package-version bump does).
# - Output: main publishes a stable release, develop a prerelease. A dispatch force-publishes its branch.
# - Gate: the publish job needs the same validate-task the PR runs, so nothing publishes that would fail
# validation, on any path (push, dispatch, or force-push).
# - The merge-bot merges with an App token, so its merge commits reach this push trigger.
# - Push trigger (main only, on.push.paths inclusion list below - library source, embedded data, version floor,
# build config, or package versions): a code-affecting Dependabot/codegen merge auto-publishes a stable release.
# The plan job (publish-plan-task.yml) computes the gate once - only the codegen App / Dependabot actor
# qualifies on a push, so a human merge or promotion to main skips and the maintainer dispatches when ready.
# - Inclusion-only: add a path when a new input starts affecting the shipped package. Package versions
# (Directory.Packages.props) ARE listed: a NuGet version can't be re-pushed, so a dependency bump must
# republish to keep declared dependencies current (closes the stale/vulnerable-dependency window). GitHub
# Actions bumps are not listed (they don't ship in the package), so an Actions bump merges without republishing.
# - workflow_dispatch: the maintainer publishes the chosen branch - main a stable release, develop a prerelease.
# - Gate: the publish job needs the same validate-task the PR runs, so nothing publishes that would fail validation.
on:
push:
branches: [main, develop]
branches: [main]
paths:
- 'LanguageTags/**'
- 'LanguageData/**'
Expand All @@ -32,22 +31,31 @@ concurrency:

jobs:

# The same unit-test + lint gate the PR runs. The publish job needs it, so a failing test or lint blocks
# the release.
# Single source of the release-gate decision (publish? stable?); validate + publish gate on its outputs
# instead of re-testing event/actor/branch. See publish-plan-task.yml for the policy.
plan:
name: Plan release job
uses: ./.github/workflows/publish-plan-task.yml
with:
event_name: ${{ github.event_name }}
actor: ${{ github.actor }}
ref_name: ${{ github.ref_name }}

# The same unit-test + lint gate the PR runs, on the branch tip; runs only when a publish will happen.
validate:
name: Validate job
needs: [plan]
if: ${{ needs.plan.outputs.publish == 'true' }}
uses: ./.github/workflows/validate-task.yml
# Thread CODECOV_TOKEN through so the unit-test job can upload coverage.
secrets: inherit

# Build, version, validate, push, and release the triggering branch. Grants the write scopes
# build-release-task needs (it declares none, so the read-only smoke caller is not forced to over-grant).
# The push trigger is already limited to main/develop, and the if-guard covers a workflow_dispatch, which
# can target any branch.
# Build, version, validate, push, and release the triggering branch (main = release, develop = prerelease via
# dispatch). Grants the write scopes build-release-task needs (it declares none, so the read-only smoke caller
# is not forced to over-grant). Gated on the plan decision.
publish:
name: Publish project release job
needs: validate
if: ${{ github.event_name == 'push' || github.ref_name == 'main' || github.ref_name == 'develop' }}
needs: [plan, validate]
if: ${{ needs.plan.outputs.publish == 'true' }}
uses: ./.github/workflows/build-release-task.yml
secrets: inherit
permissions:
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/test-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ jobs:
name: Validate job
if: ${{ !github.event.deleted }}
uses: ./.github/workflows/validate-task.yml
# Thread CODECOV_TOKEN through so the unit-test job can upload coverage.
secrets: inherit

# Build and pack the library in its branch configuration to prove it ships, publishing nothing. Runs on
Expand Down