# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
# ══════════════════════════════════════════════════════════════════════
# ReleaseKit: Rollback Pipeline
# ══════════════════════════════════════════════════════════════════════
#
# SAMPLE WORKFLOW — Copy to .github/workflows/releasekit-rollback.yml
#
# This workflow provides a one-click rollback for failed or problematic
# releases. It can:
#
# 1. Delete git tags (local + remote)
# 2. Delete GitHub Releases
# 3. Yank packages from registries (opt-in)
#
# ── Manual Dispatch UI ────────────────────────────────────────────────
#
# ┌─────────────────────────────────────────────────────────────┐
# │ workflow_dispatch UI │
# │ │
# │ tag: [genkit-v1.2.0] tag to roll back │
# │ workspace: [py / go / js / ...] │
# │ all_tags: [✓] delete all tags at the same commit │
# │ yank: [✓] also yank from package registry │
# │ yank_reason: [________] reason for yanking │
# │ dry_run: [✓] simulate, no side effects │
# └─────────────────────────────────────────────────────────────┘
#
# ── Safety ────────────────────────────────────────────────────────────
#
# The workflow defaults to dry_run=true so accidental triggers are
# harmless. Yanking is opt-in and requires explicit confirmation.
#
# ══════════════════════════════════════════════════════════════════════
name: "ReleaseKit: Rollback"
on:
workflow_call:
inputs:
tag:
description: 'Git tag to roll back'
required: true
type: string
workspace:
description: 'Workspace to target'
required: false
default: py
type: string
all_tags:
description: 'Delete ALL tags pointing to the same commit'
required: false
default: true
type: boolean
yank:
description: 'Also yank/deprecate versions from the package registry'
required: false
default: false
type: boolean
yank_reason:
description: 'Reason for yanking'
required: false
type: string
dry_run:
description: 'Dry run'
required: false
default: true
type: boolean
secrets:
GITHUB_TOKEN:
required: false
workflow_dispatch:
inputs:
tag:
description: 'Git tag to roll back (e.g. genkit-v1.2.0)'
required: true
type: string
workspace:
description: 'Workspace to target'
required: false
default: py
type: choice
options:
- py
- go
- js
- js-cli
- dart
- rust
all_tags:
description: 'Delete ALL tags pointing to the same commit (all per-package tags from the same release)'
required: false
default: true
type: boolean
yank:
description: 'Also yank/deprecate versions from the package registry'
required: false
default: false
type: boolean
yank_reason:
description: 'Reason for yanking (shown to users installing the package)'
required: false
type: string
dry_run:
description: 'Dry run — log what would happen without deleting anything'
required: true
default: true
type: boolean
# Only one rollback runs at a time.
concurrency:
group: releasekit-rollback
cancel-in-progress: false
permissions:
contents: write # Delete tags and releases
pull-requests: write # Update PR labels
env:
RELEASEKIT_DIR: py/tools/releasekit
jobs:
rollback:
name: "Rollback: ${{ inputs.tag }}"
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true
token: ${{ secrets.GITHUB_TOKEN }}
- name: Run releasekit rollback
id: rk
uses: ./py/tools/releasekit
with:
command: rollback
workspace: ${{ inputs.workspace }}
tag: ${{ inputs.tag }}
dry-run: ${{ inputs.dry_run && 'true' || 'false' }}
all-tags: ${{ inputs.all_tags && 'true' || 'false' }}
yank: ${{ inputs.yank && 'true' || 'false' }}
yank-reason: ${{ inputs.yank_reason }}