ci-cd-playground 0.1.16__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,15 @@
1
+ """ci_cd_playground package."""
2
+
3
+ from ci_cd_playground.app import app, create_app
4
+
5
+ __all__ = ["add", "app", "create_app", "hello"]
6
+
7
+
8
+ def hello(name: str = "world") -> str:
9
+ """Return a greeting message."""
10
+ return f"Hello, {name}!"
11
+
12
+
13
+ def add(a: int | float, b: int | float) -> int | float:
14
+ """Add two numbers."""
15
+ return a + b
@@ -0,0 +1,41 @@
1
+ """FastAPI application for ci_cd_playground."""
2
+
3
+ import os
4
+
5
+ from fastapi import FastAPI
6
+
7
+
8
+ def create_app() -> FastAPI:
9
+ """Create and configure the FastAPI application."""
10
+ application = FastAPI(
11
+ title="CI/CD Playground API",
12
+ description="A minimal FastAPI application.",
13
+ version="0.1.1",
14
+ )
15
+
16
+ @application.get("/")
17
+ def read_root() -> dict[str, str]:
18
+ """Root endpoint returning a greeting."""
19
+ return {"message": "Hello, world!"}
20
+
21
+ @application.get("/health")
22
+ def health_check() -> dict[str, str]:
23
+ """Health check endpoint."""
24
+ return {"status": "ok"}
25
+
26
+ @application.get("/version")
27
+ def version() -> dict[str, str]:
28
+ return {
29
+ "version": os.getenv("APP_VERSION", "unknown"),
30
+ "commit": os.getenv("GIT_SHA", "unknown"),
31
+ }
32
+
33
+ @application.get("/hello/{name}")
34
+ def greet(name: str) -> dict[str, str]:
35
+ """Greeting endpoint accepting a path parameter."""
36
+ return {"message": f"Hello, {name}!"}
37
+
38
+ return application
39
+
40
+
41
+ app = create_app()
File without changes
@@ -0,0 +1,297 @@
1
+ Metadata-Version: 2.3
2
+ Name: ci-cd-playground
3
+ Version: 0.1.16
4
+ Summary: A sample Python project with uv, ruff, pyright, and pytest
5
+ Author: john
6
+ Author-email: john <96323078+JohnStephens1@users.noreply.github.com>
7
+ Requires-Dist: fastapi>=0.162.0
8
+ Requires-Dist: uvicorn>=0.54.0
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+
12
+ # ci-cd-playground
13
+
14
+ A Python project configured with [`uv`](https://docs.astral.sh/uv/), [`ruff`](https://docs.astral.sh/ruff/), [`pyright`](https://microsoft.github.io/pyright/), and [`pytest`](https://docs.pytest.org/), complete with GitHub Actions Continuous Integration (CI), Release automation, and automated publishing to TestPyPI.
15
+
16
+ ## Prerequisites
17
+
18
+ - [uv](https://docs.astral.sh/uv/getting-started/installation/) (v0.5+ recommended)
19
+
20
+ ## Quick Start
21
+
22
+ ### 1. Install Dependencies
23
+
24
+ Install all dependencies (including development tools) into a local virtual environment:
25
+
26
+ ```bash
27
+ uv sync
28
+ ```
29
+
30
+ ### 2. Run Quality Checks & Tests Locally
31
+
32
+ | Tool | Purpose | Command |
33
+ | :--- | :--- | :--- |
34
+ | **Ruff Check** | Linting and code style rules | `uv run ruff check .` |
35
+ | **Ruff Format** | Code formatting verification | `uv run ruff format --check .` |
36
+ | **Pyright** | Static type checking | `uv run pyright` |
37
+ | **Pytest** | Unit test suite | `uv run pytest` |
38
+ | **Build** | Build sdist and wheel | `uv build` |
39
+
40
+ To automatically fix lint violations or format code:
41
+
42
+ ```bash
43
+ # Format code
44
+ uv run ruff format .
45
+
46
+ # Auto-fix linting issues
47
+ uv run ruff check --fix .
48
+ ```
49
+
50
+ ### 3. Run the FastAPI Application
51
+
52
+ Start the local development server with auto-reload:
53
+
54
+ ```bash
55
+ uv run uvicorn ci_cd_playground:app --reload
56
+ ```
57
+
58
+ The API endpoints will be accessible at `http://127.0.0.1:8000/` and interactive Swagger docs at `http://127.0.0.1:8000/docs`.
59
+
60
+ ### 4. Build Distribution Packages
61
+
62
+ Build both the source distribution (`.tar.gz`) and wheel (`.whl`):
63
+
64
+ ```bash
65
+ uv build
66
+ ```
67
+
68
+ The output packages will be located in the `dist/` directory.
69
+
70
+ ## GitHub Actions Workflows
71
+
72
+ The repository organizes continuous integration and deployment into modular, decoupled workflows:
73
+
74
+ ### 1. Continuous Integration (CI) — [`.github/workflows/ci.yml`](.github/workflows/ci.yml)
75
+
76
+ Runs automatically on pushes and pull requests to `main`, and functions as a **reusable workflow** (`workflow_call`):
77
+
78
+ 1. **Lint & Format (Ruff)**: Verifies formatting and runs linting rules.
79
+ 2. **Type Check (Pyright)**: Validates static typing rules across `src/` and `tests/`.
80
+ 3. **Matrix Tests (Pytest)**: Runs the test suite across supported Python versions (`3.10`, `3.11`, `3.12`, `3.13`) using `astral-sh/setup-uv`.
81
+ 4. **Security Check (zizmor)**: Audits GitHub Actions workflows for security vulnerabilities and permissions issues.
82
+ 5. **Build (uv build)**: Builds source distributions and wheels, performs a smoke test by installing and importing the wheel in an isolated environment, and uploads build artifacts (`dist-packages`).
83
+
84
+ ### 2. Container Security — [`.github/workflows/container-security.yml`](.github/workflows/container-security.yml)
85
+
86
+ Runs on pull requests to `main` and via `workflow_call`:
87
+ - Builds the runtime Docker image.
88
+ - Scans for vulnerabilities with Trivy using repository ignore configurations.
89
+
90
+ ### 3. Docker Build & Publish — [`.github/workflows/docker-publish.yml`](.github/workflows/docker-publish.yml)
91
+
92
+ A **reusable workflow** (`workflow_call`) that encapsulates container lifecycle tasks:
93
+ 1. Builds the production image with `APP_VERSION` and `GIT_SHA` build arguments.
94
+ 2. Scans the container with Trivy for CRITICAL and HIGH severity issues.
95
+ 3. Starts the container locally and verifies `/health` response.
96
+ 4. Logs into GitHub Container Registry (GHCR) and publishes the tagged images (`${GITHUB_SHA}` and optional custom/release tag).
97
+
98
+ ### 4. Deploy Service — [`.github/workflows/deploy.yml`](.github/workflows/deploy.yml)
99
+
100
+ A **reusable deployment workflow** (`workflow_call`) that unifies Render deployment logic for all environments:
101
+ 1. Configures the target GitHub `environment` (e.g. `staging` or `production`), enabling environment protection rules, approvals, and secret isolation.
102
+ 2. Triggers Render deploy via REST API for the given service ID and image tag.
103
+ 3. Polls Render deployment status every 30s until `live` or failed.
104
+ 4. Verifies service availability via `/health` and validates that `/version` is running the expected commit SHA.
105
+
106
+ ### 5. Continuous Delivery (CD) — [`.github/workflows/cd.yml`](.github/workflows/cd.yml)
107
+
108
+ Triggers automatically on pushes to `main` and via manual `workflow_dispatch`:
109
+ 1. **CI Validation & Build**: Calls `ci.yml` to verify quality gates.
110
+ 2. **Docker Publish**: Calls `docker-publish.yml` to build, scan, test, and push the image to GHCR.
111
+ 3. **Deploy to Staging**: Automatically calls `deploy.yml` with `staging` settings and validates staging health.
112
+ 4. **Deploy to Production**: Calls `deploy.yml` with `production` settings. Can be gated with GitHub Environment manual approval rules or targeted selectively via manual dispatch.
113
+
114
+ ### 6. Package Build & Provenance (SLSA Level 3) — [`.github/workflows/package-build.yml`](.github/workflows/package-build.yml)
115
+
116
+ A **trusted reusable builder workflow** (`workflow_call`) that enforces isolation and build platform integrity to meet **SLSA v1.0 Build Level 3**:
117
+ 1. **Isolated Build**: Checks out the target commit and builds both distributions (`uv build --no-sources`) strictly once.
118
+ 2. **Artifact Identification**: Computes cryptographic SHA-256 digests for both the wheel (`.whl`) and sdist (`.tar.gz`), generating `checksums/SHA256SUMS`.
119
+ 3. **Individual SBOM Generation (Syft)**: Scans the actual built distributions independently with Syft to generate:
120
+ - Machine-readable SPDX 2.3 JSON: `package-wheel.spdx.json` and `package-sdist.spdx.json`
121
+ - Human-readable summary tables: `package-wheel.txt` and `package-sdist.txt`
122
+ 4. **SLSA Build Provenance Attestation**: Generates cryptographically signed SLSA provenance via `actions/attest` backed by Sigstore, bound to both distribution digests and exported to `attestations/package-provenance.intoto.jsonl`.
123
+ 5. **Individual SBOM Attestations**: Cryptographically signs each distribution's SBOM with `actions/attest`, binding the wheel SBOM to the wheel digest and the sdist SBOM to the sdist digest (`package-wheel-sbom.attestation.json` and `package-sdist-sbom.attestation.json`).
124
+ 6. **Immutable Artifact Preservation**: Uploads distributions, SBOMs, attestations, and checksums as GitHub Actions artifacts for downstream pipeline consumption.
125
+
126
+ ### 7. Release & PyPI/TestPyPI Publishing — [`.github/workflows/release.yml`](.github/workflows/release.yml)
127
+
128
+ Triggers whenever a version tag matching `v*` (e.g. `v0.1.0`) is pushed to the repository (or via manual `workflow_dispatch`):
129
+
130
+ 1. **Validate Release Reference**: Validates git tag syntax, verifies that the tag cryptographically resolves to the target commit SHA, and ensures the git tag matches `project.version` in `pyproject.toml`.
131
+ 2. **Build via Trusted Builder**: Invokes the isolated reusable workflow `package-build.yml` to produce immutable distributions, Syft SBOMs, SLSA Level 3 provenance, and SBOM attestations.
132
+ 3. **Test Built Distributions**: Installs the built wheel in an isolated `.venv-wheel` and the built sdist in an isolated `.venv-sdist`, verifying installations and import smoke-tests before promotion.
133
+ 4. **Comprehensive Automated Verification**:
134
+ - Verifies distribution checksums against `SHA256SUMS`.
135
+ - Verifies SLSA Build Provenance authenticity and subject digests online via GitHub API and offline using the bundled `.intoto.jsonl` file.
136
+ - Verifies individual SBOM attestations online and offline using `--predicate-type https://spdx.dev/Document/v2.3`.
137
+ - Validates that the builder signer workflow strictly matches `package-build.yml` (`--signer-workflow`).
138
+ 5. **Publish to TestPyPI**:
139
+ - Publishes verified distributions using Trusted Publishing (OIDC) via `uv publish --index testpypi`.
140
+ - Performs a smoke-test installation in a clean environment from TestPyPI.
141
+ 6. **Publish to PyPI**:
142
+ - Gated by the `pypi` environment (with optional environment protection / manual approval rules).
143
+ - Generates PEP 740 digital provenance attestations via `astral-sh/attest-action`.
144
+ - Publishes verified distributions to PyPI via `uv publish`.
145
+ 7. **Create GitHub Release**:
146
+ - Creates a GitHub Release with release notes and attaches:
147
+ - `dist/`: Wheel (`.whl`) and source distribution (`.tar.gz`)
148
+ - `sbom/`: SPDX JSON and readable text SBOMs (`package-wheel.spdx.json`, `package-sdist.spdx.json`, `package-wheel.txt`, `package-sdist.txt`)
149
+ - `attestations/`: `package-provenance.intoto.jsonl`, `package-wheel-sbom.attestation.json`, `package-sdist-sbom.attestation.json`
150
+ - `checksums/`: `SHA256SUMS`
151
+
152
+ #### Configuring PyPI & TestPyPI Trusted Publishing
153
+
154
+ 1. **TestPyPI**:
155
+ - Add a Pending Publisher on [TestPyPI](https://test.pypi.org/manage/account/publishing/) targeting your GitHub repository and workflow (`release.yml`), with environment name `testpypi`.
156
+ - Create a GitHub Environment named `testpypi` in repository settings (**Settings > Environments**).
157
+ 2. **Production PyPI**:
158
+ - Add a Publisher on [PyPI](https://pypi.org/manage/account/publishing/) targeting your GitHub repository and workflow (`release.yml`), with environment name `pypi`.
159
+ - Create a GitHub Environment named `pypi` in repository settings (**Settings > Environments**), optionally configuring required reviewers for manual release sign-off.
160
+
161
+ #### Creating a Release
162
+
163
+ ```bash
164
+ # 1. Bump version in pyproject.toml (e.g. 0.1.15)
165
+ uv version 0.1.15
166
+
167
+ # 2. Commit and tag
168
+ git commit -am "chore: release v0.1.15"
169
+ git tag v0.1.15
170
+
171
+ # 3. Push tag to GitHub to trigger the release workflow
172
+ git push origin v0.1.15
173
+ ```
174
+
175
+ ## Consumer Verification Guide
176
+
177
+ Consumers can independently verify the authenticity, integrity, SLSA Build Level 3 provenance, and SBOM attestations of released artifacts without trusting the build workflow's claims.
178
+
179
+ ### 1. Verify SHA-256 Checksums
180
+
181
+ Download the release assets into a local directory and verify the distribution digests:
182
+
183
+ ```bash
184
+ sha256sum -c SHA256SUMS
185
+ ```
186
+
187
+ ### 2. Verify SLSA Build Level 3 Provenance
188
+
189
+ Using the official [GitHub CLI](https://cli.github.com/) (`gh` v2.97.0+):
190
+
191
+ **Online Verification (via Sigstore transparency log):**
192
+
193
+ ```bash
194
+ # Verify wheel provenance
195
+ gh attestation verify ci_cd_playground-0.1.15-py3-none-any.whl \
196
+ --repo <OWNER>/ci-cd-playground \
197
+ --signer-workflow <OWNER>/ci-cd-playground/.github/workflows/package-build.yml
198
+
199
+ # Verify sdist provenance
200
+ gh attestation verify ci_cd_playground-0.1.15.tar.gz \
201
+ --repo <OWNER>/ci-cd-playground \
202
+ --signer-workflow <OWNER>/ci-cd-playground/.github/workflows/package-build.yml
203
+ ```
204
+
205
+ **Offline Verification (using the release attestation bundle):**
206
+
207
+ ```bash
208
+ gh attestation verify ci_cd_playground-0.1.15-py3-none-any.whl \
209
+ --bundle package-provenance.intoto.jsonl \
210
+ --repo <OWNER>/ci-cd-playground \
211
+ --signer-workflow <OWNER>/ci-cd-playground/.github/workflows/package-build.yml
212
+
213
+ gh attestation verify ci_cd_playground-0.1.15.tar.gz \
214
+ --bundle package-provenance.intoto.jsonl \
215
+ --repo <OWNER>/ci-cd-playground \
216
+ --signer-workflow <OWNER>/ci-cd-playground/.github/workflows/package-build.yml
217
+ ```
218
+
219
+ ### 3. Verify Individual SBOM Attestations
220
+
221
+ Verify that the SBOMs were cryptographically signed and bound to the exact distribution files:
222
+
223
+ **Wheel SBOM Attestation:**
224
+
225
+ ```bash
226
+ # Online
227
+ gh attestation verify ci_cd_playground-0.1.15-py3-none-any.whl \
228
+ --repo <OWNER>/ci-cd-playground \
229
+ --signer-workflow <OWNER>/ci-cd-playground/.github/workflows/package-build.yml \
230
+ --predicate-type https://spdx.dev/Document/v2.3
231
+
232
+ # Offline
233
+ gh attestation verify ci_cd_playground-0.1.15-py3-none-any.whl \
234
+ --bundle package-wheel-sbom.attestation.json \
235
+ --repo <OWNER>/ci-cd-playground \
236
+ --signer-workflow <OWNER>/ci-cd-playground/.github/workflows/package-build.yml \
237
+ --predicate-type https://spdx.dev/Document/v2.3
238
+ ```
239
+
240
+ **Sdist SBOM Attestation:**
241
+
242
+ ```bash
243
+ # Online
244
+ gh attestation verify ci_cd_playground-0.1.15.tar.gz \
245
+ --repo <OWNER>/ci-cd-playground \
246
+ --signer-workflow <OWNER>/ci-cd-playground/.github/workflows/package-build.yml \
247
+ --predicate-type https://spdx.dev/Document/v2.3
248
+
249
+ # Offline
250
+ gh attestation verify ci_cd_playground-0.1.15.tar.gz \
251
+ --bundle package-sdist-sbom.attestation.json \
252
+ --repo <OWNER>/ci-cd-playground \
253
+ --signer-workflow <OWNER>/ci-cd-playground/.github/workflows/package-build.yml \
254
+ --predicate-type https://spdx.dev/Document/v2.3
255
+ ```
256
+
257
+ ### 4. Inspect Software Bill of Materials (SBOM)
258
+
259
+ Inspect the Syft-generated human-readable summary or machine-readable SPDX JSON:
260
+
261
+ ```bash
262
+ # Human-readable table summary
263
+ cat package-wheel.txt
264
+ cat package-sdist.txt
265
+
266
+ # Query packages in SPDX JSON with jq
267
+ jq '.packages[] | {name: .name, versionInfo: .versionInfo}' package-wheel.spdx.json
268
+ ```
269
+
270
+ ## Project Structure
271
+
272
+ ```text
273
+ ci-cd-playground/
274
+ ├── .github/
275
+ │ └── workflows/
276
+ │ ├── cd.yml # Continuous delivery pipeline (main -> staging -> production)
277
+ │ ├── ci.yml # Reusable CI workflow (lint, typecheck, test, build)
278
+ │ ├── container-security.yml # Container build & Trivy scan on PRs
279
+ │ ├── deploy.yml # Reusable Render deployment workflow
280
+ │ ├── docker-publish.yml # Reusable Docker build, test & GHCR publish
281
+ │ ├── package-build.yml # Reusable SLSA Level 3 builder (uv build, Syft SBOMs, attestations)
282
+ │ └── release.yml # Release pipeline (validation, build, test, verify, TestPyPI, PyPI, GitHub)
283
+ ├── src/
284
+ │ └── ci_cd_playground/
285
+ │ ├── __init__.py # Package entrypoint and sample code
286
+ │ ├── app.py # Minimal FastAPI application
287
+ │ └── py.typed # PEP 561 typing marker
288
+ ├── tests/
289
+ │ ├── __init__.py
290
+ │ ├── test_app.py # FastAPI endpoint and factory tests
291
+ │ └── test_ci_test.py # Base unit tests
292
+ ├── .gitignore
293
+ ├── .python-version # Default local Python version
294
+ ├── pyproject.toml # Project configuration, dependencies, and tool settings
295
+ ├── uv.lock # Deterministic dependency lockfile
296
+ └── README.md
297
+ ```
@@ -0,0 +1,6 @@
1
+ ci_cd_playground/__init__.py,sha256=Dz6AHaUoHOP4WWc1SqjJOrvzgescMYfYL_ub3lhGg7I,340
2
+ ci_cd_playground/app.py,sha256=mL-uzWFOzi1nyBrmPw4nfsfZtJtMGTL8HQI0v6kQH14,1076
3
+ ci_cd_playground/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ ci_cd_playground-0.1.16.dist-info/WHEEL,sha256=3OmCxFA0ffBIsX4x0o8CdfSvZAOvO3mzEG8U_z5TvV4,80
5
+ ci_cd_playground-0.1.16.dist-info/METADATA,sha256=NvrHIFaFT9LbaZmti7AKOdlxg9PZaoY4wD4_OpdiolY,14474
6
+ ci_cd_playground-0.1.16.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.13.8
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any