Skip to content

Commit 3da0c45

Browse files
committed
fix: prevent accidental production releases from feature branches
- Disable automatic PyPI publishing on tag pushes - Add manual release workflow with validation - Tags from feature branches now only go to TestPyPI - Production releases require manual workflow dispatch with confirmation - Prevents accidental releases like the v3.0.0 incident
1 parent c5862e5 commit 3da0c45

File tree

2 files changed

+97
-4
lines changed

2 files changed

+97
-4
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
name: Manual Release to Production PyPI
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
tag:
7+
description: 'Git tag to release (e.g., v3.0.0)'
8+
required: true
9+
type: string
10+
confirm:
11+
description: 'Type "RELEASE" to confirm production release'
12+
required: true
13+
type: string
14+
15+
jobs:
16+
validate-and-release:
17+
name: Validate and Release to Production PyPI
18+
runs-on: ubuntu-latest
19+
if: github.event.inputs.confirm == 'RELEASE'
20+
21+
environment:
22+
name: pypi
23+
url: https://pypi.org/p/modulink-py
24+
25+
steps:
26+
- name: Validate inputs
27+
run: |
28+
if [[ ! "${{ github.event.inputs.tag }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
29+
echo "❌ Invalid tag format. Expected format: v1.2.3"
30+
exit 1
31+
fi
32+
echo "✅ Tag format is valid: ${{ github.event.inputs.tag }}"
33+
34+
- uses: actions/checkout@v4
35+
with:
36+
ref: ${{ github.event.inputs.tag }}
37+
persist-credentials: false
38+
39+
- name: Verify tag exists
40+
run: |
41+
if ! git tag -l | grep -q "^${{ github.event.inputs.tag }}$"; then
42+
echo "❌ Tag ${{ github.event.inputs.tag }} does not exist"
43+
exit 1
44+
fi
45+
echo "✅ Tag ${{ github.event.inputs.tag }} exists"
46+
47+
- name: Set up Python
48+
uses: actions/setup-python@v5
49+
with:
50+
python-version: "3.x"
51+
52+
- name: Install pypa/build
53+
run: >-
54+
python3 -m
55+
pip install
56+
build
57+
--user
58+
59+
- name: Build a binary wheel and a source tarball
60+
run: python3 -m build
61+
62+
- name: Publish distribution 📦 to PyPI
63+
uses: pypa/gh-action-pypi-publish@release/v1
64+
with:
65+
user: __token__
66+
password: ${{ secrets.PYPI_TOKEN }}
67+
verbose: true
68+
69+
- name: Create GitHub Release
70+
uses: actions/create-release@v1
71+
env:
72+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
73+
with:
74+
tag_name: ${{ github.event.inputs.tag }}
75+
release_name: Release ${{ github.event.inputs.tag }}
76+
body: |
77+
🎉 **ModuLink-Py ${{ github.event.inputs.tag }} Released!**
78+
79+
This release has been published to PyPI and is now available for installation:
80+
81+
```bash
82+
pip install modulink-py==${{ github.event.inputs.tag }}
83+
```
84+
85+
## Changes
86+
87+
See [CHANGELOG.md](https://github.com/orchestrate-solutions/modulink-py/blob/main/CHANGELOG.md) for detailed changes.
88+
89+
---
90+
91+
Released via manual workflow on $(date)
92+
draft: false
93+
prerelease: false

.github/workflows/publish-to-pypi.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI
22

33
on:
44
push:
5-
tags:
6-
- 'v*' # Only trigger on version tags (e.g., v1.0.0, v2.1.3)
75
branches:
86
- '**' # Trigger on all branch pushes for TestPyPI testing
97
- '!main' # Exclude main branch
8+
tags:
9+
- 'v*' # Trigger on version tags
1010

1111
jobs:
1212
build:
@@ -44,7 +44,7 @@ jobs:
4444
needs:
4545
- build
4646
runs-on: ubuntu-latest
47-
if: github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/tags/') # Only publish to TestPyPI on feature branches (not main, not tags)
47+
if: github.ref != 'refs/heads/main' # Publish to TestPyPI on all branches except main, including feature branches and tags
4848

4949
environment:
5050
name: testpypi
@@ -67,7 +67,7 @@ jobs:
6767
publish-to-pypi:
6868
name: >-
6969
Publish Python 🐍 distribution 📦 to PyPI
70-
if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
70+
if: false # Disabled - require manual GitHub release to publish to production
7171
needs:
7272
- build
7373
runs-on: ubuntu-latest

0 commit comments

Comments
 (0)