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
1 change: 1 addition & 0 deletions .github/workflows/push.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ jobs:
FOLDER: docs/_build/html # The folder the action should deploy.
Publish:
runs-on: ubuntu-latest
needs: Test
if: |
(github.repository == 'PolicyEngine/policyengine-core')
&& (github.event.head_commit.message == 'Update PolicyEngine Core')
Expand Down
1 change: 1 addition & 0 deletions changelog.d/fix-publish-needs-test.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The release workflow now publishes to PyPI only after the Test job passes, instead of running Publish beside Test.
31 changes: 31 additions & 0 deletions tests/core/test_release_tagging.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import re
import shutil
import subprocess
import sys
from pathlib import Path

import pytest
import yaml


ROOT = Path(__file__).resolve().parents[2]
Expand Down Expand Up @@ -154,3 +156,32 @@ def test_publish_workflow_tags_only_after_pypi_succeeds():
assert "fetch-depth: 0" in publish_job
assert publish_job.index(tag_step) > publish_job.index(publish_step)
assert "publish-git-tag.sh || true" not in publish_job


def test_publish_workflow_publishes_only_after_tests_pass():
# Without ``needs: Test``, Publish ran beside Test, so a release could
# reach PyPI while its tests were still running or after they failed.
jobs = yaml.safe_load(PUSH_WORKFLOW.read_text())["jobs"]
publishing = [
name
for name, job in jobs.items()
if any(
"gh-action-pypi-publish" in step.get("uses", "")
for step in job.get("steps", [])
)
]

assert publishing == ["Publish"]
needs = jobs["Publish"].get("needs", [])
assert "Test" in ([needs] if isinstance(needs, str) else needs)
# A job that needs Test is skipped whenever Test is, so both must run on
# the same commits for releases to happen at all.
assert jobs["Publish"]["if"] == jobs["Test"]["if"]
# A status function such as always() would let Publish run after a
# failed Test; without one, Publish runs only when Test succeeds.
# (Expression function names are matched case-insensitively.)
assert not re.search(
r"\b(always|failure|cancelled|success)\s*\(",
jobs["Publish"]["if"],
re.IGNORECASE,
)
Loading