diff --git a/.github/workflows/rw_release_complete.yaml b/.github/workflows/rw_release_complete.yaml index e959ce5..ff13c91 100644 --- a/.github/workflows/rw_release_complete.yaml +++ b/.github/workflows/rw_release_complete.yaml @@ -55,7 +55,7 @@ on: value: ${{ jobs.intent.outputs.python != 'skip' && jobs.intent.outputs.do_release == 'true' }} docker_released: description: 'Whether Docker images were released' - value: ${{ jobs.intent.outputs.docker != 'skip' && jobs.intent.outputs.do_release == 'true' }} + value: ${{ jobs.check-dockerfile.outputs.has_dockerfile == 'true' && jobs.intent.outputs.docker != 'skip' && jobs.intent.outputs.do_release == 'true' }} docs_released: description: 'Whether documentation was versioned' value: ${{ jobs.prepare_docs_matrix.outputs.has_sections == 'true' && jobs.intent.outputs.do_release == 'true' }} @@ -71,6 +71,26 @@ jobs: name: Parse Configuration uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_project_config.yaml@master + check-dockerfile: + name: Check Dockerfile Exists + runs-on: ubuntu-latest + outputs: + has_dockerfile: ${{ steps.check.outputs.has_dockerfile }} + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Check for Dockerfile + id: check + run: | + if [ -f "Dockerfile" ]; then + echo "✅ Dockerfile found" + echo "has_dockerfile=true" >> $GITHUB_OUTPUT + else + echo "⚠️ No Dockerfile found - Docker processes will be skipped" + echo "has_dockerfile=false" >> $GITHUB_OUTPUT + fi + intent: uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_release_intent.yaml@master needs: config @@ -376,8 +396,8 @@ jobs: release_docker_hub: name: Release to DockerHub uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_docker_operations.yaml@master - needs: [config, intent, bump_version, build_git-tag_and_create_github-release] - if: needs.intent.outputs.do_release == 'true' && needs.intent.outputs.docker != 'skip' + needs: [config, check-dockerfile, intent, bump_version, build_git-tag_and_create_github-release] + if: needs.check-dockerfile.outputs.has_dockerfile == 'true' && needs.intent.outputs.do_release == 'true' && needs.intent.outputs.docker != 'skip' secrets: dockerhub-user: ${{ secrets.DOCKERHUB_USERNAME }} registry-token: ${{ secrets.DOCKERHUB_TOKEN }} @@ -393,8 +413,8 @@ jobs: release_docker_ghcr: name: Release to GHCR uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_docker_operations.yaml@master - needs: [config, intent, bump_version, build_git-tag_and_create_github-release] - if: needs.intent.outputs.do_release == 'true' && needs.intent.outputs.docker != 'skip' + needs: [config, check-dockerfile, intent, bump_version, build_git-tag_and_create_github-release] + if: needs.check-dockerfile.outputs.has_dockerfile == 'true' && needs.intent.outputs.do_release == 'true' && needs.intent.outputs.docker != 'skip' with: operation: 'push' registry: ${{ needs.config.outputs.docker_registry_ghcr }} diff --git a/.github/workflows/rw_release_staging_complete.yaml b/.github/workflows/rw_release_staging_complete.yaml index c102bb1..92c88cf 100644 --- a/.github/workflows/rw_release_staging_complete.yaml +++ b/.github/workflows/rw_release_staging_complete.yaml @@ -45,6 +45,26 @@ jobs: name: Parse Configuration uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_project_config.yaml@master + check-dockerfile: + name: Check Dockerfile Exists + runs-on: ubuntu-latest + outputs: + has_dockerfile: ${{ steps.check.outputs.has_dockerfile }} + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Check for Dockerfile + id: check + run: | + if [ -f "Dockerfile" ]; then + echo "✅ Dockerfile found" + echo "has_dockerfile=true" >> $GITHUB_OUTPUT + else + echo "⚠️ No Dockerfile found - Docker processes will be skipped" + echo "has_dockerfile=false" >> $GITHUB_OUTPUT + fi + compute-version: name: Compute Staging Version runs-on: ubuntu-latest @@ -118,7 +138,8 @@ jobs: dockerhub-rc: name: Staging Release to DockerHub uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_docker_operations.yaml@master - needs: [config, compute-version, build_git-tag_and_create_github-release] + needs: [config, check-dockerfile, compute-version, build_git-tag_and_create_github-release] + if: needs.check-dockerfile.outputs.has_dockerfile == 'true' secrets: dockerhub-user: ${{ secrets.DOCKERHUB_USERNAME }} registry-token: ${{ secrets.DOCKERHUB_TOKEN }} @@ -136,7 +157,8 @@ jobs: ghcr-rc: name: Staging Release to GHCR uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_docker_operations.yaml@master - needs: [config, compute-version, build_git-tag_and_create_github-release] + needs: [config, check-dockerfile, compute-version, build_git-tag_and_create_github-release] + if: needs.check-dockerfile.outputs.has_dockerfile == 'true' with: operation: 'push' registry: ${{ needs.config.outputs.docker_registry_ghcr }} @@ -161,7 +183,7 @@ jobs: staging-summary: name: Staging Release Summary runs-on: ubuntu-latest - needs: [config, compute-version, pypi-test, ghcr-rc, docs-preview] + needs: [config, check-dockerfile, compute-version, pypi-test, dockerhub-rc, ghcr-rc, docs-preview] if: always() outputs: success: ${{ steps.summary.outputs.success }} @@ -171,37 +193,81 @@ jobs: run: | echo "=== Staging Release Summary ===" echo "" + echo "Dockerfile Check: ${{ needs.check-dockerfile.outputs.has_dockerfile == 'true' && '✅ Found' || '⚠️ Not Found (Docker skipped)' }}" echo "Version Computation: ${{ needs.compute-version.result }}" echo "TestPyPI Upload: ${{ needs.pypi-test.result }}" - echo "GHCR RC Image: ${{ needs.ghcr-rc.result }}" + + # Check if Docker processes were run + HAS_DOCKERFILE="${{ needs.check-dockerfile.outputs.has_dockerfile }}" + if [ "$HAS_DOCKERFILE" = "true" ]; then + echo "DockerHub RC Image: ${{ needs.dockerhub-rc.result }}" + echo "GHCR RC Image: ${{ needs.ghcr-rc.result }}" + else + echo "DockerHub RC Image: ⏭️ Skipped (no Dockerfile)" + echo "GHCR RC Image: ⏭️ Skipped (no Dockerfile)" + fi + echo "Docs Preview: ${{ needs.docs-preview.result }}" echo "" echo "📦 Staging Artifacts:" echo "- Base Version: ${{ needs.compute-version.outputs.version }}" echo "- RC Version: ${{ needs.compute-version.outputs.rc_version }}" echo "- TestPyPI: https://test.pypi.org/project/${{ needs.config.outputs.project_name }}/${{ needs.compute-version.outputs.version }}/" - echo "- GHCR RC Image: ghcr.io/${{ github.repository }}:${{ needs.compute-version.outputs.rc_version }}" + + if [ "$HAS_DOCKERFILE" = "true" ]; then + echo "- DockerHub RC Image: docker.io/${{ github.repository }}:${{ needs.compute-version.outputs.rc_version }}" + echo "- GHCR RC Image: ghcr.io/${{ github.repository }}:${{ needs.compute-version.outputs.rc_version }}" + fi + echo "- Docs Preview: docs-preview branch" echo "" - if [[ "${{ needs.compute-version.result }}" == "success" && \ - "${{ needs.pypi-test.result }}" == "success" && \ - "${{ needs.ghcr-rc.result }}" == "success" && \ - "${{ needs.docs-preview.result }}" == "success" ]]; then - echo "✅ Staging release completed successfully!" - echo "success=true" >> $GITHUB_OUTPUT - echo "" - echo "🧪 Testing Instructions:" - echo "1. Install from TestPyPI:" - echo " pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ ${{ needs.config.outputs.project_name }}==${{ needs.compute-version.outputs.version }}" - echo "" - echo "2. Test RC Docker image:" - echo " docker run -p ${{ needs.config.outputs.docker_health_check_port }}:${{ needs.config.outputs.docker_health_check_port }} ${{ needs.config.outputs.docker_run_options }} ghcr.io/${{ github.repository }}:${{ needs.compute-version.outputs.rc_version }}" - echo "" - echo "3. Review documentation preview in docs-preview branch" - echo "" + # Validate results based on whether Docker processes were expected + VERSION_OK="${{ needs.compute-version.result == 'success' }}" + PYPI_OK="${{ needs.pypi-test.result == 'success' }}" + DOCS_OK="${{ needs.docs-preview.result == 'success' }}" + + if [ "$HAS_DOCKERFILE" = "true" ]; then + # Docker processes should have run - validate them + DOCKERHUB_OK="${{ needs.dockerhub-rc.result == 'success' }}" + GHCR_OK="${{ needs.ghcr-rc.result == 'success' }}" + + if [[ "$VERSION_OK" == "true" && "$PYPI_OK" == "true" && \ + "$DOCKERHUB_OK" == "true" && "$GHCR_OK" == "true" && "$DOCS_OK" == "true" ]]; then + echo "✅ Staging release completed successfully!" + echo "success=true" >> $GITHUB_OUTPUT + echo "" + echo "🧪 Testing Instructions:" + echo "1. Install from TestPyPI:" + echo " pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ ${{ needs.config.outputs.project_name }}==${{ needs.compute-version.outputs.version }}" + echo "" + echo "2. Test RC Docker images:" + echo " docker run -p ${{ needs.config.outputs.docker_health_check_port }}:${{ needs.config.outputs.docker_health_check_port }} ${{ needs.config.outputs.docker_run_options }} ghcr.io/${{ github.repository }}:${{ needs.compute-version.outputs.rc_version }}" + echo " docker run -p ${{ needs.config.outputs.docker_health_check_port }}:${{ needs.config.outputs.docker_health_check_port }} ${{ needs.config.outputs.docker_run_options }} docker.io/${{ github.repository }}:${{ needs.compute-version.outputs.rc_version }}" + echo "" + echo "3. Review documentation preview in docs-preview branch" + echo "" + else + echo "❌ Some staging deployment steps failed. Check the logs above." + echo "success=false" >> $GITHUB_OUTPUT + exit 1 + fi else - echo "❌ Some staging deployment steps failed. Check the logs above." - echo "success=false" >> $GITHUB_OUTPUT - exit 1 + # No Docker processes - only validate non-Docker components + if [[ "$VERSION_OK" == "true" && "$PYPI_OK" == "true" && "$DOCS_OK" == "true" ]]; then + echo "✅ Staging release completed successfully!" + echo "⚠️ Note: Docker builds were skipped (no Dockerfile found)" + echo "success=true" >> $GITHUB_OUTPUT + echo "" + echo "🧪 Testing Instructions:" + echo "1. Install from TestPyPI:" + echo " pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ ${{ needs.config.outputs.project_name }}==${{ needs.compute-version.outputs.version }}" + echo "" + echo "2. Review documentation preview in docs-preview branch" + echo "" + else + echo "❌ Some staging deployment steps failed. Check the logs above." + echo "success=false" >> $GITHUB_OUTPUT + exit 1 + fi fi diff --git a/.github/workflows/rw_release_validation_complete.yaml b/.github/workflows/rw_release_validation_complete.yaml index 25a5ecb..40ce25f 100644 --- a/.github/workflows/rw_release_validation_complete.yaml +++ b/.github/workflows/rw_release_validation_complete.yaml @@ -37,13 +37,13 @@ on: value: ${{ jobs.python-build-check.result }} docker_validated: description: 'Docker validation result' - value: ${{ jobs.docker-build-dockerhub.result == 'success' && jobs.docker-build-ghcr.result == 'success' }} + value: ${{ jobs.check-dockerfile.outputs.has_dockerfile == 'true' && jobs.docker-build-dockerhub.result == 'success' && jobs.docker-build-ghcr.result == 'success' || jobs.check-dockerfile.outputs.has_dockerfile == 'false' }} docs_validated: description: 'Documentation validation result' value: ${{ jobs.docs-build.result }} security_validated: description: 'Security validation result' - value: ${{ jobs.supply-chain-loopback.result }} + value: ${{ jobs.check-dockerfile.outputs.has_dockerfile == 'true' && jobs.supply-chain-loopback.result == 'success' || jobs.check-dockerfile.outputs.has_dockerfile == 'false' }} permissions: contents: read @@ -56,6 +56,26 @@ jobs: name: Parse Configuration uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_project_config.yaml@master + check-dockerfile: + name: Check Dockerfile Exists + runs-on: ubuntu-latest + outputs: + has_dockerfile: ${{ steps.check.outputs.has_dockerfile }} + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Check for Dockerfile + id: check + run: | + if [ -f "Dockerfile" ]; then + echo "✅ Dockerfile found" + echo "has_dockerfile=true" >> $GITHUB_OUTPUT + else + echo "⚠️ No Dockerfile found - Docker processes will be skipped" + echo "has_dockerfile=false" >> $GITHUB_OUTPUT + fi + intent-parse: uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_parse_release_intent.yaml@master needs: config @@ -85,7 +105,8 @@ jobs: docker-build-dockerhub: name: Validate DockerHub Build uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_docker_operations.yaml@master - needs: [config, build_git-tag_and_create_github-release] + needs: [config, check-dockerfile, build_git-tag_and_create_github-release] + if: needs.check-dockerfile.outputs.has_dockerfile == 'true' with: operation: 'test' registry: ${{ needs.config.outputs.docker_registry_dockerhub }} @@ -99,7 +120,8 @@ jobs: docker-build-ghcr: name: Validate GHCR Build uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_docker_operations.yaml@master - needs: [config, build_git-tag_and_create_github-release] + needs: [config, check-dockerfile, build_git-tag_and_create_github-release] + if: needs.check-dockerfile.outputs.has_dockerfile == 'true' with: operation: 'test' registry: ${{ needs.config.outputs.docker_registry_ghcr }} @@ -120,7 +142,8 @@ jobs: supply-chain-loopback: name: Security Scan (Supply Chain) uses: Chisanan232/Template-Python-UV-Project/.github/workflows/rw_docker_operations.yaml@master - needs: [config, docker-build-dockerhub, docker-build-ghcr] + needs: [config, check-dockerfile, docker-build-dockerhub, docker-build-ghcr] + if: needs.check-dockerfile.outputs.has_dockerfile == 'true' with: operation: 'security-scan' registry: ${{ needs.config.outputs.docker_registry_dockerhub }} # Use DockerHub build for security scan @@ -133,7 +156,7 @@ jobs: validation-summary: name: Validation Summary runs-on: ubuntu-latest - needs: [config, intent-parse, python-build-check, docker-build-dockerhub, docker-build-ghcr, docs-build, supply-chain-loopback] + needs: [config, check-dockerfile, intent-parse, python-build-check, docker-build-dockerhub, docker-build-ghcr, docs-build, supply-chain-loopback] if: always() outputs: success: ${{ steps.summary.outputs.success }} @@ -143,32 +166,64 @@ jobs: run: | echo "=== Release Validation Summary ===" echo "" + echo "Dockerfile Check: ${{ needs.check-dockerfile.outputs.has_dockerfile == 'true' && '✅ Found' || '⚠️ Not Found (Docker skipped)' }}" echo "Intent Parsing: ${{ needs.intent-parse.result }}" echo "Python Build: ${{ needs.python-build-check.result }}" - echo "DockerHub Build: ${{ needs.docker-build-dockerhub.result }}" - echo "GHCR Build: ${{ needs.docker-build-ghcr.result }}" + + # Check if Docker processes were run + HAS_DOCKERFILE="${{ needs.check-dockerfile.outputs.has_dockerfile }}" + if [ "$HAS_DOCKERFILE" = "true" ]; then + echo "DockerHub Build: ${{ needs.docker-build-dockerhub.result }}" + echo "GHCR Build: ${{ needs.docker-build-ghcr.result }}" + echo "Supply Chain: ${{ needs.supply-chain-loopback.result }}" + else + echo "DockerHub Build: ⏭️ Skipped (no Dockerfile)" + echo "GHCR Build: ⏭️ Skipped (no Dockerfile)" + echo "Supply Chain: ⏭️ Skipped (no Dockerfile)" + fi + echo "Docs Build: ${{ needs.docs-build.result }}" - echo "Supply Chain: ${{ needs.supply-chain-loopback.result }}" echo "" - if [[ "${{ needs.intent-parse.result }}" == "success" && \ - "${{ needs.python-build-check.result }}" == "success" && \ - "${{ needs.docker-build-dockerhub.result }}" == "success" && \ - "${{ needs.docker-build-ghcr.result }}" == "success" && \ - "${{ needs.docs-build.result }}" == "success" && \ - "${{ needs.supply-chain-loopback.result }}" == "success" ]]; then - echo "✅ All validation checks passed! Release process is ready." - echo "success=true" >> $GITHUB_OUTPUT - echo "" - echo "Release Configuration:" - echo "- Do Release: ${{ needs.intent-parse.outputs.do_release }}" - echo "- Level: ${{ needs.intent-parse.outputs.level }}" - echo "- Python: ${{ needs.intent-parse.outputs.python }}" - echo "- Docker: ${{ needs.intent-parse.outputs.docker }}" - echo "- Docs: ${{ needs.intent-parse.outputs.docs }}" - echo "- Notes: ${{ needs.intent-parse.outputs.notes }}" + # Validate results based on whether Docker processes were expected + INTENT_OK="${{ needs.intent-parse.result == 'success' }}" + PYTHON_OK="${{ needs.python-build-check.result == 'success' }}" + DOCS_OK="${{ needs.docs-build.result == 'success' }}" + + if [ "$HAS_DOCKERFILE" = "true" ]; then + # Docker processes should have run - validate them + DOCKER_HUB_OK="${{ needs.docker-build-dockerhub.result == 'success' }}" + DOCKER_GHCR_OK="${{ needs.docker-build-ghcr.result == 'success' }}" + SUPPLY_CHAIN_OK="${{ needs.supply-chain-loopback.result == 'success' }}" + + if [[ "$INTENT_OK" == "true" && "$PYTHON_OK" == "true" && \ + "$DOCKER_HUB_OK" == "true" && "$DOCKER_GHCR_OK" == "true" && \ + "$DOCS_OK" == "true" && "$SUPPLY_CHAIN_OK" == "true" ]]; then + echo "✅ All validation checks passed! Release process is ready." + echo "success=true" >> $GITHUB_OUTPUT + else + echo "❌ Some validation checks failed. Please review the logs above." + echo "success=false" >> $GITHUB_OUTPUT + exit 1 + fi else - echo "❌ Some validation checks failed. Please review the logs above." - echo "success=false" >> $GITHUB_OUTPUT - exit 1 + # No Docker processes - only validate non-Docker components + if [[ "$INTENT_OK" == "true" && "$PYTHON_OK" == "true" && "$DOCS_OK" == "true" ]]; then + echo "✅ All validation checks passed! Release process is ready." + echo "⚠️ Note: Docker validation was skipped (no Dockerfile found)" + echo "success=true" >> $GITHUB_OUTPUT + else + echo "❌ Some validation checks failed. Please review the logs above." + echo "success=false" >> $GITHUB_OUTPUT + exit 1 + fi fi + + echo "" + echo "Release Configuration:" + echo "- Do Release: ${{ needs.intent-parse.outputs.do_release }}" + echo "- Level: ${{ needs.intent-parse.outputs.level }}" + echo "- Python: ${{ needs.intent-parse.outputs.python }}" + echo "- Docker: ${{ needs.intent-parse.outputs.docker }}" + echo "- Docs: ${{ needs.intent-parse.outputs.docs }}" + echo "- Notes: ${{ needs.intent-parse.outputs.notes }}"