Skip to content

Commit e9d14ea

Browse files
ci(release): align PyPI OIDC + GHCR lowercase (#79)
* ci(release): fix publish-on-semrel (permissions, tag resolve, GHCR+PyPI steps) * ci(release): align PyPI OIDC (env pypi, workflow name) + GHCR lowercase; publish on semrel
1 parent 751e219 commit e9d14ea

File tree

2 files changed

+116
-97
lines changed

2 files changed

+116
-97
lines changed
Lines changed: 41 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,76 @@
11
name: publish-on-semrel
2+
23
on:
34
workflow_run:
45
workflows: ["semantic-release"]
56
types: [completed]
67
workflow_dispatch:
78
inputs:
89
tag:
9-
description: "Tag a publicar (p.ej. v0.4.35). Vacío = último release"
10+
description: "Tag a publicar (ej. v0.4.35)"
1011
required: false
11-
default: ""
12-
permissions:
13-
contents: read
14-
packages: write
15-
id-token: write
16-
concurrency:
17-
group: publish-${{ github.event_name }}-${{ github.run_id }}
18-
cancel-in-progress: false
12+
type: string
13+
1914
jobs:
2015
publish:
21-
if: ${{ github.event_name == 'workflow_dispatch' || (github.event.workflow_run.conclusion == 'success') }}
16+
if: >
17+
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') ||
18+
(github.event_name == 'workflow_dispatch')
2219
runs-on: ubuntu-latest
23-
environment: pypi
20+
permissions:
21+
contents: read
22+
packages: write
23+
id-token: write
2424
steps:
25-
- uses: actions/checkout@v4
25+
- name: Checkout (con tags)
26+
uses: actions/checkout@v4
2627
with:
2728
fetch-depth: 0
2829

29-
# Obtener tag del último release
30-
- uses: actions/github-script@v7
31-
id: latest
32-
with:
33-
script: |
34-
const { data } = await github.repos.getLatestRelease({ owner: context.repo.owner, repo: context.repo.repo });
35-
core.setOutput('tag', data.tag_name);
36-
37-
- name: Resolver TAG de publicación
30+
- name: Resolver TAG
3831
id: tag
3932
shell: bash
4033
run: |
41-
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]] && [[ -n "${{ github.event.inputs.tag }}" ]]; then
34+
if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" && -n "${{ github.event.inputs.tag }}" ]]; then
4235
TAG="${{ github.event.inputs.tag }}"
4336
else
44-
TAG="${{ steps.latest.outputs.tag }}"
37+
git fetch --tags --force
38+
TAG="$(git tag -l 'v*' --sort=-v:refname | head -n1)"
4539
fi
46-
echo "TAG=$TAG" >> "$GITHUB_ENV"
40+
echo "TAG=$TAG" | tee -a "$GITHUB_ENV"
4741
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
48-
echo "Publicando tag: $TAG"
42+
echo "Publicando TAG=$TAG"
4943
50-
- name: Sincronizar version de pyproject.toml con TAG
51-
shell: bash
44+
- name: Setup Python
45+
uses: actions/setup-python@v5
46+
with:
47+
python-version: '3.12'
48+
49+
- name: Build sdist & wheel
5250
run: |
53-
python - <<'PY'
54-
import os, re, pathlib
55-
tag = os.environ["TAG"].lstrip('v')
56-
p = pathlib.Path("pyproject.toml")
57-
t = p.read_text()
58-
t = re.sub(r'(?m)^(\s*version\s*=\s*")\d+\.\d+\.\d+(")', rf"\1{tag}\2", t)
59-
p.write_text(t)
60-
print("Set version ->", tag)
61-
PY
51+
python -m pip install -U pip build
52+
python -m build
6253
63-
# Build & push GHCR
64-
- name: Set IMAGE
65-
run: echo "IMAGE=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_ENV"
54+
- name: Publish to PyPI (OIDC)
55+
uses: pypa/gh-action-pypi-publish@release/v1
56+
with:
57+
packages-dir: dist
58+
skip-existing: true
6659

67-
- uses: docker/setup-qemu-action@v3
68-
- uses: docker/setup-buildx-action@v3
69-
- uses: docker/login-action@v3
60+
- name: Login GHCR
61+
uses: docker/login-action@v3
7062
with:
7163
registry: ghcr.io
7264
username: ${{ github.actor }}
7365
password: ${{ secrets.GITHUB_TOKEN }}
7466

