Compare commits

..

1 Commits

Author SHA1 Message Date
renovate-bot 49c9f95e32 chore(deps): update azure/setup-helm action to v5
renovate/stability-days Updates have met minimum release age requirement
2026-03-31 10:03:52 +00:00
7 changed files with 251 additions and 94 deletions
@@ -0,0 +1,19 @@
name: Extract chart name from repo name
description: Extracts the chart name from the repo name, based on the convention of helm-<chart-name>
inputs:
repo:
description: The full repository name (e.g., "helm-my-chart")
required: true
outputs:
chart-name:
description: The extracted chart name
value: ${{ steps.extract.outputs.suffix }}
runs:
using: "composite"
steps:
- id: extract
shell: bash
run: |
full_repo="${{ inputs.repo }}"
suffix="${full_repo##*helm-}"
echo "suffix=$suffix" >> $GITHUB_OUTPUT
@@ -0,0 +1,19 @@
name: "Extract namespace from repo name"
description: "Extracts the namespace name from the repo name, based on the convention of k_<namespace-name>"
inputs:
repo:
description: 'The repo name, get it from "github.repository"'
required: true
outputs:
namespace:
description: "The namespace name"
value: ${{ steps.extract.outputs.suffix }}
runs:
using: "composite"
steps:
- id: extract
shell: bash
run: |
full_repo="${{ inputs.repo }}"
suffix="${full_repo##*k_}"
echo "suffix=$suffix" >> $GITHUB_OUTPUT
@@ -3,30 +3,35 @@ name: Deploy
on:
workflow_call:
inputs:
# Optional: Override the default k8s directory path
k8s_dir:
description: "Override the default k8s directory path (k8s/)"
description: "Path to Kubernetes manifests directory"
required: false
default: "k8s/"
type: string
# Optional: Override the default helmfile path
helmfile_path:
description: "Override the default helmfile path (hemfile.yaml)"
description: "Path to helmfile.yaml"
required: false
default: "helmfile.yaml"
type: string
# Optional: Skip Helm deployment even if helmfile exists
skip_helm_deployment:
description: "Skip Helm deployment even if helmfile.yaml exists"
required: false
default: false
type: boolean
skip_shared_secrets_deployment:
description: "Skip shared secrets deployment (e.g. restic backup secret)"
# Optional: Custom secrets to create (JSON array of secret objects)
custom_secrets:
description: "JSON array of secrets to create. Each secret should have: name, type, data"
required: false
default: false
type: boolean
helmfile_env:
description: "Optional JSON object string of environment variables for Helmfile"
default: "[]"
type: string
# Optional: Branch to deploy from
deploy_branch:
description: "Branch to deploy from"
required: false
default: "{}"
default: "main"
type: string
jobs:
@@ -58,43 +63,48 @@ jobs:
echo "No k8s directory found at ${{ inputs.k8s_dir }}"
fi
deploy-shared-secrets:
runs-on: ubuntu-latest
needs: detect-service-type
if: inputs.skip_shared_secrets_deployment != 'true'
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set restic backup secret
uses: azure/k8s-create-secret@6e0ba8047235646753f2a3a3b359b4d0006ff218 # v5.0.1
with:
namespace: ${{ steps.namespace.outputs.namespace }}
secret-name: backupsidecar-secret
secret-type: generic
data: |
{
"restic_password": "${{ secrets.RESTIC_PASSWORD }}",
"restic_rest_username": "${{ secrets.RESTIC_REST_USERNAME }}",
"restic_rest_password": "${{ secrets.RESTIC_REST_PASSWORD }}",
"gotify_token": "${{ secrets.GOTIFY_TOKEN }}"
}
deploy-k8s:
runs-on: ubuntu-latest
needs: detect-service-type
if: needs.detect-service-type.outputs.has_k8s == 'true'
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: https://gitea.t000-n.de/t.behrendt/k_deploy_actions/.gitea/actions/extract-namespace-from-repo-name@0.0.1
with:
ref: ${{ inputs.deploy_branch }}
- uses: ./.gitea/actions/extract-namespace-from-repo-name
id: namespace
with:
repo: ${{ github.repository }}
- uses: azure/setup-kubectl@829323503d1be3d00ca8346e5391ca0b07a9ab0d # v5.1.0
- uses: azure/k8s-set-context@89b837d75b40a7bd2ddafde837473c212db8b313 # v5.0.0
- uses: azure/setup-kubectl@776406bce94f63e41d621b960d78ee25c8b76ede # v4.0.1
- uses: azure/k8s-set-context@ae59a723ba9abe7a9655538854a025448dbab4aa # v4.0.2
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBECONFIG }}
- name: Create custom secrets
id: create-secrets
run: |
# Parse custom secrets from input
SECRETS='${{ inputs.custom_secrets }}'
if [ "$SECRETS" != "[]" ]; then
echo "Creating custom secrets..."
echo "$SECRETS" | jq -c '.[]' | while read -r secret; do
SECRET_NAME=$(echo "$secret" | jq -r '.name')
SECRET_TYPE=$(echo "$secret" | jq -r '.type // "generic"')
SECRET_DATA=$(echo "$secret" | jq -r '.data')
echo "Creating secret: $SECRET_NAME (type: $SECRET_TYPE)"
# Create the secret using kubectl
echo "$SECRET_DATA" | kubectl create secret $SECRET_TYPE $SECRET_NAME \
--from-literal=secret.json="$SECRET_DATA" \
--namespace=${{ steps.namespace.outputs.namespace }} \
--dry-run=client -o yaml | kubectl apply -f -
done
else
echo "No custom secrets to create"
fi
- name: Deploy Kubernetes manifests
uses: azure/k8s-deploy@c7ebd0d5f39477a23f1b5dea0f52e6db04adf28e # v6.0.0
uses: azure/k8s-deploy@c8cfec839dc09896b3b8cc40cd13d04792680771 # v5.1.0
with:
action: deploy
manifests: "${{ inputs.k8s_dir }}"
@@ -110,21 +120,45 @@ jobs:
inputs.skip_helm_deployment != 'true'
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: https://gitea.t000-n.de/t.behrendt/k_deploy_actions/.gitea/actions/extract-namespace-from-repo-name@0.0.1
with:
ref: ${{ inputs.deploy_branch }}
- uses: ./.gitea/actions/extract-namespace-from-repo-name
id: namespace
with:
repo: ${{ github.repository }}
- uses: azure/setup-kubectl@829323503d1be3d00ca8346e5391ca0b07a9ab0d # v5.1.0
- uses: azure/setup-kubectl@776406bce94f63e41d621b960d78ee25c8b76ede # v4.0.1
- uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5
- uses: azure/k8s-set-context@89b837d75b40a7bd2ddafde837473c212db8b313 # v5.0.0
- uses: azure/k8s-set-context@ae59a723ba9abe7a9655538854a025448dbab4aa # v4.0.2
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBECONFIG }}
- name: Create custom secrets
id: create-secrets
run: |
# Parse custom secrets from input
SECRETS='${{ inputs.custom_secrets }}'
if [ "$SECRETS" != "[]" ]; then
echo "Creating custom secrets..."
echo "$SECRETS" | jq -c '.[]' | while read -r secret; do
SECRET_NAME=$(echo "$secret" | jq -r '.name')
SECRET_TYPE=$(echo "$secret" | jq -r '.type // "generic"')
SECRET_DATA=$(echo "$secret" | jq -r '.data')
echo "Creating secret: $SECRET_NAME (type: $SECRET_TYPE)"
# Create the secret using kubectl
echo "$SECRET_DATA" | kubectl create secret $SECRET_TYPE $SECRET_NAME \
--from-literal=secret.json="$SECRET_DATA" \
--namespace=${{ steps.namespace.outputs.namespace }} \
--dry-run=client -o yaml | kubectl apply -f -
done
else
echo "No custom secrets to create"
fi
- name: Deploy Helm
uses: helmfile/helmfile-action@02671705b1dda1dc4b0a4ddd4f9f1ea8f4568c6f # v2.4.3
uses: helmfile/helmfile-action@99b1d18ad3989701cf26a54e65baf4a3ee8156b0 # v2.4.0
with:
helmfile-args: apply
env: ${{ fromJSON(inputs.helmfile_env) }}
# Summary job that always runs to show what was deployed
deployment-summary:
@@ -153,3 +187,11 @@ jobs:
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Service Type**: ${{ needs.detect-service-type.outputs.has_helmfile == 'true' && 'Helm + Kubernetes' || 'Kubernetes Only' }}" >> $GITHUB_STEP_SUMMARY
# Show custom secrets info
SECRETS='${{ inputs.custom_secrets }}'
if [ "$SECRETS" != "[]" ]; then
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Custom Secrets Created**: $(echo "$SECRETS" | jq length)" >> $GITHUB_STEP_SUMMARY
echo "$SECRETS" | jq -r '.[] | "- " + .name + " (" + (.type // "generic") + ")"' >> $GITHUB_STEP_SUMMARY
fi
@@ -18,11 +18,6 @@ on:
required: false
default: false
type: boolean
helmfile_env:
description: "Optional JSON object string of environment variables for Helmfile"
required: false
default: "{}"
type: string
jobs:
detect-service-type:
@@ -59,12 +54,12 @@ jobs:
if: needs.detect-service-type.outputs.has_k8s == 'true'
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: https://gitea.t000-n.de/t.behrendt/k_deploy_actions/.gitea/actions/extract-namespace-from-repo-name@0.0.1
- uses: ./.gitea/actions/extract-namespace-from-repo-name
id: namespace
with:
repo: ${{ github.repository }}
- uses: azure/setup-kubectl@829323503d1be3d00ca8346e5391ca0b07a9ab0d # v5.1.0
- uses: azure/k8s-set-context@89b837d75b40a7bd2ddafde837473c212db8b313 # v5.0.0
- uses: azure/setup-kubectl@776406bce94f63e41d621b960d78ee25c8b76ede # v4.0.1
- uses: azure/k8s-set-context@ae59a723ba9abe7a9655538854a025448dbab4aa # v4.0.2
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBECONFIG }}
@@ -84,21 +79,20 @@ jobs:
inputs.skip_helm_validation != 'true'
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: https://gitea.t000-n.de/t.behrendt/k_deploy_actions/.gitea/actions/extract-namespace-from-repo-name@0.0.1
- uses: ./.gitea/actions/extract-namespace-from-repo-name
id: namespace
with:
repo: ${{ github.repository }}
- uses: azure/setup-kubectl@829323503d1be3d00ca8346e5391ca0b07a9ab0d # v5.1.0
- uses: azure/setup-kubectl@776406bce94f63e41d621b960d78ee25c8b76ede # v4.0.1
- uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5
- uses: azure/k8s-set-context@89b837d75b40a7bd2ddafde837473c212db8b313 # v5.0.0
- uses: azure/k8s-set-context@ae59a723ba9abe7a9655538854a025448dbab4aa # v4.0.2
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBECONFIG }}
- name: Validate Helm
uses: helmfile/helmfile-action@02671705b1dda1dc4b0a4ddd4f9f1ea8f4568c6f # v2.4.3
uses: helmfile/helmfile-action@99b1d18ad3989701cf26a54e65baf4a3ee8156b0 # v2.4.0
with:
helmfile-args: diff
env: ${{ fromJSON(inputs.helmfile_env) }}
# Summary job that always runs to show what was validated
ci-summary:
+2 -2
View File
@@ -18,10 +18,10 @@ jobs:
fetch-depth: 0
- name: Increment tag
id: tag
uses: https://gitea.t000-n.de/t.behrendt/conventional-semantic-git-tag-increment@ef0c23189db33220a73022d8c29a27709d0df440 # 0.1.32
uses: https://gitea.t000-n.de/t.behrendt/conventional-semantic-git-tag-increment@11c694022eefab5876ac346fc9ffc0464b2548c7 # 0.1.30
with:
token: ${{ secrets.GITEA_TOKEN }}
- name: Push tag
uses: https://gitea.t000-n.de/t.behrendt/actions/release-git-tag@47a1c635cfc76cfb4eeee3db0d0b89bf19007c7a # 0.2.3
uses: https://gitea.t000-n.de/t.behrendt/actions/release-git-tag@f386e2570df6a796ba0a69865c89ea0c1a7109ab # 0.2.2
with:
tag: ${{ steps.tag.outputs.new-tag }}
+118 -38
View File
@@ -1,75 +1,79 @@
# Reusable CI/CD Workflows for k\_ Services
> [!WARNING]
> 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
This repository contains reusable CI and CD workflows that automatically detect Kubernetes service type (Kubernetes-only vs Helm + Kubernetes) and execute the relevant steps.
# Reusable CI Workflow for Kubernetes Services
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
- **Reusable CI and CD**: Separate reusable workflows for validation and deployment
- **Automatic Detection**: Detects whether `helmfile.yaml` exists and whether `k8s/` exists
- **Conditional Execution**: Runs Helm steps only when applicable
- **Flexible Inputs**: Supports custom `k8s_dir` and `helmfile_path`
- **Automatic Detection**: Automatically detects if your service uses Helm (helmfile.yaml) or just Kubernetes manifests
- **Conditional Validation**: Only runs Helm validation when helmfile.yaml exists
- **Flexible Paths**: Configurable paths for k8s directory and helmfile
- **Comprehensive Validation**: Validates both Kubernetes manifests and Helm charts
- **CI Summary**: Provides a clear summary of what was validated
## Usage
### Basic CI Usage
### Basic Usage (Recommended)
Call the reusable CI workflow:
Simply call the workflow without any parameters - it will automatically detect your service type:
```yaml
jobs:
ci:
uses: https://gitea.t000-n.de/t.behrendt/k_deploy_workflows/.gitea/workflows/ci.yaml@main
secrets: inherit
uses: ./.gitea/workflows/ci.yaml
```
### Basic CD Usage
### Advanced Usage with Custom Paths
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
If your service uses non-standard directory names:
```yaml
jobs:
ci:
uses: https://gitea.t000-n.de/t.behrendt/k_deploy_workflows/.gitea/workflows/ci.yaml@main
uses: ./.gitea/workflows/ci.yaml
with:
k8s_dir: "kubernetes/"
helmfile_path: "helm/helmfile.yaml"
skip_helm_validation: true
secrets: inherit
```
## Inputs
### Force Skip Helm Validation
### CI (`.gitea/workflows/ci.yaml`)
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
```
## Input Parameters
| Parameter | Description | Default | Required |
| ---------------------- | -------------------------------------------- | --------------- | -------- |
| `k8s_dir` | Path to Kubernetes manifests directory | `k8s/` | No |
| `helmfile_path` | Path to helmfile.yaml | `helmfile.yaml` | 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
### Full example structure (Helm + Kubernetes):
### For Kubernetes-only services:
```
your-service/
├── k8s/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── ...
└── .gitea/workflows/your-workflow.yaml
```
### For Helm + Kubernetes services:
```
your-service/
@@ -80,3 +84,79 @@ your-service/
├── helmfile.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
+4 -1
View File
@@ -1,4 +1,7 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["local>t.behrendt/renovate-configs:action"]
"extends": [
"local>t.behrendt/renovate-configs:common",
"local>t.behrendt/renovate-configs:action"
]
}