Skip to content

Commit 2cfbcfd

Browse files
authored
chore: Restrict the sdist to an allowlist and verify it in CI (#79)
1 parent 4bb58bd commit 2cfbcfd

2 files changed

Lines changed: 102 additions & 0 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,91 @@ jobs:
6666
debug_logging: "true"
6767
token: ${{ secrets.GITHUB_TOKEN }}
6868

69+
# Proves the sdist is complete and functional, since the sdist file list is an
70+
# allowlist and an omission there is otherwise invisible. The test-count check
71+
# is what makes this meaningful: without it, an sdist missing half its tests
72+
# would still pass the tests it did ship.
73+
sdist:
74+
name: sdist (functional)
75+
runs-on: ubuntu-latest
76+
77+
steps:
78+
- uses: actions/checkout@v4
79+
80+
- name: Set up uv
81+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
82+
with:
83+
python-version: "3.13"
84+
85+
- name: Count the tests in the checkout
86+
run: |
87+
uv sync --all-extras
88+
count=$(uv run pytest --collect-only -q | grep -oE '[0-9]+ tests? collected' | grep -oE '^[0-9]+')
89+
echo "The checkout collects $count tests."
90+
echo "checkout_tests=$count" >> "$GITHUB_ENV"
91+
92+
- name: Build and unpack the sdist
93+
run: |
94+
uv build --sdist --out-dir dist
95+
mkdir -p "$RUNNER_TEMP/sdist"
96+
tar -xzf dist/*.tar.gz -C "$RUNNER_TEMP/sdist" --strip-components=1
97+
98+
- name: Check that the sdist ships every test
99+
working-directory: ${{ runner.temp }}/sdist
100+
run: |
101+
uv sync --all-extras
102+
count=$(uv run pytest --collect-only -q | grep -oE '[0-9]+ tests? collected' | grep -oE '^[0-9]+')
103+
echo "The sdist collects $count tests; the checkout collected $checkout_tests."
104+
if [ "$count" -lt "$checkout_tests" ]; then
105+
echo "::error::The sdist is missing tests. Add the missing paths to the include list in [tool.hatch.build.targets.sdist]."
106+
exit 1
107+
fi
108+
109+
- name: Run the tests from the sdist
110+
working-directory: ${{ runner.temp }}/sdist
111+
run: make test
112+
113+
- name: Verify typehints from the sdist
114+
working-directory: ${{ runner.temp }}/sdist
115+
run: make lint
116+
117+
# start-contract-test-service depends on install-contract-tests-deps, and
118+
# the -bg target backgrounds the whole chain. Without a blocking install
119+
# first, the dependency sync races the harness connecting to the service.
120+
- name: Install the contract test dependencies from the sdist
121+
working-directory: ${{ runner.temp }}/sdist
122+
run: make install-contract-tests-deps
123+
124+
- name: Start the SSE contract test service from the sdist
125+
working-directory: ${{ runner.temp }}/sdist
126+
run: make start-contract-test-service-bg
127+
128+
- name: Run SSE contract tests against the sdist
129+
uses: launchdarkly/gh-actions/actions/contract-tests@contract-tests-v1
130+
with:
131+
repo: sse-contract-tests
132+
branch: main
133+
version: v2
134+
test_service_port: 8000
135+
enable_persistence_tests: "false"
136+
debug_logging: "true"
137+
token: ${{ secrets.GITHUB_TOKEN }}
138+
139+
- name: Start the async SSE contract test service from the sdist
140+
working-directory: ${{ runner.temp }}/sdist
141+
run: make start-async-contract-test-service-bg
142+
143+
- name: Run async SSE contract tests against the sdist
144+
uses: launchdarkly/gh-actions/actions/contract-tests@contract-tests-v1
145+
with:
146+
repo: sse-contract-tests
147+
branch: main
148+
version: v2
149+
test_service_port: 8001
150+
enable_persistence_tests: "false"
151+
debug_logging: "true"
152+
token: ${{ secrets.GITHUB_TOKEN }}
153+
69154
windows:
70155
runs-on: windows-latest
71156

‎pyproject.toml‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,20 @@ build-backend = "hatchling.build"
7474
[tool.hatch.build.targets.wheel]
7575
packages = ["ld_eventsource"]
7676
exclude = ["ld_eventsource/testing"]
77+
78+
# An allowlist, so that a new repository-management file cannot leak into the
79+
# sdist by default. The CI sdist job proves the list is complete: it builds the
80+
# sdist, unpacks it, and fails if fewer tests collect there than in the
81+
# checkout. Hatchling force-includes pyproject.toml, README.md, LICENSE,
82+
# PKG-INFO and .gitignore whatever this says, so the sdist always builds.
83+
[tool.hatch.build.targets.sdist]
84+
include = [
85+
"/ld_eventsource",
86+
"/contract-tests",
87+
"/docs",
88+
"/Makefile",
89+
"/setup.cfg",
90+
"/CHANGELOG.md",
91+
"/CONTRIBUTING.md",
92+
"/SECURITY.md",
93+
]

0 commit comments

Comments
 (0)