75-
- name: Build & Push container
76-
uses: docker/build-push-action@v6
67+
- name: Setup Buildx
68+
uses: docker/setup-buildx-action@v3
69+
70+
- name: Build & Push image
71+
uses: docker/build-push-action@v5
7772
with:
7873
context: .
79-
file: ./Dockerfile
80-
platforms: linux/amd64
8174
push: true
82-
provenance: false
83-
tags: ${{ env.IMAGE }}:${{ steps.tag.outputs.tag }},${{ env.IMAGE }}:latest
84-
85-
# Build & publish PyPI (OIDC)
86-
- uses: actions/setup-python@v5
87-
with:
88-
python-version: "3.12"
89-
90-
- name: Build sdist/wheel
91-
run: |
92-
python -m pip install -U pip build
93-
python -m build
94-
95-
- name: Publish to PyPI (Trusted Publisher)
96-
uses: pypa/gh-action-pypi-publish@release/v1
97-
with:
98-
skip-existing: true
99-
verbose: true
100-
env:
101-
PYTHON_KEYRING_BACKEND: keyring.backends.null.Keyring
75+
tags: ghcr.io/${{ github.repository }}:${{ env.TAG }}
76+
platforms: linux/amd64

.github/workflows/publish-pypi.yml

Lines changed: 75 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,84 @@
11
name: publish-pypi
2-
on:
3-
release:
4-
types: [published]
5-
6-
permissions:
7-
contents: read
8-
id-token: write
92

10-
env:
11-
PIP_DISABLE_PIP_VERSION_CHECK: "1"
3+
on:
4+
workflow_run:
5+
workflows: ["semantic-release"]
6+
types: [completed]
7+
workflow_dispatch:
8+
inputs:
9+
tag:
10+
description: "Tag to publish (e.g. v0.4.35)"
11+
required: false
12+
type: string
1213

1314
jobs:
14-
pypi:
15-
if: startsWith(github.event.release.tag_name, 'v')
15+
publish:
16+
if: >
17+
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') ||
18+
(github.event_name == 'workflow_dispatch')
1619
runs-on: ubuntu-latest
1720
environment: pypi
21+
permissions:
22+
contents: read
23+
packages: write
24+
id-token: write
1825
steps:
19-
- uses: actions/checkout@v4
20-
- uses: actions/setup-python@v5
26+
- name: Checkout with tags
27+
uses: actions/checkout@v4
2128
with:
22-
python-version: '3.x'
23-
- run: python -m pip install -U pip build
24-
- name: Sync version from tag into pyproject.toml
25-
env:
26-
TAG: ${{ github.event.release.tag_name }}
29+
fetch-depth: 0
30+
31+
- name: Resolve TAG
32+
id: tag
33+
shell: bash
2734
run: |
28-
VER="${TAG#v}"
29-
export VER
30-
python - <<'PY'
31-
import os, re, pathlib
32-
ver = os.environ["VER"]
33-
p = pathlib.Path("pyproject.toml")
34-
t = p.read_text(encoding="utf-8")
35-
t = re.sub(r'(?m)^(\s*version\s*=\s*")\d+\.\d+\.\d+(")', rf'\1{ver}\2', t)
36-
p.write_text(t, encoding="utf-8")
37-
print("pyproject.toml version ->", ver)
38-
PY
39-
- run: python -m build
40-
- uses: pypa/gh-action-pypi-publish@release/v1
35+
if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" && -n "${{ github.event.inputs.tag }}" ]]; then
36+
TAG="${{ github.event.inputs.tag }}"
37+
else
38+
git fetch --tags --force
39+
TAG="$(git tag -l 'v*' --sort=-v:refname | head -n1)"
40+
fi
41+
echo "TAG=$TAG" | tee -a "$GITHUB_ENV"
42+
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
43+
44+
- name: Setup Python
45+
uses: actions/setup-python@v5
46+
with:
47+
python-version: '3.12'
48+
49+
- name: Build sdist & wheel
50+
run: |
51+
python -m pip install -U pip build
52+
python -m build
53+
54+
- name: Publish to PyPI via OIDC
55+
uses: pypa/gh-action-pypi-publish@release/v1
56+
with:
57+
packages-dir: dist
58+
skip-existing: true
59+
60+
- name: Login to GHCR
61+
uses: docker/login-action@v3
62+
with:
63+
registry: ghcr.io
64+
username: ${{ github.actor }}
65+
password: ${{ secrets.GITHUB_TOKEN }}
66+
67+
- name: Setup Buildx
68+
uses: docker/setup-buildx-action@v3
69+
70+
- name: Compute lowercase image tag
71+
id: img
72+
shell: bash
73+
run: |
74+
OWNER_LC="${GITHUB_REPOSITORY_OWNER,,}"
75+
REPO_LC="$(basename "$GITHUB_REPOSITORY" | tr '[:upper:]' '[:lower:]')"
76+
echo "IMAGE_TAG=ghcr.io/${OWNER_LC}/${REPO_LC}:${TAG}" | tee -a "$GITHUB_ENV"
77+
78+
- name: Build & Push image
79+
uses: docker/build-push-action@v5
80+
with:
81+
context: .
82+
push: true
83+
tags: ${{ env.IMAGE_TAG }}
84+
platforms: linux/amd64

0 commit comments

Comments
 (0)