@@ -46,6 +46,10 @@ graph TD
4646 A --> C[Parse Release Intent]
4747 B --> C
4848
49+ B --> B1[Check Dockerfile]
50+ B1 -->|Exists| B2[Enable Docker Jobs]
51+ B1 -->|Missing| B3[Skip Docker Jobs]
52+
4953 C --> D[Version Bump]
5054 B --> E[Config Outputs]
5155 E --> F[Docker Registry URLs]
@@ -57,8 +61,10 @@ graph TD
5761 D --> K[Documentation]
5862
5963 I --> L[PyPI via OIDC]
64+ B2 --> J
6065 J --> M[Docker Hub - Config Based]
6166 J --> N[GitHub Container Registry - Config Based]
67+ B3 -.->|Skipped| J
6268 K --> O[Docusaurus Versioning - Config Based]
6369
6470 I & J & K --> P[Supply Chain Security]
@@ -82,7 +88,26 @@ config:
8288- Auto-detects project name and package name from repository and `pyproject.toml`
8389- Applies smart defaults for missing configuration sections
8490
85- **Step 2: Release Intent Analysis**
91+ **Step 2: Dockerfile Detection** 🆕
92+ ` ` ` yaml
93+ check-dockerfile:
94+ name: Check Dockerfile Exists
95+ runs-on: ubuntu-latest
96+ steps:
97+ - name: Check for Dockerfile
98+ run: |
99+ if [ -f "Dockerfile" ]; then
100+ echo "has_dockerfile=true" >> $GITHUB_OUTPUT
101+ else
102+ echo "has_dockerfile=false" >> $GITHUB_OUTPUT
103+ fi
104+ ` ` `
105+ - Checks for `Dockerfile` in repository root
106+ - Sets `has_dockerfile` output for downstream Docker jobs
107+ - Enables conditional execution of all Docker-related processes
108+ - Provides clear logging for Docker availability
109+
110+ **Step 3: Release Intent Analysis**
86111` ` ` yaml
87112intent:
88113 uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_release_intent.yaml@master
@@ -104,17 +129,20 @@ intent:
104129 - Builds from correct bumped version (e.g., 0.0.1, not 0.0.0)
105130
1061312. **Docker Image** (`GHCR` & `DockerHub`) - **Config Enhanced** :
132+ - **Automatic Dockerfile Detection**: 🆕 Detects Dockerfile presence; gracefully skips all Docker processes if not found
133+ - **Conditional Execution**: Docker jobs only run when both a Dockerfile exists AND configuration allows it
107134 - **Config-Based Registry URLs**:
108135 - **Docker Hub**: Uses `${{ needs.config.outputs.docker_registry_dockerhub }}`
109136 - **GHCR**: Uses `${{ needs.config.outputs.docker_registry_ghcr }}`
110137 - **Health Check Configuration**: Uses config-based `${{ needs.config.outputs.docker_health_check_path }}` and `${{ needs.config.outputs.docker_health_check_port }}`
111138 - **Application Environment**: Uses `${{ needs.config.outputs.docker_app_env_name }}` and `${{ needs.config.outputs.docker_app_env_value }}`
112- - **Dual Registry Publishing**: Publishes to both registries simultaneously
139+ - **Dual Registry Publishing**: Publishes to both registries simultaneously (when Dockerfile exists)
113140 - **Parallel Publishing Jobs**: Separate jobs ensure isolated registry operations
114141 - **Multi-architecture builds**: amd64, arm64 support for both registries
115142 - **Supply Chain Security**: SBOM generation, Cosign signing, SLSA attestation
116143 - **Registry-Specific Authentication**: GHCR uses GitHub token, Docker Hub uses dedicated credentials
117144 - **Consistent Tagging**: Same version tags applied to both registries
145+ - **Smart Summaries**: Workflow outputs clearly indicate Docker skipped vs published
118146 - **Fixed**: Uses correct version tags from git sync fix
119147
1201483. **Documentation** (`Docusaurus`) - **Config Enhanced** :
@@ -159,10 +187,15 @@ graph TD
159187 A --> C[Parse Release Intent]
160188 B --> C
161189
190+ B --> B1[Check Dockerfile]
191+ B1 -->|Exists| B2[Run Docker Validation]
192+ B1 -->|Missing| B3[Skip Docker Validation]
193+
162194 C --> D[Python Build Check]
163- C --> E[Docker Build & Test - Config Based]
195+ B2 --> E[Docker Build & Test - Config Based]
196+ B3 -.->|Skipped| E
164197 C --> F[Docs Build Test - Config Based]
165- C --> G[Supply Chain Security]
198+ E --> G[Supply Chain Security]
166199
167200 B --> H[Config Validation]
168201 H --> I[Registry URL Validation]
@@ -174,6 +207,8 @@ graph TD
174207 G --> N[Security Attestation]
175208
176209 D & E & F & G & H --> O[Enhanced Validation Summary]
210+ O -->|No Dockerfile| P[Docker Skipped Status]
211+ O -->|Has Dockerfile| Q[Docker Validated Status]
177212` ` `
178213
179214**Step-by-Step Enhanced Validation:**
@@ -190,7 +225,19 @@ config:
190225- Validates Docker registry URLs and health check configurations
191226- Confirms documentation path accessibility
192227
193- **Step 2: Release Intent Validation**
228+ **Step 2: Dockerfile Detection** 🆕
229+ ` ` ` yaml
230+ check-dockerfile:
231+ name: Check Dockerfile Exists
232+ outputs:
233+ has_dockerfile: ${{ steps.check.outputs.has_dockerfile }}
234+ ` ` `
235+ - Detects Dockerfile presence in repository root
236+ - Determines whether Docker validation should run
237+ - Outputs boolean flag for conditional job execution
238+ - Enables graceful skipping for Python-only projects
239+
240+ **Step 3: Release Intent Validation**
194241` ` ` yaml
195242intent-parse:
196243 uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_release_intent.yaml@master
@@ -202,10 +249,13 @@ intent-parse:
202249
203250# ### Enhanced Security Validation
204251
252+ - **Automatic Dockerfile Detection**: 🆕 Checks for Dockerfile presence; skips Docker validation if not found
253+ - **Conditional Docker Validation**: Docker build tests and security scans only run when Dockerfile exists
205254- **Defensive Checks**: Pre-flight image existence validation
206255- **Vulnerability Scanning**: Grype integration for CVE detection
207256- **Fallback SBOM**: Workspace scanning if Docker image scan fails
208257- **Supply Chain Security**: Full SBOM, signing, and attestation testing
258+ - **Flexible Validation**: Works for both Docker-based and Python-only projects
209259
210260# ## 3. Staging Release Workflow (`release-staging.yml`)
211261
@@ -224,12 +274,19 @@ graph TD
224274 A --> C[Compute Staging Version]
225275 B --> C
226276
277+ B --> B1[Check Dockerfile]
278+ B1 -->|Exists| B2[Build Docker RC Images]
279+ B1 -->|Missing| B3[Skip Docker RC]
280+
227281 C --> D[Staging Python Package]
228282 C --> E[Staging Docker Images]
229283 C --> F[Staging Documentation]
230284
231285 D --> G[TestPyPI - Config Based]
232- E --> H[GHCR Staging - Config Based]
286+ B2 --> E
287+ E --> H1[DockerHub RC - Config Based]
288+ E --> H2[GHCR RC - Config Based]
289+ B3 -.->|Skipped| E
233290 F --> I[Preview Branch - Config Based]
234291
235292 B --> J[Config Outputs]
@@ -250,7 +307,19 @@ config:
250307- Provides validation version settings : ` ${{ needs.config.outputs.validation_version }}` and `${{ needs.config.outputs.validation_test_version }}`
251308- Configures preview documentation branch : ` ${{ needs.config.outputs.docs_preview_branch }}`
252309
253- **Step 2: Staging Version Computation**
310+ **Step 2: Dockerfile Detection** 🆕
311+ ` ` ` yaml
312+ check-dockerfile:
313+ name: Check Dockerfile Exists
314+ outputs:
315+ has_dockerfile: ${{ steps.check.outputs.has_dockerfile }}
316+ ` ` `
317+ - Checks for Dockerfile in repository root
318+ - Controls Docker RC image builds for both DockerHub and GHCR
319+ - Enables Python-only projects to skip Docker staging
320+ - Provides clear feedback in staging summary
321+
322+ **Step 3: Staging Version Computation**
254323- Uses config-based validation version format
255324- Creates release candidate versions with config-provided settings
256325- Integrates with git configuration from config outputs
@@ -261,10 +330,12 @@ config:
261330 - Pre-release Python packages using `${{ needs.config.outputs.validation_version }}`
262331 - Git commits with `${{ needs.config.outputs.git_commit_name }}` and `${{ needs.config.outputs.git_commit_email }}`
263332
264- 2. **GHCR Staging** - **Config Enhanced** :
265- - Docker images with `-rc` tags using `${{ needs.config.outputs.docker_registry_ghcr }}`
333+ 2. **Docker Staging (DockerHub & GHCR)** - **Config Enhanced** :
334+ - **Automatic Dockerfile Detection**: 🆕 RC images only built if Dockerfile exists in repository
335+ - Docker images with `-rc` tags using `${{ needs.config.outputs.docker_registry_dockerhub }}` and `${{ needs.config.outputs.docker_registry_ghcr }}`
266336 - Health check validation using config-based `${{ needs.config.outputs.docker_health_check_path }}` and `${{ needs.config.outputs.docker_health_check_port }}`
267337 - Application environment testing with `${{ needs.config.outputs.docker_app_env_name }}` and `${{ needs.config.outputs.docker_app_env_value }}`
338+ - Gracefully skips if no Dockerfile present
268339
2693403. **Documentation Preview** - **Config Enhanced** :
270341 - Staging documentation branch using `${{ needs.config.outputs.docs_preview_branch }}`
@@ -332,6 +403,7 @@ graph LR
332403✅ **Validated** : Comprehensive pre-release validation
333404✅ **Staged** : Safe staging environment testing
334405✅ **Multi-Target** : Python, Docker, and docs deployment
406+ ✅ **Flexible** : 🆕 Automatic Dockerfile detection - works for both Docker-based and Python-only projects
335407✅ **Efficient** : Matrix-based concurrent processing
336408✅ **Robust** : Fallback mechanisms and defensive checks
337409
@@ -1332,6 +1404,32 @@ artifacts:
13321404 docker: skip # Skips both registries
13331405` ` `
13341406
1407+ :::tip Automatic Dockerfile Detection
1408+ **New Feature**: All release workflows now automatically detect the presence of a `Dockerfile` in the repository root. If no Dockerfile is found, all Docker-related processes are gracefully skipped, regardless of the `docker` configuration setting.
1409+
1410+ **Smart Behavior:**
1411+ - ✅ **Dockerfile exists** : Docker processes run based on `docker` configuration (`auto`, `force`, `skip`)
1412+ - ⚠️ **No Dockerfile** : Docker processes are automatically skipped with clear logging
1413+ - 📋 **Summary output** : Workflow summaries clearly indicate when Docker was skipped due to missing Dockerfile
1414+
1415+ **Affected Workflows:**
1416+ - **Production Release** (`release.yml`): Skips Docker Hub and GHCR publishing
1417+ - **Validation** (`release-validate.yml`): Skips Docker build validation and security scanning
1418+ - **Staging** (`release-staging.yml`): Skips Docker Hub and GHCR RC image publishing
1419+
1420+ **Example Workflow Output:**
1421+ ```
1422+ === Release Summary ===
1423+ Dockerfile Check: ⚠️ Not Found (Docker skipped)
1424+ Python Package: ✅ Published to PyPI
1425+ DockerHub Build: ⏭️ Skipped (no Dockerfile)
1426+ GHCR Build: ⏭️ Skipped (no Dockerfile)
1427+ Documentation: ✅ Versioned
1428+ ```
1429+
1430+ This allows the same template workflows to work seamlessly for Python-only projects without requiring any configuration changes.
1431+ :::
1432+
13351433:::info Dual Registry Publishing Details
13361434When `docker: auto` or `docker: force`, the workflow creates **two parallel jobs**:
13371435
@@ -1448,15 +1546,21 @@ notes: "Documentation update release"
14481546
14491547# ## Behavioral Matrix
14501548
1451- | Configuration | Changed Files | Behavior |
1452- |---------------|---------------|----------|
1453- | `python : auto` | Python files changed | ✅ Publishes to PyPI |
1454- | `python : auto` | No Python files changed | ⏭️ Skips publishing |
1455- | `python : force` | Any/no changes | ✅ Always publishes |
1456- | `python : skip` | Any/no changes | ⏭️ Always skips |
1457- | `docs.mode : auto, strategy: changed` | Docs files changed | ✅ Versions changed sections |
1458- | `docs.mode : auto, strategy: always` | Any changes | ✅ Versions all sections |
1459- | `docs.mode : force` | Any/no changes | ✅ Always versions |
1549+ | Configuration | Dockerfile Exists | Changed Files | Behavior |
1550+ |---------------|-------------------|---------------|----------|
1551+ | `python : auto` | N/A | Python files changed | ✅ Publishes to PyPI |
1552+ | `python : auto` | N/A | No Python files changed | ⏭️ Skips publishing |
1553+ | `python : force` | N/A | Any/no changes | ✅ Always publishes |
1554+ | `python : skip` | N/A | Any/no changes | ⏭️ Always skips |
1555+ | `docker : auto` | ✅ Yes | Docker files changed | ✅ Publishes to registries |
1556+ | `docker : auto` | ✅ Yes | No Docker files changed | ⏭️ Skips publishing |
1557+ | `docker : auto` | ❌ No | Any/no changes | ⏭️ Skips (no Dockerfile) |
1558+ | `docker : force` | ✅ Yes | Any/no changes | ✅ Always publishes |
1559+ | `docker : force` | ❌ No | Any/no changes | ⏭️ Skips (no Dockerfile) |
1560+ | `docker : skip` | Any | Any/no changes | ⏭️ Always skips |
1561+ | `docs.mode : auto, strategy: changed` | N/A | Docs files changed | ✅ Versions changed sections |
1562+ | `docs.mode : auto, strategy: always` | N/A | Any changes | ✅ Versions all sections |
1563+ | `docs.mode : force` | N/A | Any/no changes | ✅ Always versions |
14601564
14611565# ## Configuration Validation
14621566
0 commit comments