Compare commits

..

2 Commits

Author SHA1 Message Date
t.behrendt 33ef2a2d12 docs: finish docs 2026-04-29 19:44:03 +02:00
t.behrendt 1c26064357 merge summary back in 2026-04-29 19:39:22 +02:00
5 changed files with 74 additions and 262 deletions
-41
View File
@@ -1,41 +0,0 @@
name: "CI Summary"
description: "Writes CI validation summary to GITHUB_STEP_SUMMARY"
inputs:
has_k8s:
description: "Whether Kubernetes manifests were detected"
required: true
has_helmfile:
description: "Whether helmfile.yaml was detected"
required: true
skip_helm_validation:
description: "Whether Helm validation is manually disabled"
required: true
runs:
using: "composite"
steps:
- shell: bash
run: |
echo "## CI Validation Summary" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
if [ "${{ inputs.has_k8s }}" = "true" ]; then
echo "✅ **Kubernetes validation**: Completed" >> "$GITHUB_STEP_SUMMARY"
else
echo "❌ **Kubernetes validation**: Skipped (no k8s/ directory found)" >> "$GITHUB_STEP_SUMMARY"
fi
if [ "${{ inputs.has_helmfile }}" = "true" ] && [ "${{ inputs.skip_helm_validation }}" != "true" ]; then
echo "✅ **Helm validation**: Completed" >> "$GITHUB_STEP_SUMMARY"
elif [ "${{ inputs.has_helmfile }}" = "true" ] && [ "${{ inputs.skip_helm_validation }}" = "true" ]; then
echo "⏭️ **Helm validation**: Skipped (manually disabled)" >> "$GITHUB_STEP_SUMMARY"
else
echo "⏭️ **Helm validation**: Skipped (no helmfile.yaml found)" >> "$GITHUB_STEP_SUMMARY"
fi
echo "" >> "$GITHUB_STEP_SUMMARY"
if [ "${{ inputs.has_helmfile }}" = "true" ]; then
service_type="Helm + Kubernetes"
else
service_type="Kubernetes Only"
fi
echo "**Service Type**: ${service_type}" >> "$GITHUB_STEP_SUMMARY"
@@ -1,41 +0,0 @@
name: "Deployment Summary"
description: "Writes deployment summary to GITHUB_STEP_SUMMARY"
inputs:
has_k8s:
description: "Whether Kubernetes manifests were detected"
required: true
has_helmfile:
description: "Whether helmfile.yaml was detected"
required: true
skip_helm_deployment:
description: "Whether Helm deployment is manually disabled"
required: true
runs:
using: "composite"
steps:
- shell: bash
run: |
echo "## Deployment Summary" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
if [ "${{ inputs.has_k8s }}" = "true" ]; then
echo "✅ **Kubernetes deployment**: Completed" >> "$GITHUB_STEP_SUMMARY"
else
echo "❌ **Kubernetes deployment**: Skipped (no k8s/ directory found)" >> "$GITHUB_STEP_SUMMARY"
fi
if [ "${{ inputs.has_helmfile }}" = "true" ] && [ "${{ inputs.skip_helm_deployment }}" != "true" ]; then
echo "✅ **Helm deployment**: Completed" >> "$GITHUB_STEP_SUMMARY"
elif [ "${{ inputs.has_helmfile }}" = "true" ] && [ "${{ inputs.skip_helm_deployment }}" = "true" ]; then
echo "⏭️ **Helm deployment**: Skipped (manually disabled)" >> "$GITHUB_STEP_SUMMARY"
else
echo "⏭️ **Helm deployment**: Skipped (no helmfile.yaml found)" >> "$GITHUB_STEP_SUMMARY"
fi
echo "" >> "$GITHUB_STEP_SUMMARY"
if [ "${{ inputs.has_helmfile }}" = "true" ]; then
service_type="Helm + Kubernetes"
else
service_type="Kubernetes Only"
fi
echo "**Service Type**: ${service_type}" >> "$GITHUB_STEP_SUMMARY"
+18 -31
View File
@@ -28,19 +28,6 @@ on:
required: false required: false
default: "{}" default: "{}"
type: string type: string
outputs:
has_k8s:
description: "Whether Kubernetes manifests were detected"
value: ${{ jobs.summary-data.outputs.has_k8s }}
has_helmfile:
description: "Whether helmfile.yaml was detected"
value: ${{ jobs.summary-data.outputs.has_helmfile }}
skip_helm_deployment:
description: "Whether Helm deployment was manually skipped"
value: ${{ jobs.summary-data.outputs.skip_helm_deployment }}
service_type:
description: "Service type inferred from repository contents"
value: ${{ jobs.summary-data.outputs.service_type }}
jobs: jobs:
detect-service-type: detect-service-type:
@@ -139,30 +126,30 @@ jobs:
helmfile-args: apply helmfile-args: apply
env: ${{ fromJSON(inputs.helmfile_env) }} env: ${{ fromJSON(inputs.helmfile_env) }}
summary-data: # Summary job that always runs to show what was deployed
deployment-summary:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [detect-service-type, deploy-k8s, deploy-helm] needs: [detect-service-type, deploy-k8s, deploy-helm]
if: always() if: always()
outputs:
has_k8s: ${{ steps.export.outputs.has_k8s }}
has_helmfile: ${{ steps.export.outputs.has_helmfile }}
skip_helm_deployment: ${{ steps.export.outputs.skip_helm_deployment }}
service_type: ${{ steps.export.outputs.service_type }}
steps: steps:
- name: Export summary data - name: Deployment Summary
id: export
run: | run: |
has_k8s="${{ needs.detect-service-type.outputs.has_k8s }}" echo "## Deployment Summary" >> $GITHUB_STEP_SUMMARY
has_helmfile="${{ needs.detect-service-type.outputs.has_helmfile }}" echo "" >> $GITHUB_STEP_SUMMARY
skip_helm_deployment="${{ inputs.skip_helm_deployment }}"
if [ "$has_helmfile" = "true" ]; then if [ "${{ needs.detect-service-type.outputs.has_k8s }}" == "true" ]; then
service_type="Helm + Kubernetes" echo "✅ **Kubernetes deployment**: Completed" >> $GITHUB_STEP_SUMMARY
else else
service_type="Kubernetes Only" echo "❌ **Kubernetes deployment**: Skipped (no k8s/ directory found)" >> $GITHUB_STEP_SUMMARY
fi fi
echo "has_k8s=$has_k8s" >> "$GITHUB_OUTPUT" if [ "${{ needs.detect-service-type.outputs.has_helmfile }}" == "true" ] && [ "${{ inputs.skip_helm_deployment }}" != "true" ]; then
echo "has_helmfile=$has_helmfile" >> "$GITHUB_OUTPUT" echo "✅ **Helm deployment**: Completed" >> $GITHUB_STEP_SUMMARY
echo "skip_helm_deployment=$skip_helm_deployment" >> "$GITHUB_OUTPUT" elif [ "${{ needs.detect-service-type.outputs.has_helmfile }}" == "true" ] && [ "${{ inputs.skip_helm_deployment }}" == "true" ]; then
echo "service_type=$service_type" >> "$GITHUB_OUTPUT" echo "⏭️ **Helm deployment**: Skipped (manually disabled)" >> $GITHUB_STEP_SUMMARY
else
echo "⏭️ **Helm deployment**: Skipped (no helmfile.yaml found)" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Service Type**: ${{ needs.detect-service-type.outputs.has_helmfile == 'true' && 'Helm + Kubernetes' || 'Kubernetes Only' }}" >> $GITHUB_STEP_SUMMARY
+18 -31
View File
@@ -23,19 +23,6 @@ on:
required: false required: false
default: "{}" default: "{}"
type: string type: string
outputs:
has_k8s:
description: "Whether Kubernetes manifests were detected"
value: ${{ jobs.summary-data.outputs.has_k8s }}
has_helmfile:
description: "Whether helmfile.yaml was detected"
value: ${{ jobs.summary-data.outputs.has_helmfile }}
skip_helm_validation:
description: "Whether Helm validation was manually skipped"
value: ${{ jobs.summary-data.outputs.skip_helm_validation }}
service_type:
description: "Service type inferred from repository contents"
value: ${{ jobs.summary-data.outputs.service_type }}
jobs: jobs:
detect-service-type: detect-service-type:
@@ -113,30 +100,30 @@ jobs:
helmfile-args: diff helmfile-args: diff
env: ${{ fromJSON(inputs.helmfile_env) }} env: ${{ fromJSON(inputs.helmfile_env) }}
summary-data: # Summary job that always runs to show what was validated
ci-summary:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [detect-service-type, validate-k8s, validate-helm] needs: [detect-service-type, validate-k8s, validate-helm]
if: always() if: always()
outputs:
has_k8s: ${{ steps.export.outputs.has_k8s }}
has_helmfile: ${{ steps.export.outputs.has_helmfile }}
skip_helm_validation: ${{ steps.export.outputs.skip_helm_validation }}
service_type: ${{ steps.export.outputs.service_type }}
steps: steps:
- name: Export summary data - name: CI Summary
id: export
run: | run: |
has_k8s="${{ needs.detect-service-type.outputs.has_k8s }}" echo "## CI Validation Summary" >> $GITHUB_STEP_SUMMARY
has_helmfile="${{ needs.detect-service-type.outputs.has_helmfile }}" echo "" >> $GITHUB_STEP_SUMMARY
skip_helm_validation="${{ inputs.skip_helm_validation }}"
if [ "$has_helmfile" = "true" ]; then if [ "${{ needs.detect-service-type.outputs.has_k8s }}" == "true" ]; then
service_type="Helm + Kubernetes" echo "✅ **Kubernetes validation**: Completed" >> $GITHUB_STEP_SUMMARY
else else
service_type="Kubernetes Only" echo "❌ **Kubernetes validation**: Skipped (no k8s/ directory found)" >> $GITHUB_STEP_SUMMARY
fi fi
echo "has_k8s=$has_k8s" >> "$GITHUB_OUTPUT" if [ "${{ needs.detect-service-type.outputs.has_helmfile }}" == "true" ] && [ "${{ inputs.skip_helm_validation }}" != "true" ]; then
echo "has_helmfile=$has_helmfile" >> "$GITHUB_OUTPUT" echo "✅ **Helm validation**: Completed" >> $GITHUB_STEP_SUMMARY
echo "skip_helm_validation=$skip_helm_validation" >> "$GITHUB_OUTPUT" elif [ "${{ needs.detect-service-type.outputs.has_helmfile }}" == "true" ] && [ "${{ inputs.skip_helm_validation }}" == "true" ]; then
echo "service_type=$service_type" >> "$GITHUB_OUTPUT" echo "⏭️ **Helm validation**: Skipped (manually disabled)" >> $GITHUB_STEP_SUMMARY
else
echo "⏭️ **Helm validation**: Skipped (no helmfile.yaml found)" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Service Type**: ${{ needs.detect-service-type.outputs.has_helmfile == 'true' && 'Helm + Kubernetes' || 'Kubernetes Only' }}" >> $GITHUB_STEP_SUMMARY
+38 -118
View File
@@ -1,79 +1,75 @@
> [!WARNING] # Reusable CI/CD Workflows for k\_ Services
> Repo is currently not in use and not tested.
> We are waiting for proper shared workflow UI support in gitea. Otherwise errors are hard to identify.
> Follow https://github.com/go-gitea/gitea/issues/24604
# Reusable CI Workflow for Kubernetes Services This repository contains reusable CI and CD workflows that automatically detect Kubernetes service type (Kubernetes-only vs Helm + Kubernetes) and execute the relevant steps.
This directory contains a reusable CI workflow that automatically detects and validates your Kubernetes services, whether they use Helm + Kubernetes or just Kubernetes manifests.
## Features ## Features
- **Automatic Detection**: Automatically detects if your service uses Helm (helmfile.yaml) or just Kubernetes manifests - **Reusable CI and CD**: Separate reusable workflows for validation and deployment
- **Conditional Validation**: Only runs Helm validation when helmfile.yaml exists - **Automatic Detection**: Detects whether `helmfile.yaml` exists and whether `k8s/` exists
- **Flexible Paths**: Configurable paths for k8s directory and helmfile - **Conditional Execution**: Runs Helm steps only when applicable
- **Comprehensive Validation**: Validates both Kubernetes manifests and Helm charts - **Flexible Inputs**: Supports custom `k8s_dir` and `helmfile_path`
- **CI Summary**: Provides a clear summary of what was validated
## Usage ## Usage
### Basic Usage (Recommended) ### Basic CI Usage
Simply call the workflow without any parameters - it will automatically detect your service type: Call the reusable CI workflow:
```yaml ```yaml
jobs: jobs:
ci: ci:
uses: ./.gitea/workflows/ci.yaml uses: https://gitea.t000-n.de/t.behrendt/k_deploy_workflows/.gitea/workflows/ci.yaml@main
secrets: inherit
``` ```
### Advanced Usage with Custom Paths ### Basic CD Usage
If your service uses non-standard directory names: Call the reusable CD workflow:
```yaml
jobs:
deploy:
uses: https://gitea.t000-n.de/t.behrendt/k_deploy_workflows/.gitea/workflows/cd.yaml@main
secrets: inherit
```
### Advanced Usage with Custom Paths and Flags
```yaml ```yaml
jobs: jobs:
ci: ci:
uses: ./.gitea/workflows/ci.yaml uses: https://gitea.t000-n.de/t.behrendt/k_deploy_workflows/.gitea/workflows/ci.yaml@main
with: with:
k8s_dir: "kubernetes/" k8s_dir: "kubernetes/"
helmfile_path: "helm/helmfile.yaml" helmfile_path: "helm/helmfile.yaml"
```
### Force Skip Helm Validation
If you want to skip Helm validation even when helmfile.yaml exists:
```yaml
jobs:
ci:
uses: ./.gitea/workflows/ci.yaml
with:
skip_helm_validation: true skip_helm_validation: true
secrets: inherit
``` ```
## Input Parameters ## Inputs
### CI (`.gitea/workflows/ci.yaml`)
| Parameter | Description | Default | Required | | Parameter | Description | Default | Required |
| ---------------------- | -------------------------------------------- | --------------- | -------- | | ---------------------- | -------------------------------------------- | --------------- | -------- |
| `k8s_dir` | Path to Kubernetes manifests directory | `k8s/` | No | | `k8s_dir` | Path to Kubernetes manifests directory | `k8s/` | No |
| `helmfile_path` | Path to helmfile.yaml | `helmfile.yaml` | No | | `helmfile_path` | Path to helmfile.yaml | `helmfile.yaml` | No |
| `skip_helm_validation` | Skip Helm validation even if helmfile exists | `false` | No | | `skip_helm_validation` | Skip Helm validation even if helmfile exists | `false` | No |
| `helmfile_env` | JSON object string passed as env to helmfile | `{}` | No |
### CD (`.gitea/workflows/cd.yaml`)
| Parameter | Description | Default | Required |
| -------------------------------- | -------------------------------------------- | --------------- | -------- |
| `k8s_dir` | Path to Kubernetes manifests directory | `k8s/` | No |
| `helmfile_path` | Path to helmfile.yaml | `helmfile.yaml` | No |
| `skip_helm_deployment` | Skip Helm deployment even if helmfile exists | `false` | No |
| `skip_shared_secrets_deployment` | Skip shared secrets deployment | `false` | No |
| `helmfile_env` | JSON object string passed as env to helmfile | `{}` | No |
## Directory Structure Requirements ## Directory Structure Requirements
### For Kubernetes-only services: ### Full example structure (Helm + Kubernetes):
```
your-service/
├── k8s/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── ...
└── .gitea/workflows/your-workflow.yaml
```
### For Helm + Kubernetes services:
``` ```
your-service/ your-service/
@@ -84,79 +80,3 @@ your-service/
├── helmfile.yaml ├── helmfile.yaml
└── .gitea/workflows/your-workflow.yaml └── .gitea/workflows/your-workflow.yaml
``` ```
## What Gets Validated
### Always (if k8s/ directory exists):
- Kubernetes manifest validation using `kubectl --dry-run`
- Namespace extraction from repository name
- Basic Kubernetes syntax and schema validation
### Conditionally (if helmfile.yaml exists and Helm validation not skipped):
- Helm chart validation using `helmfile diff`
- Kubernetes manifests in Helm context
- Helm-specific configurations and values
## Example Workflows
See `example-usage.yaml` for complete examples of how to use this workflow in different scenarios.
## Available Actions
### Extract Chart Name from Repository Name
The `extract-chart-name-from-repo-name` action extracts the chart name from repository names following the `helm-<chart-name>` convention.
#### Usage
```yaml
- name: Extract chart name
uses: ./.gitea/actions/extract-chart-name-from-repo-name
with:
repo: ${{ github.repository_name }} # e.g., "helm-my-service"
```
#### Inputs
| Parameter | Description | Required |
| --------- | ------------------------------------------------ | -------- |
| `repo` | The full repository name (e.g., "helm-my-chart") | Yes |
#### Outputs
| Output | Description |
| ------------ | ---------------------------------------------------------------- |
| `chart-name` | The extracted chart name (e.g., "my-chart" from "helm-my-chart") |
#### Example
For a repository named `helm-user-service`, this action will extract `user-service` as the chart name.
## Dependencies
This workflow requires:
- `./.gitea/actions/extract-namespace-from-repo-name` action
- `./.gitea/actions/extract-chart-name-from-repo-name` action
- `KUBECONFIG` secret configured in your repository
- Access to your Kubernetes cluster
## Troubleshooting
### Helm validation skipped unexpectedly
- Check if `helmfile.yaml` exists in the expected location
- Verify the `skip_helm_validation` parameter is not set to `true`
- Ensure the file path is correct if using custom paths
### Kubernetes validation skipped
- Verify the `k8s/` directory (or custom path) exists
- Check the directory contains valid Kubernetes manifests
### Permission issues
- Ensure the `KUBECONFIG` secret is properly configured
- Verify the workflow has access to your Kubernetes cluster