1 Commits

Author SHA1 Message Date
761eba7f0b chore(deps): update rmcrackan/libation to v13.3.0
All checks were successful
lint-test-helm / lint-helm (pull_request) Successful in 11s
2026-03-14 18:25:41 +00:00
204 changed files with 2589 additions and 2362 deletions

View File

@@ -14,21 +14,21 @@ on:
- 'hosts/**'
env:
BASE_BRANCH: "origin/${{ github.base_ref }}"
BASE_BRANCH: "origin/${{ gitea.base_ref }}"
jobs:
lint-docker-compose:
runs-on: ubuntu-js
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check Branch Exists
id: check-branch-exists
if: github.event_name == 'pull_request'
uses: GuillaumeFalourd/branch-exists@009290475dc3d75b5d7ec680c0c5b614b0d9855d # v1.1
uses: GuillaumeFalourd/branch-exists@v1.1
with:
branch: "${{ github.base_ref }}"
@@ -36,22 +36,21 @@ jobs:
id: branch-exists
if: github.event_name == 'push' || steps.check-branch-exists.outputs.exists == 'true' && github.event_name == 'pull_request'
run: |
if [ "${{ github.event_name }}" == "push" ]; then
if [ ${{ github.event_name == 'push' }} ]; then
echo ">> Action is from a push event, will continue with linting"
else
echo ">> Branch ${{ github.base_ref }} exists, will continue with linting"
echo ">> Branch ${{ gitea.base_ref }} exists, will continue with linting"
fi
echo ""
echo "----"
echo "exists=true" >> $GITHUB_OUTPUT
echo "exists=true" >> $GITEA_OUTPUT
- name: Set Up Node.js
- name: Set up Node.js
if: steps.branch-exists.outputs.exists == 'true'
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
uses: actions/setup-node@v6
with:
node-version: '24'
@@ -59,48 +58,58 @@ jobs:
id: check-dir-changes
if: steps.branch-exists.outputs.exists == 'true'
run: |
CHANGED_COMPOSE=()
echo ">> Target branch for diff is: ${BASE_BRANCH}"
if [ "${{ github.event_name }}" == "pull_request" ]; then
DIFF_TARGET="${BASE_BRANCH}"
echo ""
echo ">> Checking for changes in a pull request ..."
GIT_DIFF=$(git diff --name-only "${BASE_BRANCH}" | xargs -I {} dirname {} | sort -u)
else
DIFF_TARGET="${{ github.event.before }}..HEAD"
echo ""
echo ">> Checking for changes from a push ..."
GIT_DIFF=$(git diff --name-only ${{ gitea.event.before }}..HEAD | xargs -I {} dirname {} | sort -u)
fi
CHANGED_COMPOSE=$(git diff --name-only "${DIFF_TARGET}" | grep -E "^hosts/[^/]+/[^/]+/" | cut -d/ -f1,2,3 | sort -u || true)
if [ -n "${GIT_DIFF}" ]; then
echo ""
echo ">> Changes detected:"
echo "$GIT_DIFF"
for path in $GIT_DIFF; do
if echo "$path" | grep -q -E "hosts/[^/]+/[^/]+"; then
echo ""
echo ">> Adding path: $path"
CHANGED_COMPOSE+=$(echo "$path")
CHANGED_COMPOSE+=$(echo " ")
fi
done
else
echo ""
echo ">> No changes detected"
fi
if [ -n "${CHANGED_COMPOSE}" ]; then
echo ""
echo ">> Compose to Lint:"
echo ""
echo "${CHANGED_COMPOSE}"
echo "$(echo "${CHANGED_COMPOSE}" | sort -u)"
CHANGED_COMPOSE_CSV=$(echo "$CHANGED_COMPOSE" | paste -sd ',' -)
echo ""
echo "----"
echo "changes-detected=true" >> $GITHUB_OUTPUT
echo "compose-dir-csv=${CHANGED_COMPOSE_CSV}" >> $GITHUB_OUTPUT
echo "compose-dir<<EOF" >> $GITHUB_OUTPUT
echo "${CHANGED_COMPOSE}" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "changes-detected=true" >> $GITEA_OUTPUT
echo "compose-dir<<EOF" >> $GITEA_OUTPUT
echo "$(echo "${CHANGED_COMPOSE}" | sort -u)" >> $GITEA_OUTPUT
echo "EOF" >> $GITEA_OUTPUT
else
echo ""
echo ">> Did not find any docker compose files to lint"
echo ""
echo "----"
echo "changes-detected=false" >> $GITHUB_OUTPUT
echo "changes-detected=false" >> $GITEA_OUTPUT
fi
- name: Lint Docker Compose
@@ -108,27 +117,25 @@ jobs:
env:
CHANGED_COMPOSE: ${{ steps.check-dir-changes.outputs.compose-dir }}
run: |
echo ">> Running dclint on changed compose files ..."
for COMPOSE in $CHANGED_COMPOSE; do
echo ">> Linting ${COMPOSE} ..."
npx dclint ${COMPOSE}
echo ">> Running dclint on changed compose files:"
echo "$CHANGED_COMPOSE"
for compose in $CHANGED_COMPOSE; do
echo ">> Linting $compose ..."
npx dclint $compose
done
echo ""
echo "----"
- name: ntfy Failed
uses: niniyas/ntfy-action@96acac57fdc91d4c4f50b78486c1ed6f03f9f61c # master
uses: niniyas/ntfy-action@master
if: failure()
with:
url: '${{ secrets.NTFY_URL }}'
topic: '${{ secrets.NTFY_TOPIC }}'
title: 'Docker Compose Test Failure'
title: 'Test Failure - Infrastructure'
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,failed
details: "Docker linting for compose dirs: ${{ steps.check-dir-changes.outputs.compose-dir-csv }}"
details: 'Docker linting on Pull Request for Infrastructure has failed!'
icon: 'https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png'
actions: '[{"action": "view", "label": "View Logs", "url": "${{ vars.USER_URL }}/${{ github.repository }}/actions/runs/${{ github.run_id }}", "clear": true}]'
actions: '[{"action": "view", "label": "Open Gitea", "url": "https://gitea.alexlebens.dev/alexlebens/infrastructure/actions?workflow=lint-test-docker-pull.yaml", "clear": true}]'
image: true

View File

@@ -15,113 +15,104 @@ on:
env:
CLUSTER: cl01tl
BASE_BRANCH: "origin/${{ github.base_ref }}"
# renovate: datasource=github-releases depName=yannh/kubeconform
KUBECONFORM_VERSION: "v0.6.7"
BASE_BRANCH: "origin/${{ gitea.base_ref }}"
jobs:
lint-helm:
runs-on: ubuntu-js
outputs:
chart-dir: ${{ steps.check-dir-changes.outputs.chart-dir }}
chart-dir-csv: ${{ steps.check-dir-changes.outputs.chart-dir-csv }}
changes-detected: ${{ steps.check-dir-changes.outputs.changes-detected }}
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check Branch Exists
id: check-branch-exists
if: github.event_name == 'pull_request'
uses: GuillaumeFalourd/branch-exists@009290475dc3d75b5d7ec680c0c5b614b0d9855d # v1.1
uses: GuillaumeFalourd/branch-exists@v1.1
with:
branch: ${{ github.base_ref }}
branch: ${{ gitea.base_ref }}
- name: Report Branch Exists
id: branch-exists
if: github.event_name == 'push' || steps.check-branch-exists.outputs.exists == 'true' && github.event_name == 'pull_request'
run: |
if [ "${{ github.event_name }}" == "push" ]; then
if [ ${{ github.event_name == 'push' }} ]; then
echo ">> Action is from a push event, will continue with linting"
else
echo ">> Branch ${{ github.base_ref }} exists, will continue with linting"
echo ">> Branch ${{ gitea.base_ref }} exists, will continue with linting"
fi
echo ""
echo "----"
echo "exists=true" >> $GITHUB_OUTPUT
echo "exists=true" >> $GITEA_OUTPUT
- name: Set Up Helm
- name: Set up Helm
if: steps.branch-exists.outputs.exists == 'true'
uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4
uses: azure/setup-helm@v4
with:
token: ${{ secrets.GITEA_TOKEN }}
# renovate: datasource=github-releases depName=helm/helm
version: v4.1.3
version: v3.19.2
cache: true
- name: Cache Helm Dependencies
if: steps.branch-exists.outputs.exists == 'true'
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
with:
path: |
~/.cache/helm
~/.config/helm
key: helm-cache-${{ runner.os }}-${{ hashFiles('infrastructure/clusters/cl01tl/helm/**/Chart.yaml', 'infrastructure/clusters/cl01tl/helm/**/Chart.lock') }}
restore-keys: |
helm-cache-${{ runner.os }}-
- name: Check Directories for Changes
id: check-dir-changes
if: steps.branch-exists.outputs.exists == 'true'
run: |
CHANGED_CHARTS=()
echo ">> Target branch for diff is: ${BASE_BRANCH}"
if [ "${{ github.event_name }}" == "pull_request" ]; then
DIFF_TARGET="${BASE_BRANCH}"
echo ""
echo ">> Checking for changes in a pull request ..."
GIT_DIFF=$(git diff --name-only "${BASE_BRANCH}" | xargs -I {} dirname {} | sort -u)
else
DIFF_TARGET="${{ github.event.before }}..HEAD"
echo ""
echo ">> Checking for changes from a push ..."
GIT_DIFF=$(git diff --name-only ${{ gitea.event.before }}..HEAD | xargs -I {} dirname {} | sort -u)
fi
CHANGED_CHARTS=$(git diff --name-only "${DIFF_TARGET}" | grep -E "^clusters/${CLUSTER}/helm/" | awk -F '/' '{print $4}' | sort -u || true)
if [ -n "${GIT_DIFF}" ]; then
echo ""
echo ">> Changes detected:"
echo "$GIT_DIFF"
for path in $GIT_DIFF; do
if echo "$path" | grep -q -E "clusters/[^/]+/helm/[^/]+"; then
echo ""
echo ">> Adding path: $path"
CHANGED_CHARTS+=$(echo "$path" | awk -F '/' '{print $4}')
CHANGED_CHARTS+=$(echo "\n")
fi
done
else
echo ""
echo ">> No changes detected"
fi
if [ -n "${CHANGED_CHARTS}" ]; then
echo ""
echo ">> Chart to Lint:"
echo ""
echo "${CHANGED_CHARTS}"
echo "$(echo "${CHANGED_CHARTS}" | sort -u)"
CHANGED_CHARTS_CSV=$(echo "$CHANGED_CHARTS" | paste -sd ',' -)
echo ""
echo "----"
echo "changes-detected=true" >> $GITHUB_OUTPUT
echo "chart-dir-csv=${CHANGED_CHARTS_CSV}" >> $GITHUB_OUTPUT
echo "chart-dir<<EOF" >> $GITHUB_OUTPUT
echo "${CHANGED_CHARTS}" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "changes-detected=true" >> $GITEA_OUTPUT
echo "chart-dir<<EOF" >> $GITEA_OUTPUT
echo "$(echo "${CHANGED_CHARTS}" | sort -u)" >> $GITEA_OUTPUT
echo "EOF" >> $GITEA_OUTPUT
else
echo ""
echo ">> Did not find any helm charts files to lint"
echo ""
echo "----"
echo "changes-detected=false" >> $GITHUB_OUTPUT
echo "changes-detected=false" >> $GITEA_OUTPUT
fi
- name: Add Repositories
@@ -130,238 +121,68 @@ jobs:
CHANGED_CHARTS: ${{ steps.check-dir-changes.outputs.chart-dir }}
run: |
echo ">> Adding repositories for chart dependencies ..."
echo ""
for DIR in ${CHANGED_CHARTS}; do
helm dependency list --max-col-width 120 clusters/${CLUSTER}/helm/${DIR} 2> /dev/null \
| tail -n +2 \
| awk 'NF > 0 { print $1, $3 }' \
| while read -r REPO_NAME REPO_URL; do
if [[ "${REPO_URL}" == oci://* ]]; then
echo ">> Ignoring OCI repo: ${REPO_URL}"
elif [[ -n "${REPO_NAME}" && -n "${REPO_URL}" ]]; then
helm repo add "${REPO_NAME}" "${REPO_URL}"
for dir in ${CHANGED_CHARTS}; do
helm dependency list --max-col-width 120 clusters/${CLUSTER}/helm/$dir 2> /dev/null \
| tail +2 | head -n -1 \
| awk '{ print "helm repo add " $1 " " $3 }' \
| while read cmd; do
if [[ "$cmd" == "*oci://*" ]]; then
echo ">> Ignoring OCI repo"
else
echo ">> Command: $cmd"
echo "$cmd" | sh;
fi
done || true
done
if helm repo list > /dev/null 2>&1; then
if helm repo list | tail +2 | read -r; then
echo ""
echo ">> Update repository cache ..."
helm repo update
fi
echo ""
echo "----"
- name: Lint Helm Chart
id: lint
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
CHANGED_CHARTS: ${{ steps.check-dir-changes.outputs.chart-dir }}
run: |
EXIT_CODE=0
FAILED_CHARTS=""
echo ">> Running linting on changed charts ..."
for DIR in ${CHANGED_CHARTS}; do
CHART_PATH="clusters/${CLUSTER}/helm/${DIR}"
CHART_NAME=$(basename "${CHART_PATH}")
for dir in ${CHANGED_CHARTS}; do
chart_path=clusters/${CLUSTER}/helm/$dir
chart_name=$(basename "$chart_path")
if [ -f "${CHART_PATH}/Chart.yaml" ]; then
echo ""
echo ">> Building helm dependency for ${CHART_NAME} ..."
helm dependency build "${CHART_PATH}" --skip-refresh
if [ -f "$chart_path/Chart.yaml" ]; then
cd $chart_path
echo ""
echo ">> Linting helm chart ${CHART_NAME} ..."
echo ">> Building helm dependency ..."
helm dependency build --skip-refresh
if ! helm lint "${CHART_PATH}" --namespace "default"; then
EXIT_CODE=1
if [ -z "${FAILED_CHARTS}" ]; then
FAILED_CHARTS="${DIR}"
else
FAILED_CHARTS="${FAILED_CHARTS}, ${DIR}"
fi
fi
echo ""
echo ">> Linting helm ..."
helm lint --namespace "$chart_name"
else
echo ""
echo ">> Directory ${CHART_PATH} does not contain a Chart.yaml. Skipping ..."
echo ">> Directory $chart_path does not contain a Chart.yaml. Skipping ..."
echo ""
fi
done
echo ""
echo "----"
echo "failed-charts=${FAILED_CHARTS}" >> "$GITHUB_OUTPUT"
exit $EXIT_CODE
- name: ntfy Failed
uses: niniyas/ntfy-action@96acac57fdc91d4c4f50b78486c1ed6f03f9f61c # master
uses: niniyas/ntfy-action@master
if: failure()
with:
url: '${{ secrets.NTFY_URL }}'
topic: '${{ secrets.NTFY_TOPIC }}'
title: 'Helm Test Failure'
title: 'Test Failure - Infrastructure'
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,failed
details: "Helm linting for cluster '${{ env.CLUSTER }}' failed on charts: ${{ steps.lint.outputs.failed-charts }}"
details: 'Helm linting on Pull Request for Infrastructure has failed!'
icon: 'https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png'
actions: '[{"action": "view", "label": "View Run", "url": "${{ vars.USER_URL }}/${{ github.repository }}/actions/runs/${{ github.run_id }}", "clear": true}]'
image: true
validate-kubeconform:
needs: lint-helm
runs-on: ubuntu-js
if: |
needs.lint-helm.result == 'success' &&
needs.lint-helm.outputs.changes-detected == 'true' &&
github.event_name == 'pull_request'
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
- name: Install Kubeconform
run: |
echo ">> Downloading Kubeconform ${{ env.KUBECONFORM_VERSION }} ..."
wget -q https://github.com/yannh/kubeconform/releases/download/${{ env.KUBECONFORM_VERSION }}/kubeconform-linux-amd64.tar.gz
echo ""
echo ">> Extracting Kubeconform ..."
tar xf kubeconform-linux-amd64.tar.gz
echo ""
echo ">> Installing Kubeconform ..."
sudo mv kubeconform /usr/local/bin/
echo ""
echo ">> Verifying installation ..."
kubeconform -v
echo ""
echo "----"
- name: Set Up Helm
uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4
with:
token: ${{ secrets.GITEA_TOKEN }}
# renovate: datasource=github-releases depName=helm/helm
version: v4.1.3
cache: true
- name: Cache Helm Dependencies
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
with:
path: |
~/.cache/helm
~/.config/helm
key: helm-cache-${{ runner.os }}-${{ hashFiles('infrastructure/clusters/cl01tl/helm/**/Chart.yaml', 'infrastructure/clusters/cl01tl/helm/**/Chart.lock') }}
restore-keys: |
helm-cache-${{ runner.os }}-
- name: Add Repositories
env:
CHANGED_CHARTS: ${{ needs.lint-helm.outputs.chart-dir }}
run: |
echo ">> Adding repositories for chart dependencies ..."
echo ""
for DIR in ${CHANGED_CHARTS}; do
helm dependency list --max-col-width 120 clusters/${CLUSTER}/helm/${DIR} 2> /dev/null \
| tail -n +2 \
| awk 'NF > 0 { print $1, $3 }' \
| while read -r REPO_NAME REPO_URL; do
if [[ "${REPO_URL}" == oci://* ]]; then
echo ">> Ignoring OCI repo: ${REPO_URL}"
elif [[ -n "${REPO_NAME}" && -n "${REPO_URL}" ]]; then
helm repo add "${REPO_NAME}" "${REPO_URL}"
fi
done || true
done
if helm repo list > /dev/null 2>&1; then
echo ""
echo ">> Update repository cache ..."
helm repo update
fi
echo ""
echo "----"
- name: Validate Rendered Templates
id: validate
env:
CHANGED_CHARTS: ${{ needs.lint-helm.outputs.chart-dir }}
run: |
SCHEMA_LOCATIONS="-schema-location default -schema-location https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json"
EXIT_CODE=0
FAILED_CHARTS=""
for DIR in ${CHANGED_CHARTS}; do
CHART_PATH="clusters/${CLUSTER}/helm/${DIR}"
echo ""
echo ">> Validating: ${DIR}"
helm dependency build "${CHART_PATH}" --skip-refresh
if ! helm template "${DIR}" "${CHART_PATH}" --include-crds --namespace default --api-versions "gateway.networking.k8s.io/v1/HTTPRoute" | \
kubeconform \
${SCHEMA_LOCATIONS} \
-ignore-missing-schemas \
-strict \
-summary; then
EXIT_CODE=1
if [ -z "${FAILED_CHARTS}" ]; then
FAILED_CHARTS="${DIR}"
else
FAILED_CHARTS="${FAILED_CHARTS}, ${DIR}"
fi
fi
done
echo ""
echo "----"
echo "failed-charts=${FAILED_CHARTS}" >> "$GITHUB_OUTPUT"
exit $EXIT_CODE
- name: ntfy Failed
uses: niniyas/ntfy-action@96acac57fdc91d4c4f50b78486c1ed6f03f9f61c # master
if: failure()
with:
url: '${{ secrets.NTFY_URL }}'
topic: '${{ secrets.NTFY_TOPIC }}'
title: 'Kubeconform Test Failure'
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,failed
details: "Kubeconform for cluster '${{ env.CLUSTER }}' failed on charts: ${{ steps.validate.outputs.failed-charts }}"
icon: 'https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png'
actions: '[{"action": "view", "label": "View Run", "url": "${{ vars.USER_URL }}/${{ github.repository }}/actions/runs/${{ github.run_id }}", "clear": true}]'
actions: '[{"action": "view", "label": "Open Gitea", "url": "https://gitea.alexlebens.dev/alexlebens/infrastructure/actions?workflow=lint-test-helm-pull.yaml", "clear": true}]'
image: true

View File

@@ -0,0 +1,440 @@
name: render-manifests-automerge
on:
pull_request:
branches:
- main
paths:
- 'clusters/cl01tl/helm/**'
types:
- closed
env:
CLUSTER: cl01tl
BASE_BRANCH: manifests
BRANCH_NAME_BASE: auto/update-manifests-automerge
MAIN_DIR: /workspace/alexlebens/infrastructure/infrastructure
MANIFEST_DIR: /workspace/alexlebens/infrastructure/infrastructure-manifests
jobs:
render-manifests-automerge:
runs-on: ubuntu-js
if: ${{ (github.event.pull_request.merged == true) && (contains(github.event.pull_request.labels.*.name, 'automerge')) }}
steps:
- name: Checkout Main
uses: actions/checkout@v6
with:
path: infrastructure
fetch-depth: 0
- name: Checkout Manifests
uses: actions/checkout@v6
with:
ref: manifests
path: infrastructure-manifests
- name: Set up Helm
uses: azure/setup-helm@v4
with:
token: ${{ secrets.GITEA_TOKEN }}
version: v3.17.2 # Pending https://github.com/helm/helm/pull/30743
cache: true
- name: Configure Kubeconfig
uses: azure/k8s-set-context@v4
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBECONFIG }}
- name: Prepare Manifest Branch
id: prepare-manifest-branch
run: |
cd ${MANIFEST_DIR}
BRANCH_NAME="${BRANCH_NAME_BASE}-$(date +%Y%m%d%H%M%S)"
echo ">> Configure git to use gitea-bot as user ..."
git config user.name "gitea-bot"
git config user.email "gitea-bot@alexlebens.net"
echo ">> Creating branch ..."
git checkout -b $BRANCH_NAME
echo "----"
echo "BRANCH_NAME=${BRANCH_NAME}" >> $GITEA_OUTPUT
- name: Check which Directories have Changes
id: check-dir-changes
run: |
cd ${MAIN_DIR}
RENDER_DIR=()
echo ">> Checking for changes from HEAD^..HEAD ..."
GIT_DIFF=$(git diff --name-only HEAD^..HEAD | xargs -I {} dirname {} | sort -u | grep -E "clusters/[^/]+/helm/[^/]+")
if [ -n "${GIT_DIFF}" ]; then
echo ">> Changes detected:"
echo "$GIT_DIFF"
for path in $GIT_DIFF; do
RENDER_DIR+=$(echo "$path" | awk -F '/' '{print $4}')
RENDER_DIR+=$(echo " ")
done
else
echo ">> No changes detected"
fi
if [ -n "${RENDER_DIR}" ]; then
echo ">> Directories to Render:"
echo "$(echo "${RENDER_DIR}" | sort -u)"
echo "----"
echo "changes-detected=true" >> $GITEA_OUTPUT
echo "render-dir<<EOF" >> $GITEA_OUTPUT
echo "$(echo "${RENDER_DIR}" | sort -u)" >> $GITEA_OUTPUT
echo "EOF" >> $GITEA_OUTPUT
else
echo "changes-detected=false" >> $GITEA_OUTPUT
fi
- name: Add Repositories
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Adding repositories for chart dependencies ..."
for dir in ${RENDER_DIR}; do
helm dependency list --max-col-width 120 ${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir 2> /dev/null \
| tail +2 | head -n -1 \
| awk '{ print "helm repo add " $1 " " $3 }' \
| while read cmd; do
if [[ "$cmd" == "*oci://*" ]]; then
echo ">> Ignoring OCI repo"
else
echo "$cmd" | sh;
fi
done || true
done
if helm repo list | tail +2 | read -r; then
echo ">> Update repository cache ..."
helm repo update
fi
echo "----"
- name: Remove Changed Manifest Files
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MANIFEST_DIR}
echo ">> Remove manfiest files and rebuild from source ..."
for dir in ${RENDER_DIR}; do
chart_path=${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$dir
echo "$chart_path"
rm -rf $chart_path/*
done
echo "----"
- name: Render Helm Manifests
id: render-manifests
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Rendering Manifests ..."
for dir in ${RENDER_DIR}; do
chart_path=${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir
chart_name=$(basename "$chart_path")
echo ""
echo ""
echo ">> Rendering chart: $chart_name"
echo ">> Chart path $chart_path"
if [ -f "$chart_path/Chart.yaml" ]; then
OUTPUT_FOLDER="${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name/"
TEMPLATE=""
mkdir -p ${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name
cd $chart_path
echo ""
echo ">> Updating helm dependency ..."
helm dependency update --skip-refresh
echo ""
echo ">> Building helm dependency ..."
helm dependency build --skip-refresh
echo ""
echo ">> Linting helm ..."
helm lint --namespace "$chart_name"
echo ""
echo ">> Rendering templates ..."
case "$chart_name" in
"stack")
echo ""
echo ">> Special Rendering for stack into argocd namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace argocd --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
"cilium" | "coredns" | "metrics-server" |"prometheus-operator-crds")
echo ""
echo ">> Special Rendering for $chart_name into kube-system namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace kube-system --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
*)
echo ""
echo ">> Standard Rendering for $chart_name ..."
TEMPLATE=$(helm template "$chart_name" ./ --namespace "$chart_name" --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
esac
echo ""
echo ">> Formating rendered template ..."
echo "$TEMPLATE" | yq '... comments=""' | yq 'select(. != null)' | yq -s '"'"$OUTPUT_FOLDER"'" + .kind + "-" + .metadata.name + ".yaml"'
# Strip comments again to ensure formatting correctness
for file in "$OUTPUT_FOLDER"/*; do
yq -i '... comments=""' $file
done
echo ""
echo ">> Manifests for $chart_name rendered to $OUTPUT_FOLDER"
ls $OUTPUT_FOLDER
echo ""
else
echo ""
echo ">> Directory $chart_path does not contain a Chart.yaml. Skipping ..."
echo ""
fi
done
echo "----"
- name: Check for Changes
id: check-changes
if: steps.check-dir-changes.outputs.changes-detected == 'true'
run: |
cd ${MANIFEST_DIR}
GIT_CHANGES=$(git status --porcelain)
if [ -n "$GIT_CHANGES" ]; then
echo ">> Changes detected"
git status --porcelain
echo "changes-detected=true" >> $GITEA_OUTPUT
else
echo ">> No changes detected, skipping PR creation"
fi
echo "----"
- name: Commit and Push Changes
id: commit-push
if: steps.check-changes.outputs.changes-detected == 'true'
env:
BRANCH_NAME: ${{ steps.prepare-manifest-branch.outputs.BRANCH_NAME }}
run: |
cd ${MANIFEST_DIR}
echo ">> Commiting changes to ${BRANCH_NAME} ..."
git add .
git commit -m "chore: Update manifests after automerge"
REPO_URL="${{ secrets.REPO_URL }}/${{ gitea.repository }}"
echo ">> Pushing changes to $REPO_URL ..."
git push -u "https://oauth2:${{ secrets.BOT_TOKEN }}@$(echo $REPO_URL | sed -e 's|https://||')" ${BRANCH_NAME}
echo "----"
echo "push=true" >> $GITEA_OUTPUT
- name: Create Pull Request
id: create-pull-request
if: steps.commit-push.outputs.push == 'true'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
BRANCH_NAME: ${{ steps.prepare-manifest-branch.outputs.BRANCH_NAME }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls"
PAYLOAD=$( jq -n \
--arg head "${BRANCH_NAME}" \
--arg base "${BASE_BRANCH}" \
--arg title "Automated Manifest Update - Automerge" \
--arg body "This PR contains newly rendered Kubernetes manifests automatically generated by the CI workflow. This is expected to be automerged." \
'{head: $head, base: $base, title: $title, body: $body}' )
echo ">> Creating PR from branch ${BRANCH_NAME} into ${BASE_BRANCH}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
echo ">> With Payload of:"
echo "$PAYLOAD"
HTTP_STATUS=$(
curl -X POST \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
--data "$PAYLOAD" \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "201" ]; then
echo ">> Pull Request created successfully!"
PR_URL=$(cat response_body.json | jq -r .html_url)
echo ">> Pull Request URL: $PR_URL"
echo "pull-request-url=${PR_URL}" >> $GITEA_OUTPUT
PR_NUMBER=$(cat response_body.json | jq -r .number)
echo ">> Pull Request Number: $PR_NUMBER"
echo "pull-request-number=${PR_NUMBER}" >> $GITEA_OUTPUT
echo "pull-request-operation=created" >> $GITEA_OUTPUT
elif [ "$HTTP_STATUS" == "422" ]; then
echo ">> Failed to create PR (HTTP 422: Unprocessable Entity), PR may already exist"
elif [ "$HTTP_STATUS" == "409" ]; then
echo ">> Failed to create PR (HTTP 409: Conflict), PR already exists"
else
echo ">> Failed to create PR, HTTP status code: $HTTP_STATUS"
exit 1
fi
echo "----"
- name: Merge Changes
id: merge-changes
if: steps.commit-push.outputs.push == 'true'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
BRANCH_NAME: ${{ steps.prepare-manifest-branch.outputs.BRANCH_NAME }}
PR_NUMBER: ${{ steps.create-pull-request.outputs.pull-request-number }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls/${PR_NUMBER}/merge"
PAYLOAD=$( jq -n \
--arg Do "merge" \
'{Do: $Do}' )
echo ">> Merging PR with ID: ${PR_NUMBER}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
echo ">> With Payload of:"
echo "$PAYLOAD"
HTTP_STATUS=$(
curl -X POST \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
--data "$PAYLOAD" \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "200" ]; then
echo ">> Pull Request merged successfully!"
echo "pull-request-operation=merged" >> $GITEA_OUTPUT
else
echo ">> Failed to create PR, HTTP status code: $HTTP_STATUS"
echo "pull-request-operation=failed" >> $GITEA_OUTPUT
exit 1
fi
echo "----"
- name: Cleanup Branch
if: failure()
env:
BRANCH_NAME: ${{ steps.prepare-manifest-branch.outputs.BRANCH_NAME }}
run: |
cd ${MANIFEST_DIR}
echo ">> Removing branch: ${BRANCH_NAME}"
git push origin --delete ${BRANCH_NAME}
echo "----"
- name: ntfy Merged
uses: niniyas/ntfy-action@master
if: steps.merge-changes.outputs.pull-request-operation == 'merged'
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render PR Merged - Infrastructure"
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,successfully,completed
details: "Automerge Manifest rendering for Infrastructure!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "${{ steps.create-pull-request.outputs.pull-request-url }}", "clear": true}]'
- name: ntfy Failed
uses: niniyas/ntfy-action@master
if: failure()
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render Failure - Infrastructure"
priority: 4
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,failed
details: "Automerge Manifest rendering for Infrastructure has failed!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "https://gitea.alexlebens.dev/alexlebens/infrastructure/actions?workflow=render-manifests-automerge.yaml", "clear": true}]'
image: true

View File

@@ -0,0 +1,390 @@
name: render-manifests-dispatch
on:
schedule:
- cron: '0 3 * * *'
workflow_dispatch:
env:
CLUSTER: cl01tl
BASE_BRANCH: manifests
BRANCH_NAME: auto/update-manifests
ASSIGNEE: alexlebens
MAIN_DIR: /workspace/alexlebens/infrastructure/infrastructure
MANIFEST_DIR: /workspace/alexlebens/infrastructure/infrastructure-manifests
jobs:
render-manifests-dispatch:
runs-on: ubuntu-js
steps:
- name: Checkout Main
uses: actions/checkout@v6
with:
path: infrastructure
fetch-depth: 0
- name: Checkout Manifests
uses: actions/checkout@v6
with:
ref: manifests
path: infrastructure-manifests
- name: Set up Helm
uses: azure/setup-helm@v4
with:
token: ${{ secrets.GITEA_TOKEN }}
version: v3.17.2 # Pending https://github.com/helm/helm/pull/30743
cache: true
- name: Configure Kubeconfig
uses: azure/k8s-set-context@v4
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBECONFIG }}
- name: Prepare Manifest Branch
run: |
cd ${MANIFEST_DIR}
echo ">> Configure git to use gitea-bot as user ..."
git config user.name "gitea-bot"
git config user.email "gitea-bot@alexlebens.net"
echo ">> Checking if PR branch exists ..."
if [[ $(git ls-remote --heads origin "${BRANCH_NAME}" | wc -l) -gt 0 ]]; then
echo ">> Branch '${BRANCH_NAME}' exists, pulling changes ..."
git fetch origin "${BRANCH_NAME}"
git checkout "${BRANCH_NAME}"
git pull --rebase
else
echo ">> Branch '${BRANCH_NAME}' does not exist, creating ..."
git checkout -b $BRANCH_NAME
fi
echo "----"
- name: Check which Directories have Changes
id: check-dir-changes
run: |
cd ${MAIN_DIR}
RENDER_DIR=()
echo ">> Triggered on dispatch, will check all paths ..."
RENDER_DIR+=$(ls clusters/cl01tl/helm/)
if [ -n "${RENDER_DIR}" ]; then
echo ">> Directories to Render:"
echo "$(echo "${RENDER_DIR}" | sort -u)"
echo "----"
echo "changes-detected=true" >> $GITEA_OUTPUT
echo "render-dir<<EOF" >> $GITEA_OUTPUT
echo "$(echo "${RENDER_DIR}" | sort -u)" >> $GITEA_OUTPUT
echo "EOF" >> $GITEA_OUTPUT
else
echo "changes-detected=false" >> $GITEA_OUTPUT
fi
- name: Add Repositories
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Adding repositories for chart dependencies ..."
for dir in ${RENDER_DIR}; do
helm dependency list --max-col-width 120 ${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir 2> /dev/null \
| tail +2 | head -n -1 \
| awk '{ print "helm repo add " $1 " " $3 }' \
| while read cmd; do
if [[ "$cmd" == "*oci://*" ]]; then
echo ">> Ignoring OCI repo"
else
echo "$cmd" | sh;
fi
done || true
done
if helm repo list | tail +2 | read -r; then
echo ">> Update repository cache ..."
helm repo update
fi
echo "----"
- name: Render Helm Manifests
id: render-manifests
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Rendering Manifests ..."
for dir in ${RENDER_DIR}; do
chart_path=${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir
chart_name=$(basename "$chart_path")
echo ""
echo ""
echo ">> Rendering chart: $chart_name"
echo ">> Chart path $chart_path"
if [ -f "$chart_path/Chart.yaml" ]; then
OUTPUT_FOLDER="${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name/"
TEMPLATE=""
mkdir -p ${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name
cd $chart_path
echo ""
echo ">> Updating helm dependency ..."
helm dependency update --skip-refresh
echo ""
echo ">> Building helm dependency ..."
helm dependency build --skip-refresh
echo ""
echo ">> Linting helm ..."
helm lint --namespace "$chart_name"
echo ""
echo ">> Rendering templates ..."
case "$chart_name" in
"stack")
echo ""
echo ">> Special Rendering for stack into argocd namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace argocd --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
"cilium" | "coredns" | "metrics-server" |"prometheus-operator-crds")
echo ""
echo ">> Special Rendering for $chart_name into kube-system namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace kube-system --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
*)
echo ""
echo ">> Standard Rendering for $chart_name ..."
TEMPLATE=$(helm template "$chart_name" ./ --namespace "$chart_name" --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
esac
echo ""
echo ">> Formating rendered template ..."
echo "$TEMPLATE" | yq '... comments=""' | yq 'select(. != null)' | yq -s '"'"$OUTPUT_FOLDER"'" + .kind + "-" + .metadata.name + ".yaml"'
# Strip comments again to ensure formatting correctness
for file in "$OUTPUT_FOLDER"/*; do
yq -i '... comments=""' $file
done
echo ""
echo ">> Manifests for $chart_name rendered to $OUTPUT_FOLDER"
ls $OUTPUT_FOLDER
echo ""
else
echo ""
echo ">> Directory $chart_path does not contain a Chart.yaml. Skipping ..."
echo ""
fi
done
echo "----"
- name: Check for Changes
id: check-changes
if: steps.check-dir-changes.outputs.changes-detected == 'true'
run: |
cd ${MANIFEST_DIR}
GIT_CHANGES=$(git status --porcelain)
if [ -n "$GIT_CHANGES" ]; then
echo ">> Changes detected"
git status --porcelain
echo "changes-detected=true" >> $GITEA_OUTPUT
else
echo ">> No changes detected, skipping PR creation"
fi
echo "----"
- name: Commit and Push Changes
id: commit-push
if: steps.check-changes.outputs.changes-detected == 'true'
run: |
cd ${MANIFEST_DIR}
echo ">> Commiting changes to ${BRANCH_NAME} ..."
git add .
git commit -m "chore: Update manifests after change"
REPO_URL="${{ secrets.REPO_URL }}/${{ gitea.repository }}"
echo ">> Pushing changes to $REPO_URL ..."
git push -u "https://oauth2:${{ secrets.BOT_TOKEN }}@$(echo $REPO_URL | sed -e 's|https://||')" ${BRANCH_NAME}
echo "----"
echo "HEAD_BRANCH=${BRANCH_NAME}" >> $GITEA_OUTPUT
echo "push=true" >> $GITEA_OUTPUT
- name: Check for Pull Request
id: check-for-pull-requst
if: steps.commit-push.outputs.push == 'true'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
HEAD_BRANCH: ${{ steps.commit-push.outputs.HEAD_BRANCH }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls?base_branch=${BASE_BRANCH}&state=open&page=1"
echo ">> Checking if PR from branch ${HEAD_BRANCH} into ${BASE_BRANCH}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
HTTP_STATUS=$(
curl -X GET \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "200" ] && [ "$(cat response_body.json | jq -r .[0].state)" == "open" ]; then
echo ">> Pull Request has been found open, will update"
PR_INDEX=$(cat response_body.json | jq -r .[0].number)
echo "pull-request-exists=${PR_INDEX}" >> $GITEA_OUTPUT
echo "pull-request-index=true" >> $GITEA_OUTPUT
elif [ "$HTTP_STATUS" == "200" ] && [ "$(cat response_body.json | jq -r .[0].state)" == "closed" ]; then
echo ">> Pull Request found, but was closed"
echo "pull-request-exists=false" >> $GITEA_OUTPUT
else
echo ">> Pull Request not found"
echo "pull-request-exists=false" >> $GITEA_OUTPUT
fi
echo "----"
- name: Create Pull Request
id: create-pull-request
if: steps.commit-push.outputs.push == 'true' && steps.check-for-pull-requst.outputs.pull-request-exists == 'false'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
HEAD_BRANCH: ${{ steps.commit-push.outputs.HEAD_BRANCH }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls"
PAYLOAD=$( jq -n \
--arg head "${HEAD_BRANCH}" \
--arg base "${BASE_BRANCH}" \
--arg assignee "${ASSIGNEE}" \
--arg title "Automated Manifest Update" \
--arg body "This PR contains newly rendered Kubernetes manifests automatically generated by the CI workflow." \
'{head: $head, base: $base, assignee: $assignee, title: $title, body: $body}' )
echo ">> Creating PR from branch ${HEAD_BRANCH} into ${BASE_BRANCH}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
echo ">> With Payload of:"
echo "$PAYLOAD"
HTTP_STATUS=$(
curl -X POST \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
--data "$PAYLOAD" \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "201" ]; then
echo ">> Pull Request created successfully!"
PR_URL=$(cat response_body.json | jq -r .html_url)
echo "pull-request-url=${PR_URL}" >> $GITEA_OUTPUT
PR_ID=$(cat response_body.json | jq -r .id)
echo "pull-request-id=${PR_ID}" >> $GITEA_OUTPUT
echo "pull-request-operation=created" >> $GITEA_OUTPUT
elif [ "$HTTP_STATUS" == "422" ]; then
echo ">> Failed to create PR (HTTP 422: Unprocessable Entity), PR may already exist"
elif [ "$HTTP_STATUS" == "409" ]; then
echo ">> Failed to create PR (HTTP 409: Conflict), PR already exists"
else
echo ">> Failed to create PR, HTTP status code: $HTTP_STATUS"
exit 1
fi
echo "----"
- name: ntfy Created
uses: niniyas/ntfy-action@master
if: steps.create-pull-request.outputs.pull-request-operation == 'created'
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render PR Created - Infrastructure"
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,successfully,completed
details: "Manifest rendering for Infrastructure has created a new Pull Request with ID: ${{ steps.create-pull-request.outputs.pull-request-id }}!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "${{ steps.create-pull-request.outputs.pull-request-url }}", "clear": true}]'
- name: ntfy Failed
uses: niniyas/ntfy-action@master
if: failure()
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render Failure - Infrastructure"
priority: 4
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,failed
details: "Manifest rendering for Infrastructure has failed!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "https://gitea.alexlebens.dev/alexlebens/infrastructure/actions?workflow=render-manifests.yaml", "clear": true}]'
image: true

View File

@@ -0,0 +1,425 @@
name: render-manifests-merge
on:
pull_request:
branches:
- main
paths:
- 'clusters/cl01tl/helm/**'
types:
- closed
env:
CLUSTER: cl01tl
BASE_BRANCH: manifests
BRANCH_NAME: auto/update-manifests
ASSIGNEE: alexlebens
MAIN_DIR: /workspace/alexlebens/infrastructure/infrastructure
MANIFEST_DIR: /workspace/alexlebens/infrastructure/infrastructure-manifests
jobs:
render-manifests-merge:
runs-on: ubuntu-js
if: ${{ (github.event.pull_request.merged == true) && !(contains(github.event.pull_request.labels.*.name, 'automerge')) }}
steps:
- name: Checkout Main
uses: actions/checkout@v6
with:
path: infrastructure
fetch-depth: 0
- name: Checkout Manifests
uses: actions/checkout@v6
with:
ref: manifests
path: infrastructure-manifests
- name: Set up Helm
uses: azure/setup-helm@v4
with:
token: ${{ secrets.GITEA_TOKEN }}
version: v3.17.2 # Pending https://github.com/helm/helm/pull/30743
cache: true
- name: Configure Kubeconfig
uses: azure/k8s-set-context@v4
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBECONFIG }}
- name: Prepare Manifest Branch
run: |
cd ${MANIFEST_DIR}
echo ">> Configure git to use gitea-bot as user ..."
git config user.name "gitea-bot"
git config user.email "gitea-bot@alexlebens.net"
echo ">> Checking if PR branch exists ..."
if [[ $(git ls-remote --heads origin "${BRANCH_NAME}" | wc -l) -gt 0 ]]; then
echo ">> Branch '${BRANCH_NAME}' exists, pulling changes ..."
git fetch origin "${BRANCH_NAME}"
git checkout "${BRANCH_NAME}"
git pull --rebase
else
echo ">> Branch '${BRANCH_NAME}' does not exist, creating ..."
git checkout -b $BRANCH_NAME
fi
echo "----"
- name: Check which Directories have Changes
id: check-dir-changes
run: |
cd ${MAIN_DIR}
RENDER_DIR=()
echo ">> Checking for changes from HEAD^..HEAD ..."
GIT_DIFF=$(git diff --name-only HEAD^..HEAD | xargs -I {} dirname {} | sort -u | grep -E "clusters/[^/]+/helm/[^/]+")
if [ -n "${GIT_DIFF}" ]; then
echo ">> Changes detected:"
echo "$GIT_DIFF"
for path in $GIT_DIFF; do
RENDER_DIR+=$(echo "$path" | awk -F '/' '{print $4}')
RENDER_DIR+=$(echo " ")
done
else
echo ">> No changes detected"
fi
if [ -n "${RENDER_DIR}" ]; then
echo ">> Directories to Render:"
echo "$(echo "${RENDER_DIR}" | sort -u)"
echo "----"
echo "changes-detected=true" >> $GITEA_OUTPUT
echo "render-dir<<EOF" >> $GITEA_OUTPUT
echo "$(echo "${RENDER_DIR}" | sort -u)" >> $GITEA_OUTPUT
echo "EOF" >> $GITEA_OUTPUT
else
echo "changes-detected=false" >> $GITEA_OUTPUT
fi
- name: Add Repositories
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Adding repositories for chart dependencies ..."
for dir in ${RENDER_DIR}; do
helm dependency list --max-col-width 120 ${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir 2> /dev/null \
| tail +2 | head -n -1 \
| awk '{ print "helm repo add " $1 " " $3 }' \
| while read cmd; do
if [[ "$cmd" == "*oci://*" ]]; then
echo ">> Ignoring OCI repo"
else
echo "$cmd" | sh;
fi
done || true
done
if helm repo list | tail +2 | read -r; then
echo ">> Update repository cache ..."
helm repo update
fi
echo "----"
- name: Remove Changed Manifest Files
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MANIFEST_DIR}
echo ">> Remove manfiest files and rebuild from source ..."
for dir in ${RENDER_DIR}; do
chart_path=${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$dir
echo "$chart_path"
rm -rf $chart_path/*
done
echo "----"
- name: Render Helm Manifests
id: render-manifests
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Rendering Manifests ..."
for dir in ${RENDER_DIR}; do
chart_path=${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir
chart_name=$(basename "$chart_path")
echo ""
echo ""
echo ">> Rendering chart: $chart_name"
echo ">> Chart path $chart_path"
if [ -f "$chart_path/Chart.yaml" ]; then
OUTPUT_FOLDER="${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name/"
TEMPLATE=""
mkdir -p ${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name
cd $chart_path
echo ""
echo ">> Updating helm dependency ..."
helm dependency update --skip-refresh
echo ""
echo ">> Building helm dependency ..."
helm dependency build --skip-refresh
echo ""
echo ">> Linting helm ..."
helm lint --namespace "$chart_name"
echo ""
echo ">> Rendering templates ..."
case "$chart_name" in
"stack")
echo ""
echo ">> Special Rendering for stack into argocd namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace argocd --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
"cilium" | "coredns" | "metrics-server" |"prometheus-operator-crds")
echo ""
echo ">> Special Rendering for $chart_name into kube-system namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace kube-system --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
*)
echo ""
echo ">> Standard Rendering for $chart_name ..."
TEMPLATE=$(helm template "$chart_name" ./ --namespace "$chart_name" --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
esac
echo ""
echo ">> Formating rendered template ..."
echo "$TEMPLATE" | yq '... comments=""' | yq 'select(. != null)' | yq -s '"'"$OUTPUT_FOLDER"'" + .kind + "-" + .metadata.name + ".yaml"'
# Strip comments again to ensure formatting correctness
for file in "$OUTPUT_FOLDER"/*; do
yq -i '... comments=""' $file
done
echo ""
echo ">> Manifests for $chart_name rendered to $OUTPUT_FOLDER"
ls $OUTPUT_FOLDER
echo ""
else
echo ""
echo ">> Directory $chart_path does not contain a Chart.yaml. Skipping ..."
echo ""
fi
done
echo "----"
- name: Check for Changes
id: check-changes
if: steps.check-dir-changes.outputs.changes-detected == 'true'
run: |
cd ${MANIFEST_DIR}
GIT_CHANGES=$(git status --porcelain)
if [ -n "$GIT_CHANGES" ]; then
echo ">> Changes detected"
git status --porcelain
echo "changes-detected=true" >> $GITEA_OUTPUT
else
echo ">> No changes detected, skipping PR creation"
fi
echo "----"
- name: Commit and Push Changes
id: commit-push
if: steps.check-changes.outputs.changes-detected == 'true'
run: |
cd ${MANIFEST_DIR}
echo ">> Commiting changes to ${BRANCH_NAME} ..."
git add .
git commit -m "chore: Update manifests after change"
REPO_URL="${{ secrets.REPO_URL }}/${{ gitea.repository }}"
echo ">> Pushing changes to $REPO_URL ..."
git push -u "https://oauth2:${{ secrets.BOT_TOKEN }}@$(echo $REPO_URL | sed -e 's|https://||')" ${BRANCH_NAME}
echo "----"
echo "HEAD_BRANCH=${BRANCH_NAME}" >> $GITEA_OUTPUT
echo "push=true" >> $GITEA_OUTPUT
- name: Check for Pull Request
id: check-for-pull-requst
if: steps.commit-push.outputs.push == 'true'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
HEAD_BRANCH: ${{ steps.commit-push.outputs.HEAD_BRANCH }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls?base_branch=${BASE_BRANCH}&state=open&page=1"
echo ">> Checking if PR from branch ${HEAD_BRANCH} into ${BASE_BRANCH}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
HTTP_STATUS=$(
curl -X GET \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "200" ] && [ "$(cat response_body.json | jq -r .[0].state)" == "open" ]; then
echo ">> Pull Request has been found open, will update"
PR_INDEX=$(cat response_body.json | jq -r .[0].number)
echo "pull-request-exists=${PR_INDEX}" >> $GITEA_OUTPUT
echo "pull-request-index=true" >> $GITEA_OUTPUT
elif [ "$HTTP_STATUS" == "200" ] && [ "$(cat response_body.json | jq -r .[0].state)" == "closed" ]; then
echo ">> Pull Request found, but was closed"
echo "pull-request-exists=false" >> $GITEA_OUTPUT
else
echo ">> Pull Request not found"
echo "pull-request-exists=false" >> $GITEA_OUTPUT
fi
echo "----"
- name: Create Pull Request
id: create-pull-request
if: steps.commit-push.outputs.push == 'true' && steps.check-for-pull-requst.outputs.pull-request-exists == 'false'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
HEAD_BRANCH: ${{ steps.commit-push.outputs.HEAD_BRANCH }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls"
PAYLOAD=$( jq -n \
--arg head "${HEAD_BRANCH}" \
--arg base "${BASE_BRANCH}" \
--arg assignee "${ASSIGNEE}" \
--arg title "Automated Manifest Update" \
--arg body "This PR contains newly rendered Kubernetes manifests automatically generated by the CI workflow." \
'{head: $head, base: $base, assignee: $assignee, title: $title, body: $body}' )
echo ">> Creating PR from branch ${HEAD_BRANCH} into ${BASE_BRANCH}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
echo ">> With Payload of:"
echo "$PAYLOAD"
HTTP_STATUS=$(
curl -X POST \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
--data "$PAYLOAD" \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "201" ]; then
echo ">> Pull Request created successfully!"
PR_URL=$(cat response_body.json | jq -r .html_url)
echo "pull-request-url=${PR_URL}" >> $GITEA_OUTPUT
PR_ID=$(cat response_body.json | jq -r .id)
echo "pull-request-id=${PR_ID}" >> $GITEA_OUTPUT
echo "pull-request-operation=created" >> $GITEA_OUTPUT
elif [ "$HTTP_STATUS" == "422" ]; then
echo ">> Failed to create PR (HTTP 422: Unprocessable Entity), PR may already exist"
elif [ "$HTTP_STATUS" == "409" ]; then
echo ">> Failed to create PR (HTTP 409: Conflict), PR already exists"
else
echo ">> Failed to create PR, HTTP status code: $HTTP_STATUS"
exit 1
fi
echo "----"
- name: ntfy Created
uses: niniyas/ntfy-action@master
if: steps.create-pull-request.outputs.pull-request-operation == 'created'
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render PR Created - Infrastructure"
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,successfully,completed
details: "Manifest rendering for Infrastructure has created a new Pull Request with ID: ${{ steps.create-pull-request.outputs.pull-request-id }}!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "${{ steps.create-pull-request.outputs.pull-request-url }}", "clear": true}]'
- name: ntfy Failed
uses: niniyas/ntfy-action@master
if: failure()
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render Failure - Infrastructure"
priority: 4
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,failed
details: "Manifest rendering for Infrastructure has failed!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "https://gitea.alexlebens.dev/alexlebens/infrastructure/actions?workflow=render-manifests.yaml", "clear": true}]'
image: true

View File

@@ -0,0 +1,423 @@
name: render-manifests-push
on:
push:
branches:
- main
paths:
- 'clusters/cl01tl/helm/**'
env:
CLUSTER: cl01tl
BASE_BRANCH: manifests
BRANCH_NAME: auto/update-manifests
ASSIGNEE: alexlebens
MAIN_DIR: /workspace/alexlebens/infrastructure/infrastructure
MANIFEST_DIR: /workspace/alexlebens/infrastructure/infrastructure-manifests
jobs:
render-manifests-push:
runs-on: ubuntu-js
if: gitea.event.commits[0].author.username != 'renovate-bot'
steps:
- name: Checkout Main
uses: actions/checkout@v6
with:
path: infrastructure
fetch-depth: 0
- name: Checkout Manifests
uses: actions/checkout@v6
with:
ref: manifests
path: infrastructure-manifests
- name: Set up Helm
uses: azure/setup-helm@v4
with:
token: ${{ secrets.GITEA_TOKEN }}
version: v3.17.2 # Pending https://github.com/helm/helm/pull/30743
cache: true
- name: Configure Kubeconfig
uses: azure/k8s-set-context@v4
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBECONFIG }}
- name: Prepare Manifest Branch
run: |
cd ${MANIFEST_DIR}
echo ">> Configure git to use gitea-bot as user ..."
git config user.name "gitea-bot"
git config user.email "gitea-bot@alexlebens.net"
echo ">> Checking if PR branch exists ..."
if [[ $(git ls-remote --heads origin "${BRANCH_NAME}" | wc -l) -gt 0 ]]; then
echo ">> Branch '${BRANCH_NAME}' exists, pulling changes ..."
git fetch origin "${BRANCH_NAME}"
git checkout "${BRANCH_NAME}"
git pull --rebase
else
echo ">> Branch '${BRANCH_NAME}' does not exist, creating ..."
git checkout -b $BRANCH_NAME
fi
echo "----"
- name: Check which Directories have Changes
id: check-dir-changes
run: |
cd ${MAIN_DIR}
RENDER_DIR=()
echo ">> Checking for changes ..."
GIT_DIFF=$(git diff --name-only ${{ gitea.event.before }}..HEAD | xargs -I {} dirname {} | sort -u | grep -E "clusters/[^/]+/helm/[^/]+")
if [ -n "${GIT_DIFF}" ]; then
echo ">> Changes detected:"
echo "$GIT_DIFF"
for path in $GIT_DIFF; do
RENDER_DIR+=$(echo "$path" | awk -F '/' '{print $4}')
RENDER_DIR+=$(echo " ")
done
else
echo ">> No changes detected"
fi
if [ -n "${RENDER_DIR}" ]; then
echo ">> Directories to Render:"
echo "$(echo "${RENDER_DIR}" | sort -u)"
echo "----"
echo "changes-detected=true" >> $GITEA_OUTPUT
echo "render-dir<<EOF" >> $GITEA_OUTPUT
echo "$(echo "${RENDER_DIR}" | sort -u)" >> $GITEA_OUTPUT
echo "EOF" >> $GITEA_OUTPUT
else
echo "changes-detected=false" >> $GITEA_OUTPUT
fi
- name: Add Repositories
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Adding repositories for chart dependencies ..."
for dir in ${RENDER_DIR}; do
helm dependency list --max-col-width 120 ${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir 2> /dev/null \
| tail +2 | head -n -1 \
| awk '{ print "helm repo add " $1 " " $3 }' \
| while read cmd; do
if [[ "$cmd" == "*oci://*" ]]; then
echo ">> Ignoring OCI repo"
else
echo "$cmd" | sh;
fi
done || true
done
if helm repo list | tail +2 | read -r; then
echo ">> Update repository cache ..."
helm repo update
fi
echo "----"
- name: Remove Changed Manifest Files
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MANIFEST_DIR}
echo ">> Remove manfiest files and rebuild from source ..."
for dir in ${RENDER_DIR}; do
chart_path=${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$dir
echo "$chart_path"
rm -rf $chart_path/*
done
echo "----"
- name: Render Helm Manifests
id: render-manifests
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd ${MAIN_DIR}
echo ">> Rendering Manifests ..."
for dir in ${RENDER_DIR}; do
chart_path=${MAIN_DIR}/clusters/${CLUSTER}/helm/$dir
chart_name=$(basename "$chart_path")
echo ""
echo ""
echo ">> Rendering chart: $chart_name"
echo ">> Chart path $chart_path"
if [ -f "$chart_path/Chart.yaml" ]; then
OUTPUT_FOLDER="${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name/"
TEMPLATE=""
mkdir -p ${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/$chart_name
cd $chart_path
echo ""
echo ">> Updating helm dependency ..."
helm dependency update --skip-refresh
echo ""
echo ">> Building helm dependency ..."
helm dependency build --skip-refresh
echo ""
echo ">> Linting helm ..."
helm lint --namespace "$chart_name"
echo ""
echo ">> Rendering templates ..."
case "$chart_name" in
"stack")
echo ""
echo ">> Special Rendering for stack into argocd namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace argocd --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
"cilium" | "coredns" | "metrics-server" |"prometheus-operator-crds")
echo ""
echo ">> Special Rendering for $chart_name into kube-system namespace ..."
TEMPLATE=$(helm template $chart_name ./ --namespace kube-system --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
*)
echo ""
echo ">> Standard Rendering for $chart_name ..."
TEMPLATE=$(helm template "$chart_name" ./ --namespace "$chart_name" --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
;;
esac
echo ""
echo ">> Formating rendered template ..."
echo "$TEMPLATE" | yq '... comments=""' | yq 'select(. != null)' | yq -s '"'"$OUTPUT_FOLDER"'" + .kind + "-" + .metadata.name + ".yaml"'
# Strip comments again to ensure formatting correctness
for file in "$OUTPUT_FOLDER"/*; do
yq -i '... comments=""' $file
done
echo ""
echo ">> Manifests for $chart_name rendered to $OUTPUT_FOLDER"
ls $OUTPUT_FOLDER
echo ""
else
echo ""
echo ">> Directory $chart_path does not contain a Chart.yaml. Skipping ..."
echo ""
fi
done
echo "----"
- name: Check for Changes
id: check-changes
if: steps.check-dir-changes.outputs.changes-detected == 'true'
run: |
cd ${MANIFEST_DIR}
GIT_CHANGES=$(git status --porcelain)
if [ -n "$GIT_CHANGES" ]; then
echo ">> Changes detected"
git status --porcelain
echo "changes-detected=true" >> $GITEA_OUTPUT
else
echo ">> No changes detected, skipping PR creation"
fi
echo "----"
- name: Commit and Push Changes
id: commit-push
if: steps.check-changes.outputs.changes-detected == 'true'
run: |
cd ${MANIFEST_DIR}
echo ">> Commiting changes to ${BRANCH_NAME} ..."
git add .
git commit -m "chore: Update manifests after change"
REPO_URL="${{ secrets.REPO_URL }}/${{ gitea.repository }}"
echo ">> Pushing changes to $REPO_URL ..."
git push -u "https://oauth2:${{ secrets.BOT_TOKEN }}@$(echo $REPO_URL | sed -e 's|https://||')" ${BRANCH_NAME}
echo "----"
echo "HEAD_BRANCH=${BRANCH_NAME}" >> $GITEA_OUTPUT
echo "push=true" >> $GITEA_OUTPUT
- name: Check for Pull Request
id: check-for-pull-requst
if: steps.commit-push.outputs.push == 'true'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
HEAD_BRANCH: ${{ steps.commit-push.outputs.HEAD_BRANCH }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls?base_branch=${BASE_BRANCH}&state=open&page=1"
echo ">> Checking if PR from branch ${HEAD_BRANCH} into ${BASE_BRANCH}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
HTTP_STATUS=$(
curl -X GET \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "200" ] && [ "$(cat response_body.json | jq -r .[0].state)" == "open" ]; then
echo ">> Pull Request has been found open, will update"
PR_INDEX=$(cat response_body.json | jq -r .[0].number)
echo "pull-request-exists=${PR_INDEX}" >> $GITEA_OUTPUT
echo "pull-request-index=true" >> $GITEA_OUTPUT
elif [ "$HTTP_STATUS" == "200" ] && [ "$(cat response_body.json | jq -r .[0].state)" == "closed" ]; then
echo ">> Pull Request found, but was closed"
echo "pull-request-exists=false" >> $GITEA_OUTPUT
else
echo ">> Pull Request not found"
echo "pull-request-exists=false" >> $GITEA_OUTPUT
fi
echo "----"
- name: Create Pull Request
id: create-pull-request
if: steps.commit-push.outputs.push == 'true' && steps.check-for-pull-requst.outputs.pull-request-exists == 'false'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
HEAD_BRANCH: ${{ steps.commit-push.outputs.HEAD_BRANCH }}
run: |
cd ${MANIFEST_DIR}
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls"
PAYLOAD=$( jq -n \
--arg head "${HEAD_BRANCH}" \
--arg base "${BASE_BRANCH}" \
--arg assignee "${ASSIGNEE}" \
--arg title "Automated Manifest Update" \
--arg body "This PR contains newly rendered Kubernetes manifests automatically generated by the CI workflow." \
'{head: $head, base: $base, assignee: $assignee, title: $title, body: $body}' )
echo ">> Creating PR from branch ${HEAD_BRANCH} into ${BASE_BRANCH}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
echo ">> With Payload of:"
echo "$PAYLOAD"
HTTP_STATUS=$(
curl -X POST \
--silent \
--write-out '%{http_code}' \
--output response_body.json \
--dump-header response_headers.txt \
--data "$PAYLOAD" \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"$API_ENDPOINT" 2> response_errors.txt
)
echo ">> HTTP Status Code: $HTTP_STATUS"
echo ">> Response Output ..."
echo "----"
cat response_body.json
echo "----"
cat response_headers.txt
echo "----"
cat response_errors.txt
echo "----"
if [ "$HTTP_STATUS" == "201" ]; then
echo ">> Pull Request created successfully!"
PR_URL=$(cat response_body.json | jq -r .html_url)
echo "pull-request-url=${PR_URL}" >> $GITEA_OUTPUT
PR_ID=$(cat response_body.json | jq -r .id)
echo "pull-request-id=${PR_ID}" >> $GITEA_OUTPUT
echo "pull-request-operation=created" >> $GITEA_OUTPUT
elif [ "$HTTP_STATUS" == "422" ]; then
echo ">> Failed to create PR (HTTP 422: Unprocessable Entity), PR may already exist"
elif [ "$HTTP_STATUS" == "409" ]; then
echo ">> Failed to create PR (HTTP 409: Conflict), PR already exists"
else
echo ">> Failed to create PR, HTTP status code: $HTTP_STATUS"
exit 1
fi
echo "----"
- name: ntfy Created
uses: niniyas/ntfy-action@master
if: steps.create-pull-request.outputs.pull-request-operation == 'created'
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render PR Created - Infrastructure"
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,successfully,completed
details: "Manifest rendering for Infrastructure has created a new Pull Request with ID: ${{ steps.create-pull-request.outputs.pull-request-id }}!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "${{ steps.create-pull-request.outputs.pull-request-url }}", "clear": true}]'
- name: ntfy Failed
uses: niniyas/ntfy-action@master
if: failure()
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render Failure - Infrastructure"
priority: 4
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,failed
details: "Manifest rendering for Infrastructure has failed!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "Open Gitea", "url": "https://gitea.alexlebens.dev/alexlebens/infrastructure/actions?workflow=render-manifests.yaml", "clear": true}]'
image: true

View File

@@ -1,624 +0,0 @@
name: render-manifests
on:
schedule:
- cron: '0 15 * * *'
workflow_dispatch:
pull_request:
branches:
- main
paths:
- 'clusters/cl01tl/helm/**'
types:
- closed
env:
CLUSTER: cl01tl
BASE_BRANCH: manifests
BRANCH_NAME_BASE: auto/update-manifests
ASSIGNEE: alexlebens
MAIN_DIR: /workspace/alexlebens/infrastructure/infrastructure
MANIFEST_DIR: /workspace/alexlebens/infrastructure/infrastructure-manifests
jobs:
render-manifests:
runs-on: ubuntu-js
if: >-
github.event_name == 'schedule' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && github.event.pull_request.merged == true)
steps:
- name: Checkout Main
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
path: infrastructure
fetch-depth: 0
- name: Checkout Manifests
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: manifests
path: infrastructure-manifests
- name: Set Up Helm
uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4
with:
token: ${{ secrets.GITEA_TOKEN }}
version: v3.17.2 # Pending https://github.com/helm/helm/pull/30743
cache: true
- name: Configure Kubeconfig
uses: azure/k8s-set-context@ae59a723ba9abe7a9655538854a025448dbab4aa # v4
with:
method: kubeconfig
kubeconfig: ${{ secrets.KUBECONFIG }}
- name: Cache Helm Dependencies
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
with:
path: |
~/.cache/helm
~/.config/helm
key: helm-cache-${{ runner.os }}-${{ hashFiles('infrastructure/clusters/cl01tl/helm/**/Chart.yaml', 'infrastructure/clusters/cl01tl/helm/**/Chart.lock') }}
restore-keys: |
helm-cache-${{ runner.os }}-
- name: Determine Workflow Mode
id: mode
run: |
IS_AUTOMERGE="false"
RENDER_ALL="false"
DIFF_TARGET=""
if [[ "${{ github.event_name }}" == "schedule" || "${{ github.event_name }}" == "workflow_dispatch" ]]; then
echo ">> Mode: Dispatch/Schedule (Render All)"
RENDER_ALL="true"
elif [[ "${{ github.event_name }}" == "pull_request" ]]; then
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'automerge') }}" == "true" ]]; then
echo ">> Mode: PR Merged (Automerge)"
IS_AUTOMERGE="true"
else
echo ">> Mode: PR Merged (Standard)"
fi
DIFF_TARGET="HEAD^..HEAD"
fi
echo ""
echo "----"
echo "is-automerge=${IS_AUTOMERGE}" >> "$GITHUB_OUTPUT"
echo "render-all=${RENDER_ALL}" >> "$GITHUB_OUTPUT"
echo "diff-target=${DIFF_TARGET}" >> "$GITHUB_OUTPUT"
- name: Prepare Manifest Branch
id: prepare-manifest-branch
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
IS_AUTOMERGE: ${{ steps.mode.outputs.is-automerge }}
run: |
cd "${MANIFEST_DIR}"
echo ">> Configure git to use gitea-bot as user ..."
git config user.name "gitea-bot"
git config user.email "gitea-bot@alexlebens.net"
if [[ "$IS_AUTOMERGE" == "true" ]]; then
BRANCH_NAME="${BRANCH_NAME_BASE}-automerge-${PR_NUMBER}"
echo ""
echo ">> Creating branch ${BRANCH_NAME} ..."
git checkout -B "$BRANCH_NAME"
else
echo ""
echo ">> Checking if PR branch exists ..."
BRANCH_NAME="${BRANCH_NAME_BASE}"
if git ls-remote --exit-code --heads origin "${BRANCH_NAME}" > /dev/null 2>&1; then
echo ""
echo ">> Branch '${BRANCH_NAME}' exists, pulling changes ..."
git fetch origin "${BRANCH_NAME}"
git checkout "${BRANCH_NAME}"
git pull --rebase
else
echo ""
echo ">> Branch '${BRANCH_NAME}' does not exist, creating ..."
git checkout -b "${BRANCH_NAME}"
fi
fi
echo ""
echo "----"
echo "branch-name=${BRANCH_NAME}" >> "$GITHUB_OUTPUT"
- name: Check Which Directories Have Changes
id: check-dir-changes
env:
RENDER_ALL: ${{ steps.mode.outputs.render-all }}
DIFF_TARGET: ${{ steps.mode.outputs.diff-target }}
run: |
cd "${MAIN_DIR}"
if [[ "$RENDER_ALL" == "true" ]]; then
echo ">> Triggered on dispatch, will check all paths ..."
RENDER_DIR=$(find "clusters/${CLUSTER}/helm" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | sort -u)
else
echo ">> Checking for changes from ${DIFF_TARGET} ..."
RENDER_DIR=$(git diff --name-only "${DIFF_TARGET}" | grep -E "^clusters/${CLUSTER}/helm/" | awk -F '/' '{print $4}' | sort -u || true)
fi
if [ -n "${RENDER_DIR}" ]; then
echo ""
echo ">> Directories to Render:"
echo ""
echo "${RENDER_DIR}"
echo ""
echo "----"
echo "changes-detected=true" >> "$GITHUB_OUTPUT"
echo "render-dir<<EOF" >> "$GITHUB_OUTPUT"
echo "${RENDER_DIR}" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
else
echo ""
echo ">> No chart changes detected"
echo ""
echo "----"
echo "changes-detected=false" >> "$GITHUB_OUTPUT"
fi
- name: Add Repositories
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd "${MAIN_DIR}"
echo ">> Adding repositories for chart dependencies ..."
echo ""
for DIR in ${RENDER_DIR}; do
helm dependency list --max-col-width 120 "${MAIN_DIR}/clusters/${CLUSTER}/helm/${DIR}" 2> /dev/null \
| tail -n +2 \
| awk 'NF > 0 { print $1, $3 }' \
| while read -r REPO_NAME REPO_URL; do
if [[ "${REPO_URL}" == oci://* ]]; then
echo ">> Ignoring OCI repo: ${REPO_URL}"
elif [[ -n "${REPO_NAME}" && -n "${REPO_URL}" ]]; then
helm repo add "${REPO_NAME}" "${REPO_URL}"
fi
done || true
done
if helm repo list > /dev/null 2>&1; then
echo ""
echo ">> Update repository cache ..."
helm repo update
fi
echo ""
echo "----"
- name: Remove Changed Manifest Files
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd "${MANIFEST_DIR}"
echo ">> Remove manifest files and rebuild from source ..."
echo ""
for DIR in ${RENDER_DIR}; do
CHART_PATH="${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/${DIR}"
echo "${CHART_PATH}"
rm -rf "${CHART_PATH}"/*
done
echo ""
echo "----"
- name: Render Helm Manifests
id: render-manifests
if: steps.check-dir-changes.outputs.changes-detected == 'true'
env:
RENDER_DIR: ${{ steps.check-dir-changes.outputs.render-dir }}
run: |
cd "${MAIN_DIR}"
echo ">> Rendering Manifests ..."
render_chart() {
local DIR="$1"
local CHART_PATH="${MAIN_DIR}/clusters/${CLUSTER}/helm/${DIR}"
local CHART_NAME=$(basename "${CHART_PATH}")
echo ""
echo ">> Rendering chart: ${CHART_NAME}"
if [ -f "${CHART_PATH}/Chart.yaml" ]; then
local OUTPUT_FOLDER="${MANIFEST_DIR}/clusters/${CLUSTER}/manifests/${CHART_NAME}/"
mkdir -p "${OUTPUT_FOLDER}"
cd "${CHART_PATH}"
helm dependency update --skip-refresh > /dev/null
helm lint --namespace "${CHART_NAME}" --quiet
local NAMESPACE="${CHART_NAME}"
case "${CHART_NAME}" in
"stack")
NAMESPACE="argocd"
echo ">> Special Rendering into 'argocd' namespace ..."
;;
"cilium" | "coredns" | "metrics-server" | "prometheus-operator-crds")
NAMESPACE="kube-system"
echo ">> Special Rendering for ${CHART_NAME} into 'kube-system' namespace ..."
;;
*)
echo ">> Standard Rendering ..."
esac
echo ">> Formating rendered template ..."
local TEMPLATE
TEMPLATE=$(helm template "${CHART_NAME}" ./ --namespace "${NAMESPACE}" --include-crds --dry-run=server --api-versions "gateway.networking.k8s.io/v1/HTTPRoute")
# Format and split rendered template
echo "${TEMPLATE}" | yq '... comments=""' | yq 'select(. != null)' | yq -s '"'"${OUTPUT_FOLDER}"'" + .kind + "-" + .metadata.name + ".yaml"'
# Strip comments again to ensure formatting correctness
for file in "$OUTPUT_FOLDER"/*; do
yq -i '... comments=""' $file
done
echo ">> Manifests for ${CHART_NAME} rendered successfully to $OUTPUT_FOLDER:"
echo ""
ls $OUTPUT_FOLDER
echo ""
else
echo ""
echo ">> Directory ${CHART_PATH} does not contain a Chart.yaml. Skipping ..."
fi
}
export -f render_chart
export MAIN_DIR CLUSTER MANIFEST_DIR
# Run rendering in parallel
for DIR in ${RENDER_DIR}; do
echo "${DIR}"
done | xargs -P 4 -I {} bash -c 'OUT=$(render_chart "$@" 2>&1); printf "%s\n" "$OUT"' _ {}
echo ""
echo "----"
- name: Check for Changes
id: check-changes
if: steps.check-dir-changes.outputs.changes-detected == 'true'
run: |
cd "${MANIFEST_DIR}"
GIT_CHANGES=$(git status --porcelain)
if [ -n "${GIT_CHANGES}" ]; then
echo ">> Changes detected"
git status --porcelain
CHANGED_CHARTS=$(echo "$GIT_CHANGES" | grep -oE "clusters/${CLUSTER}/manifests/[^/]+" | awk -F '/' '{print $4}' | sort -u | paste -sd ',' -)
echo ""
echo "----"
echo "changes-detected=true" >> "$GITHUB_OUTPUT"
echo "changed-charts-csv=${CHANGED_CHARTS}" >> "$GITHUB_OUTPUT"
else
echo ">> No changes detected, skipping PR creation"
echo ""
echo "----"
fi
- name: Commit and Push Changes
id: commit-push
if: steps.check-changes.outputs.changes-detected == 'true'
env:
BRANCH_NAME: ${{ steps.prepare-manifest-branch.outputs.branch-name }}
IS_AUTOMERGE: ${{ steps.mode.outputs.is-automerge }}
run: |
cd "${MANIFEST_DIR}"
MSG="chore: Update manifests after change"
if [[ "$IS_AUTOMERGE" == "true" ]]; then
MSG="chore: Update manifests after automerge"
fi
echo ">> Commiting changes to ${BRANCH_NAME} ..."
git add .
git commit -m "${MSG}"
REPO_URL="${{ secrets.REPO_URL }}/${{ gitea.repository }}"
echo ""
echo ">> Pushing changes to ${REPO_URL} ..."
git push -u "https://oauth2:${{ secrets.BOT_TOKEN }}@${REPO_URL#*://}" "${BRANCH_NAME}"
echo ""
echo "----"
echo "push=true" >> "$GITHUB_OUTPUT"
echo "head-branch=${BRANCH_NAME}" >> "$GITHUB_OUTPUT"
- name: Check for Pull Request
id: check-for-pull-request
if: steps.commit-push.outputs.push == 'true' && steps.mode.outputs.is-automerge == 'false'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
HEAD_BRANCH: ${{ steps.commit-push.outputs.head-branch }}
run: |
cd "${MANIFEST_DIR}"
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls?base_branch=${BASE_BRANCH}&state=open&page=1"
echo ">> Checking if PR from branch ${HEAD_BRANCH} into ${BASE_BRANCH}"
echo ">> With Endpoint of:"
echo "$API_ENDPOINT"
HTTP_STATUS=$(curl -X GET -s -w '%{http_code}' -o response_body.json -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" "$API_ENDPOINT")
if [ "$HTTP_STATUS" == "200" ] && [ "$(cat response_body.json | jq -r .[0].state)" == "open" ]; then
echo ""
echo ">> Pull Request has been found open, will update"
echo ""
echo "----"
echo "pull-request-exists=$(cat response_body.json | jq -r .[0].number)" >> "$GITHUB_OUTPUT"
else
echo ""
echo ">> Pull Request not found"
echo ""
echo "----"
echo "pull-request-exists=false" >> "$GITHUB_OUTPUT"
fi
- name: Create Pull Request
id: create-pull-request
if: steps.commit-push.outputs.push == 'true' && (steps.mode.outputs.is-automerge == 'true' || steps.check-for-pull-request.outputs.pull-request-exists == 'false')
env:
IS_AUTOMERGE: ${{ steps.mode.outputs.is-automerge }}
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
HEAD_BRANCH: ${{ steps.commit-push.outputs.head-branch }}
CHARTS: ${{ steps.check-changes.outputs.changed-charts-csv }}
EVENT_NAME: ${{ github.event_name }}
ACTOR: ${{ github.actor }}
SHA: ${{ github.sha }}
REF: ${{ github.ref_name }}
run: |
cd "${MANIFEST_DIR}"
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls"
BODY=$(printf "This PR contains newly rendered Kubernetes manifests automatically generated by the CI workflow.\n\n### Details\n- **Trigger**: \`%s\` by \`@%s\`\n- **Commit**: \`%s\` (on \`%s\`)\n- **Charts Updated**: \`%s\`" "${EVENT_NAME}" "${ACTOR}" "${SHA:0:7}" "${REF}" "${CHARTS}")
if [[ "$IS_AUTOMERGE" == "true" ]]; then
TITLE="Automated Manifest Update - Automerge"
BODY=$(printf "%s\n\n_This PR is expected to be automerged._" "${BODY}")
else
TITLE="Automated Manifest Update"
fi
PAYLOAD=$(jq -n --arg head "${HEAD_BRANCH}" --arg base "${BASE_BRANCH}" --arg assignee "${ASSIGNEE}" --arg title "${TITLE}" --arg body "${BODY}" '{head: $head, base: $base, assignee: $assignee, title: $title, body: $body}')
HTTP_STATUS=$(curl -X POST -s -w '%{http_code}' -o response_body.json --data "$PAYLOAD" -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" "$API_ENDPOINT")
if [ "$HTTP_STATUS" == "201" ]; then
echo ">> Pull Request created successfully!"
echo ""
echo "----"
echo "pull-request-id=$(jq -r .id response_body.json)" >> "$GITHUB_OUTPUT"
echo "pull-request-number=$(jq -r .number response_body.json)" >> "$GITHUB_OUTPUT"
echo "pull-request-operation=created" >> "$GITHUB_OUTPUT"
elif [[ "$HTTP_STATUS" == "422" || "$HTTP_STATUS" == "409" ]]; then
echo ""
echo ">> Failed to create PR (Already exists)"
echo ""
echo "----"
else
echo ""
echo ">> Failed to create PR, HTTP status code: $HTTP_STATUS"
echo ""
echo "----"
exit 1
fi
- name: Update Pull Request
id: update-pull-request
if: steps.commit-push.outputs.push == 'true' && steps.check-for-pull-request.outputs.pull-request-exists != 'false' && steps.mode.outputs.is-automerge == 'false'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
PR_NUMBER: ${{ steps.check-for-pull-request.outputs.pull-request-exists }}
CHARTS: ${{ steps.check-changes.outputs.changed-charts-csv }}
EVENT_NAME: ${{ github.event_name }}
ACTOR: ${{ github.actor }}
SHA: ${{ github.sha }}
REF: ${{ github.ref_name }}
run: |
cd "${MANIFEST_DIR}"
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls/${PR_NUMBER}"
EXISTING_BODY=$(jq -r '.[0].body' response_body.json)
NEW_DETAILS=$(printf "### Update Details (%s)\n- **Trigger**: \`%s\` by \`@%s\`\n- **Commit**: \`%s\` (on \`%s\`)\n- **Charts Updated**: \`%s\`" "$(date -u +'%Y-%m-%d %H:%M UTC')" "${EVENT_NAME}" "${ACTOR}" "${SHA:0:7}" "${REF}" "${CHARTS}")
UPDATED_BODY=$(printf "%s\n\n%s" "${EXISTING_BODY}" "${NEW_DETAILS}")
PAYLOAD=$(jq -n --arg body "${UPDATED_BODY}" '{body: $body}')
HTTP_STATUS=$(curl -X PATCH -s -w '%{http_code}' -o update_response.json --data "$PAYLOAD" -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" "$API_ENDPOINT")
if [ "$HTTP_STATUS" == "201" ] || [ "$HTTP_STATUS" == "200" ]; then
echo ">> Pull Request updated successfully!"
echo ""
echo "----"
echo "pull-request-operation=updated" >> "$GITHUB_OUTPUT"
else
echo ">> Failed to update PR, HTTP status code: $HTTP_STATUS"; exit 1
echo ""
echo "----"
fi
- name: Merge Changes
id: merge-changes
if: steps.commit-push.outputs.push == 'true' && steps.mode.outputs.is-automerge == 'true'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
GITEA_URL: ${{ secrets.REPO_URL }}
PR_NUMBER: ${{ steps.create-pull-request.outputs.pull-request-number }}
run: |
cd "${MANIFEST_DIR}"
API_ENDPOINT="${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/pulls/${PR_NUMBER}/merge"
PAYLOAD=$(jq -n --arg Do "merge" '{Do: $Do}')
HTTP_STATUS=$(curl -X POST -s -w '%{http_code}' -o response_body.json --data "$PAYLOAD" -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" "$API_ENDPOINT")
if [ "$HTTP_STATUS" == "200" ]; then
echo ">> Pull Request merged successfully!"
echo ""
echo "----"
echo "pull-request-operation=merged" >> "$GITHUB_OUTPUT"
else
echo ">> Failed to merge PR, HTTP status code: $HTTP_STATUS"; exit 1
echo ""
echo "----"
fi
- name: Cleanup Branch
if: failure() && steps.mode.outputs.is-automerge == 'true'
env:
BRANCH_NAME: ${{ steps.prepare-manifest-branch.outputs.branch-name }}
run: |
cd "${MANIFEST_DIR}"
echo ">> Removing branch: ${BRANCH_NAME}"
git push origin --delete "${BRANCH_NAME}" || true
echo ""
echo "----"
- name: ntfy Created
uses: niniyas/ntfy-action@96acac57fdc91d4c4f50b78486c1ed6f03f9f61c # master
if: steps.create-pull-request.outputs.pull-request-operation == 'created' && steps.mode.outputs.is-automerge == 'false'
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render - Open PR"
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,successfully,completed
details: "Created renderd manifests for cluster '${{ env.CLUSTER }}' with charts: ${{ steps.check-changes.outputs.changed-charts-csv }}"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "View PR", "url": "${{ vars.USER_URL }}/${{ github.repository }}/pulls/${{ steps.create-pull-request.outputs.pull-request-number }}", "clear": true}]'
- name: ntfy Updated
uses: niniyas/ntfy-action@96acac57fdc91d4c4f50b78486c1ed6f03f9f61c # master
if: steps.commit-push.outputs.push == 'true' && steps.check-for-pull-request.outputs.pull-request-exists != 'false' && steps.mode.outputs.is-automerge == 'false'
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render - PR Updated"
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,successfully,completed
details: "Updated rendered manifests PR for cluster '${{ env.CLUSTER }}' with charts: ${{ steps.check-changes.outputs.changed-charts-csv }}"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "View PR", "url": "${{ vars.USER_URL }}/${{ github.repository }}/pulls/${{ steps.create-pull-request.outputs.pull-request-number }}", "clear": true}]'
- name: ntfy Merged
uses: niniyas/ntfy-action@96acac57fdc91d4c4f50b78486c1ed6f03f9f61c # master
if: steps.merge-changes.outputs.pull-request-operation == 'merged'
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render - Automerged"
priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,successfully,completed
details: "Automerged manifest rendering for cluster '${{ env.CLUSTER }}' with charts: ${{ steps.check-changes.outputs.changed-charts-csv }}"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "View PR", "url": "${{ vars.USER_URL }}/${{ github.repository }}/pulls/${{ steps.create-pull-request.outputs.pull-request-number }}", "clear": true}]'
- name: ntfy Failed
uses: niniyas/ntfy-action@96acac57fdc91d4c4f50b78486c1ed6f03f9f61c # master
if: failure()
with:
url: "${{ secrets.NTFY_URL }}"
topic: "${{ secrets.NTFY_TOPIC }}"
title: "Manifest Render Failure"
priority: 4
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,failed
details: "Manifest rendering for Infrastructure has failed!"
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/gitea.png"
actions: '[{"action": "view", "label": "View Logs", "url": "${{ vars.USER_URL }}/${{ github.repository }}/actions/runs/${{ github.run_id }}", "clear": true}]'

View File

@@ -13,10 +13,10 @@ on:
jobs:
renovate:
runs-on: ubuntu-latest
container: ghcr.io/renovatebot/renovate:43.84.2@sha256:92285747b3aac062a4f567762c272a12dce037843a20177a02c95b7c420e20cb
container: ghcr.io/renovatebot/renovate:43
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@v6
- name: Renovate
run: renovate
@@ -25,7 +25,7 @@ jobs:
RENOVATE_ENDPOINT: ${{ vars.INSTANCE_URL }}
RENOVATE_REPOSITORIES: alexlebens/infrastructure
RENOVATE_GIT_AUTHOR: Renovate Bot <renovate-bot@alexlebens.net>
LOG_LEVEL: debug
LOG_LEVEL: info
RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }}
RENOVATE_GIT_PRIVATE_KEY: ${{ secrets.RENOVATE_GIT_PRIVATE_KEY }}
RENOVATE_GITHUB_COM_TOKEN: ${{ secrets.RENOVATE_GITHUB_COM_TOKEN }}

View File

@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
rev: v2.3.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
@@ -9,9 +9,7 @@ repos:
exclude: '^.*\/templates\/.*$'
args:
- --multi
- id: check-merge-conflict
- id: check-json
- repo: https://github.com/IamTheFij/docker-pre-commit
rev: v3.0.1
rev: v2.0.0
hooks:
- id: docker-compose-check

View File

@@ -5,12 +5,11 @@ description: Actual
keywords:
- actual
- budget
home: https://docs.alexlebens.dev/applications/actual/
home: https://wiki.alexlebens.dev/s/86192f45-94b7-45de-872c-6ef3fec7df5e
sources:
- https://github.com/actualbudget/actual
- https://github.com/actualbudget/actual/pkgs/container/actual
- https://github.com/bjw-s-labs/helm-charts/tree/main/charts/other/app-template
- https://gitea.alexlebens.dev/alexlebens/helm-charts/src/branch/main/charts/volsync-target
maintainers:
- name: alexlebens
dependencies:

View File

@@ -4,18 +4,20 @@ actual:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
containers:
main:
image:
repository: ghcr.io/actualbudget/actual
tag: 26.3.0@sha256:eb8bc26f53025e07e464594c12d77c52c4b95840c8dadd9b95c4f0c4660f8ad2
tag: 26.3.0
pullPolicy: IfNotPresent
env:
- name: ACTUAL_PORT
value: 5006
- name: TZ
value: US/Central
resources:
requests:
cpu: 25m
memory: 64Mi
cpu: 10m
memory: 128Mi
probes:
liveness:
enabled: true
@@ -52,8 +54,11 @@ actual:
- actual.alexlebens.net
rules:
- backendRefs:
- name: actual
- group: ''
kind: Service
name: actual
port: 80
weight: 100
matches:
- path:
type: PathPrefix
@@ -64,6 +69,7 @@ actual:
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 2Gi
retain: true
advancedMounts:
main:
main:

View File

@@ -1,12 +1,12 @@
dependencies:
- name: argo-workflows
repository: https://argoproj.github.io/argo-helm
version: 1.0.5
version: 0.47.5
- name: argo-events
repository: https://argoproj.github.io/argo-helm
version: 2.4.21
version: 2.4.20
- name: postgres-cluster
repository: oci://harbor.alexlebens.net/helm-charts
version: 7.10.0
digest: sha256:d0d7ebf1c0013d001aa2f17d04a6d3f3d7a1fa7d5c62792eef856b87c24eb26e
generated: "2026-03-20T20:48:30.830922259Z"
version: 7.9.1
digest: sha256:5b7f498040dd93f99a00c708c80fcefdb64dcdf473cfd3edcf8a94255b80b3b4
generated: "2026-03-12T13:02:52.109982708Z"

View File

@@ -7,26 +7,26 @@ keywords:
- argo-events
- workflows
- events
home: https://docs.alexlebens.dev/applications/argo-workflows/
home: https://wiki.alexlebens.dev/s/a268508f-d81d-4b4b-8bd5-9058edaea635
sources:
- https://github.com/argoproj/argo-workflows
- https://github.com/argoproj/argo-events
- https://github.com/argoproj/argo-helm/tree/main/charts/argo-workflows
- https://github.com/argoproj/argo-helm/tree/main/charts/argo-events
- https://github.com/cloudnative-pg/cloudnative-pg
- https://github.com/argoproj/argo-helm/tree/main/charts
- https://gitea.alexlebens.dev/alexlebens/helm-charts/src/branch/main/charts/postgres-cluster
maintainers:
- name: alexlebens
dependencies:
- name: argo-workflows
version: 1.0.5
version: 0.47.5
repository: https://argoproj.github.io/argo-helm
- name: argo-events
version: 2.4.21
version: 2.4.20
repository: https://argoproj.github.io/argo-helm
- name: postgres-cluster
alias: postgres-18-cluster
version: 7.10.0
version: 7.9.1
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/argo-cd.png
# renovate: datasource=github-releases depName=argoproj/argo-workflows
appVersion: v4.0.3
appVersion: v4.0.2

View File

@@ -14,9 +14,15 @@ spec:
data:
- secretKey: secret
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /authentik/oidc/argo-workflows
metadataPolicy: None
property: secret
- secretKey: client
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /authentik/oidc/argo-workflows
metadataPolicy: None
property: client

View File

@@ -0,0 +1,28 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: argo-workflows
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: argo-workflows
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- argo-workflows.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ''
kind: Service
name: argo-workflows-server
port: 2746
weight: 100

View File

@@ -1,16 +1,13 @@
argo-workflows:
crds:
install: true
keep: true
full: true
upgradeJob:
image:
repository: registry.k8s.io/kubectl
tag: v1.35.3
controller:
metricsConfig:
enabled: true
persistence:
connectionPool:
maxIdleConns: 100
maxOpenConns: 0
nodeStatusOffLoad: true
archive: true
postgresql:
host: argo-workflows-postgresql-18-cluster-rw
port: 5432
@@ -25,34 +22,24 @@ argo-workflows:
ssl: false
sslMode: disable
workflowWorkers: 2
workflowTTLWorkers: 2
podCleanupWorkers: 2
cronWorkflowWorkers: 2
workflowTTLWorkers: 1
podCleanupWorkers: 1
cronWorkflowWorkers: 1
resources:
requests:
cpu: 10m
memory: 32Mi
memory: 128Mi
serviceMonitor:
enabled: true
name: workflow-controller
workflowNamespaces:
- argocd
- argo-workflows
server:
authModes:
- sso
httproute:
enabled: true
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- argo-workflows.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
ingress:
enabled: false
sso:
enabled: true
issuer: https://authentik.alexlebens.net/application/o/argo-workflows/
@@ -69,15 +56,15 @@ argo-workflows:
- openid
- email
- profile
useStaticCredentials: true
artifactRepository:
archiveLogs: false
argo-events:
crds:
install: true
keep: true
controller:
resources:
requests:
cpu: 10m
memory: 32Mi
memory: 128Mi
metrics:
enabled: true
serviceMonitor:
@@ -87,7 +74,7 @@ argo-events:
resources:
requests:
cpu: 10m
memory: 32Mi
memory: 128Mi
postgres-18-cluster:
mode: recovery
recovery:
@@ -101,9 +88,32 @@ postgres-18-cluster:
destinationBucket: postgres-backups
externalSecretCredentialPath: /garage/home-infra/postgres-backups
isWALArchiver: true
# - name: garage-remote
# index: 1
# destinationBucket: postgres-backups
# externalSecretCredentialPath: /garage/home-infra/postgres-backups
# retentionPolicy: "90d"
# data:
# compression: bzip2
# - name: external
# index: 1
# endpointURL: https://nyc3.digitaloceanspaces.com
# destinationBucket: postgres-backups-ce540ddf106d186bbddca68a
# externalSecretCredentialPath: /garage/home-infra/postgres-backups
# isWALArchiver: false
scheduledBackups:
- name: live-backup
suspend: false
immediate: true
schedule: "0 0 14 * * *"
backupName: garage-local
# - name: weekly-backup
# suspend: true
# immediate: true
# schedule: "0 0 4 * * SAT"
# backupName: garage-remote
# - name: daily-backup
# suspend: true
# immediate: true
# schedule: "0 0 0 * * *"
# backupName: external

View File

@@ -1,6 +1,6 @@
dependencies:
- name: argo-cd
repository: https://argoproj.github.io/argo-helm
version: 9.4.15
digest: sha256:a0eed2e174bb6b13d04653c755a359025b050d479a92180039a1990dd8ee7caa
generated: "2026-03-20T01:09:07.547016465Z"
version: 9.4.10
digest: sha256:795aad956acef3f5efb8160390caf9b9792b7b4150d3a7984f1c5edbad92dfaa
generated: "2026-03-10T18:58:35.720448421Z"

View File

@@ -4,8 +4,10 @@ version: 1.0.0
description: Argo CD
keywords:
- argo-cd
- delivery
- deployment
home: https://docs.alexlebens.dev/applications/argo-cd/
- gitops
home: https://wiki.alexlebens.dev/s/8a75cf26-b9df-437e-9cc5-2ef47e871a5f
sources:
- https://github.com/argoproj/argo-cd
- https://github.com/argoproj/argo-helm/tree/main/charts/argo-cd
@@ -13,8 +15,8 @@ maintainers:
- name: alexlebens
dependencies:
- name: argo-cd
version: 9.4.15
version: 9.4.10
repository: https://argoproj.github.io/argo-helm
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/argo-cd.png
# renovate: datasource=github-releases depName=argoproj/argo-cd
appVersion: v3.3.4
appVersion: v3.3.3

View File

@@ -14,11 +14,17 @@ spec:
data:
- secretKey: secret
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /authentik/oidc/argocd
metadataPolicy: None
property: secret
- secretKey: client
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /authentik/oidc/argocd
metadataPolicy: None
property: client
---
@@ -38,7 +44,10 @@ spec:
data:
- secretKey: ntfy-token
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /ntfy/user/cl01tl
metadataPolicy: None
property: token
---
@@ -58,13 +67,22 @@ spec:
data:
- secretKey: type
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/argocd/credentials/repo/infrastructure
metadataPolicy: None
property: type
- secretKey: url
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/argocd/credentials/repo/infrastructure
metadataPolicy: None
property: url
- secretKey: sshPrivateKey
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/argocd/credentials/repo/infrastructure
metadataPolicy: None
property: sshPrivateKey

View File

@@ -1,11 +1,12 @@
argo-cd:
crds:
install: true
keep: true
configs:
cm:
admin.enabled: true
accounts.homepage: apiKey
timeout.reconciliation: 100s
timeout.reconciliation.jitter: 60s
url: https://argocd.alexlebens.net
statusbadge.url: https://argocd.alexlebens.net/
statusbadge.enabled: true
@@ -32,53 +33,12 @@ argo-cd:
g, homepage, role:readonly
controller:
replicas: 1
resources:
requests:
cpu: 15m
memory: 1Gi
readinessProbe:
failureThreshold: 3
initialDelaySeconds: 60
periodSeconds: 30
successThreshold: 1
timeoutSeconds: 5
metrics:
enabled: true
serviceMonitor:
enabled: true
rules:
enabled: true
spec:
- alert: ArgoAppMissing
expr: |
absent(argocd_app_info) == 1
for: 15m
labels:
severity: critical
annotations:
summary: "[Argo CD] No reported applications"
description: >
Argo CD has not reported any applications data for the past 15 minutes which
means that it must be down or not functioning properly. This needs to be
resolved for this cloud to continue to maintain state.
- alert: ArgoAppNotSynced
expr: |
argocd_app_info{sync_status!="Synced"} == 1
for: 12h
labels:
severity: warning
annotations:
summary: "[{{`{{$labels.name}}`}}] Application not synchronized"
description: >
The application [{{`{{$labels.name}}`}} has not been synchronized for over
12 hours which means that the state of this cloud has drifted away from the
state inside Git.
dex:
enabled: true
resources:
requests:
cpu: 10m
memory: 64Mi
metrics:
enabled: true
serviceMonitor:
@@ -89,57 +49,20 @@ argo-cd:
enabled: true
redis-ha:
enabled: true
image:
repository: redis
tag: 8.6.1-alpine@sha256:315270d166080f537bbdf1b489b603aaaa213cb55a544acfa51feb7481abb1c0
persistentVolume:
enabled: true
redis:
resources:
requests:
cpu: 1000m
memory: 64Mi
haproxy:
enabled: true
image:
repository: haproxy
tag: 3.3.6-alpine@sha256:744be2dca649a44d490a4c565d36968d19482dd387f1bdd44c168f4322bc6b1e
resources:
requests:
cpu: 10m
memory: 128Mi
metrics:
enabled: true
serviceMonitor:
enabled: true
exporter:
enabled: true
image: ghcr.io/oliver006/redis_exporter
tag: v1.82.0@sha256:6a97d4dd743b533e1f950c677b87d880e44df363c61af3f406fc9e53ed65ee03
serviceMonitor:
enabled: true
prometheusRule:
enabled: true
interval: 30s
rules:
- alert: RedisPodDown
expr: |
redis_up{job="{{ include "redis-ha.fullname" . }}"} == 0
for: 5m
labels:
severity: critical
annotations:
description: Redis pod {{ "{{ $labels.pod }}" }} is down
summary: Redis pod {{ "{{ $labels.pod }}" }} is down
auth: false
redisSecretInit:
enabled: false
server:
replicas: 2
resources:
requests:
cpu: 10m
memory: 64Mi
extensions:
enabled: true
extensionList:
- name: extension-trivy
env:
- name: EXTENSION_URL
value: https://github.com/mziyabo/argocd-trivy-extension/releases/download/v0.2.0/extension-trivy.tar
- name: EXTENSION_CHECKSUM_URL
value: https://github.com/mziyabo/argocd-trivy-extension/releases/download/v0.2.0/extension-trivy_checksums.txt
metrics:
enabled: true
serviceMonitor:
@@ -153,56 +76,31 @@ argo-cd:
namespace: traefik
hostnames:
- argocd.alexlebens.net
rules:
- matches:
- path:
type: PathPrefix
value: /
repoServer:
replicas: 2
resources:
requests:
cpu: 10m
memory: 64Mi
readinessProbe:
enabled: true
failureThreshold: 3
initialDelaySeconds: 60
periodSeconds: 30
successThreshold: 1
timeoutSeconds: 5
livenessProbe:
enabled: true
failureThreshold: 3
initialDelaySeconds: 60
periodSeconds: 30
successThreshold: 1
timeoutSeconds: 5
metrics:
enabled: true
serviceMonitor:
enabled: true
applicationSet:
replicas: 2
resources:
requests:
cpu: 10m
memory: 64Mi
metrics:
enabled: true
serviceMonitor:
enabled: true
readinessProbe:
enabled: true
failureThreshold: 3
initialDelaySeconds: 60
periodSeconds: 30
successThreshold: 1
timeoutSeconds: 5
livenessProbe:
enabled: true
failureThreshold: 3
initialDelaySeconds: 60
periodSeconds: 30
successThreshold: 1
timeoutSeconds: 5
readinessProbe:
enabled: true
notifications:
argocdUrl: https://argocd.alexlebens.net
enabled: true
context:
argocdUrl: https://argocd.alexlebens.net
secret:
create: false
name: argocd-notifications-secret
@@ -216,10 +114,6 @@ argo-cd:
headers:
- name: Authorization
value: Bearer $ntfy-token
resources:
requests:
cpu: 10m
memory: 64Mi
livenessProbe:
enabled: true
readinessProbe:

View File

@@ -7,14 +7,11 @@ keywords:
- books
- podcasts
- audiobooks
home: https://docs.alexlebens.dev/applications/audiobookshelf/
home: https://wiki.alexlebens.dev/s/d4d6719f-cd1c-4b6e-b78e-2d2d7a5097d7
sources:
- https://github.com/advplyr/audiobookshelf
- https://github.com/caronc/apprise
- https://github.com/advplyr/audiobookshelf/pkgs/container/audiobookshelf
- https://github.com/caronc/apprise-api/pkgs/container/apprise
- https://github.com/bjw-s-labs/helm-charts/tree/main/charts/other/app-template
- https://gitea.alexlebens.dev/alexlebens/helm-charts/src/branch/main/charts/volsync-target
maintainers:
- name: alexlebens
dependencies:
@@ -32,4 +29,4 @@ dependencies:
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/audiobookshelf.png
# renovate: datasource=github-releases depName=advplyr/audiobookshelf
appVersion: 2.33.1
appVersion: 2.32.1

View File

@@ -14,5 +14,8 @@ spec:
data:
- secretKey: ntfy-url
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/audiobookshelf/apprise
metadataPolicy: None
property: ntfy-url

View File

@@ -4,25 +4,28 @@ audiobookshelf:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
containers:
main:
image:
repository: ghcr.io/advplyr/audiobookshelf
tag: 2.33.1@sha256:a4a5841bba093d81e5f4ad1eaedb4da3fda6dbb2528c552349da50ad1f7ae708
tag: 2.32.1
pullPolicy: IfNotPresent
env:
- name: TZ
value: America/Chicago
value: US/Central
resources:
requests:
cpu: 10m
memory: 200Mi
memory: 128Mi
apprise-api:
image:
repository: ghcr.io/caronc/apprise
tag: v1.3.2@sha256:1aafc2118b6eae5d70d17831d9a8a52adee7104fd6f2bb018e6421664699c903
repository: caronc/apprise
tag: v1.3.2
pullPolicy: IfNotPresent
env:
- name: TZ
value: America/Chicago
value: US/Central
- name: PGID
value: "1000"
- name: PUID
@@ -38,6 +41,10 @@ audiobookshelf:
secretKeyRef:
name: audiobookshelf-apprise-config
key: ntfy-url
resources:
requests:
cpu: 10m
memory: 128Mi
service:
main:
controller: main
@@ -75,8 +82,11 @@ audiobookshelf:
- audiobookshelf.alexlebens.net
rules:
- backendRefs:
- name: audiobookshelf
- group: ''
kind: Service
name: audiobookshelf
port: 80
weight: 100
matches:
- path:
type: PathPrefix
@@ -87,6 +97,7 @@ audiobookshelf:
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 2Gi
retain: true
advancedMounts:
main:
main:
@@ -97,6 +108,7 @@ audiobookshelf:
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 10Gi
retain: true
advancedMounts:
main:
main:

View File

@@ -7,9 +7,9 @@ dependencies:
version: 2.4.0
- name: postgres-cluster
repository: oci://harbor.alexlebens.net/helm-charts
version: 7.10.0
version: 7.9.1
- name: valkey
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.4.0
digest: sha256:8c353c5dad4c3d04d518c1445497f0d1cb64261a4201ae17a2c0874454b807a7
generated: "2026-03-15T20:04:35.99407071Z"
digest: sha256:abb34b7bb54393236e695453aa1940497cb4def3d3a56a45ca004a22f8e05648
generated: "2026-03-11T22:55:49.936164674Z"

View File

@@ -6,14 +6,17 @@ keywords:
- authentik
- sso
- oidc
- ldap
- idp
- authentication
home: https://docs.alexlebens.dev/applications/authentik/
home: https://wiki.alexlebens.dev/s/45ca5171-581f-41d2-b6fb-2b0915029a2d
sources:
- https://github.com/goauthentik/authentik
- https://github.com/cloudflare/cloudflared
- https://github.com/cloudnative-pg/cloudnative-pg
- https://github.com/goauthentik/helm
- https://gitea.alexlebens.dev/alexlebens/helm-charts/src/branch/main/charts/cloudflared
- https://gitea.alexlebens.dev/alexlebens/helm-charts/src/branch/main/charts/postgres-cluster
- https://gitea.alexlebens.dev/alexlebens/helm-charts/src/branch/main/charts/valkey
maintainers:
- name: alexlebens
dependencies:
@@ -25,7 +28,7 @@ dependencies:
version: 2.4.0
- name: postgres-cluster
alias: postgres-18-cluster
version: 7.10.0
version: 7.9.1
repository: oci://harbor.alexlebens.net/helm-charts
- name: valkey
alias: valkey

View File

@@ -14,5 +14,8 @@ spec:
data:
- secretKey: key
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/authentik/key
metadataPolicy: None
property: key

View File

@@ -30,23 +30,8 @@ authentik:
redis:
host: authentik-valkey
server:
replicas: 2
resources:
requests:
cpu: 100m
memory: 700Mi
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 15
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
readinessProbe:
failureThreshold: 3
initialDelaySeconds: 15
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
name: server
replicas: 1
metrics:
enabled: true
serviceMonitor:
@@ -54,6 +39,8 @@ authentik:
route:
main:
enabled: true
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
hostnames:
- authentik.alexlebens.net
parentRefs:
@@ -61,20 +48,21 @@ authentik:
kind: Gateway
name: traefik-gateway
namespace: traefik
httpsRedirect: false
matches:
- path:
type: PathPrefix
value: /
worker:
name: worker
replicas: 2
resources:
requests:
cpu: 100m
memory: 512Mi
metrics:
enabled: true
serviceMonitor:
enabled: true
replicas: 1
prometheus:
rules:
enabled: true
postgresql:
enabled: false
redis:
enabled: false
postgres-18-cluster:
mode: recovery
recovery:
@@ -88,9 +76,32 @@ postgres-18-cluster:
destinationBucket: postgres-backups
externalSecretCredentialPath: /garage/home-infra/postgres-backups
isWALArchiver: true
# - name: garage-remote
# index: 1
# destinationBucket: postgres-backups
# externalSecretCredentialPath: /garage/home-infra/postgres-backups
# retentionPolicy: "90d"
# data:
# compression: bzip2
# - name: external
# index: 1
# endpointURL: https://nyc3.digitaloceanspaces.com
# destinationBucket: postgres-backups-ce540ddf106d186bbddca68a
# externalSecretCredentialPath: /garage/home-infra/postgres-backups
# isWALArchiver: false
scheduledBackups:
- name: live-backup
suspend: false
immediate: true
schedule: "0 5 14 * * *"
backupName: garage-local
# - name: weekly-backup
# suspend: true
# immediate: true
# schedule: "0 0 4 * * SAT"
# backupName: garage-remote
# - name: daily-backup
# suspend: true
# immediate: true
# schedule: "0 0 0 * * *"
# backupName: external

View File

@@ -5,12 +5,11 @@ description: backrest
keywords:
- backrest
- backup
home: https://docs.alexlebens.dev/applications/backrest/
home: https://wiki.alexlebens.dev/
sources:
- https://github.com/garethgeorge/backrest
- https://github.com/garethgeorge/backrest/pkgs/container/backrest
- https://hub.docker.com/r/garethgeorge/backrest
- https://github.com/bjw-s-labs/helm-charts/tree/main/charts/other/app-template
- https://gitea.alexlebens.dev/alexlebens/helm-charts/src/branch/main/charts/volsync-target
maintainers:
- name: alexlebens
dependencies:

View File

@@ -7,8 +7,9 @@ backrest:
containers:
main:
image:
repository: ghcr.io/garethgeorge/backrest
tag: v1.12.1@sha256:f4d34bd6fa985d13bdb6c01c5d8727e07708899afa9567d800808357d77b9fb0
repository: garethgeorge/backrest
tag: v1.12.1
pullPolicy: IfNotPresent
env:
- name: TZ
value: America/Chicago
@@ -23,7 +24,7 @@ backrest:
resources:
requests:
cpu: 10m
memory: 80Mi
memory: 256Mi
service:
main:
controller: main
@@ -32,19 +33,6 @@ backrest:
port: 80
targetPort: 9898
protocol: TCP
serviceMonitor:
main:
selector:
matchLabels:
app.kubernetes.io/name: backrest
app.kubernetes.io/instance: backrest
serviceName: '{{ include "bjw-s.common.lib.chart.names.fullname" $ }}'
endpoints:
- port: http
scheme: http
path: /metrics
interval: 300s
scrapeTimeout: 15s
route:
main:
kind: HTTPRoute
@@ -57,8 +45,11 @@ backrest:
- backrest.alexlebens.net
rules:
- backendRefs:
- name: backrest
- group: ''
kind: Service
name: backrest
port: 80
weight: 100
matches:
- path:
type: PathPrefix
@@ -69,6 +60,7 @@ backrest:
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 10Gi
retain: true
advancedMounts:
main:
main:
@@ -79,6 +71,7 @@ backrest:
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 1Gi
retain: true
advancedMounts:
main:
main:

View File

@@ -4,14 +4,14 @@ version: 1.0.0
description: Bazarr
keywords:
- bazarr
- servarr
- subtitles
home: https://docs.alexlebens.dev/applications/bazarr/
home: https://wiki.alexlebens.dev/s/92784d53-1d43-42fd-b509-f42c73454226
sources:
- https://github.com/morpheus65535/bazarr
- https://github.com/linuxserver/docker-bazarr
- https://github.com/linuxserver/docker-bazarr/pkgs/container/bazarr
- https://github.com/bjw-s-labs/helm-charts/tree/main/charts/other/app-template
- https://gitea.alexlebens.dev/alexlebens/helm-charts/src/branch/main/charts/volsync-target
maintainers:
- name: alexlebens
dependencies:

View File

@@ -4,6 +4,7 @@ bazarr:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
pod:
securityContext:
runAsUser: 1000
@@ -15,9 +16,10 @@ bazarr:
image:
repository: ghcr.io/linuxserver/bazarr
tag: 1.5.6@sha256:05f9d5b24884f37120453dc1a008a47be244eebec32099ae1bd29032e75b67aa
pullPolicy: IfNotPresent
env:
- name: TZ
value: America/Chicago
value: US/Central
- name: PUID
value: 1000
- name: PGID
@@ -46,8 +48,11 @@ bazarr:
- bazarr.alexlebens.net
rules:
- backendRefs:
- name: bazarr
- group: ''
kind: Service
name: bazarr
port: 80
weight: 100
matches:
- path:
type: PathPrefix
@@ -58,6 +63,7 @@ bazarr:
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 5Gi
retain: true
advancedMounts:
main:
main:

View File

@@ -5,12 +5,11 @@ description: Blocky
keywords:
- blocky
- dns
home: https://docs.alexlebens.dev/applications/blocky/
home: https://wiki.alexlebens.dev/s/cf70113d-20bc-48ad-afb8-1e22ed3fd62a
sources:
- https://github.com/0xERR0R/blocky
- https://github.com/0xERR0R/blocky/pkgs/container/blocky
- https://hub.docker.com/r/spx01/blocky
- https://github.com/bjw-s-labs/helm-charts/tree/main/charts/other/app-template
- https://gitea.alexlebens.dev/alexlebens/helm-charts/src/branch/main/charts/valkey
maintainers:
- name: alexlebens
dependencies:

View File

@@ -4,18 +4,20 @@ blocky:
type: deployment
replicas: 3
strategy: RollingUpdate
revisionHistoryLimit: 3
containers:
main:
image:
repository: ghcr.io/0xerr0r/blocky
tag: v0.29.0@sha256:a6d99f323d3036a99a3767a52ad612f4d8f3f31167492bfc14d4ea57b24cdfd0
pullPolicy: IfNotPresent
env:
- name: TZ
value: America/Chicago
value: US/Central
resources:
requests:
cpu: 10m
memory: 90Mi
memory: 128Mi
configMaps:
config:
enabled: true
@@ -96,7 +98,7 @@ blocky:
traefik-cl01tl IN A 10.232.1.21
blocky IN A 10.232.1.22
plex-lb IN A 10.232.1.23
cilium-cl01tl IN A 10.232.1.23
;; Application Names
@@ -115,7 +117,6 @@ blocky:
directus IN CNAME traefik-cl01tl
excalidraw IN CNAME traefik-cl01tl
feishin IN CNAME traefik-cl01tl
foldergram IN CNAME traefik-cl01tl
garage-s3 IN CNAME traefik-cl01tl
garage-webui IN CNAME traefik-cl01tl
gatus IN CNAME traefik-cl01tl
@@ -126,17 +127,14 @@ blocky:
home IN CNAME traefik-cl01tl
home-assistant IN CNAME traefik-cl01tl
home-assistant-code-server IN CNAME traefik-cl01tl
houndarr IN CNAME traefik-cl01tl
hubble IN CNAME traefik-cl01tl
immich IN CNAME traefik-cl01tl
jellyfin IN CNAME traefik-cl01tl
jellystat IN CNAME traefik-cl01tl
kiwix IN CNAME traefik-cl01tl
komodo IN CNAME traefik-cl01tl
languagetool IN CNAME traefik-cl01tl
lidarr IN CNAME traefik-cl01tl
mail IN CNAME traefik-cl01tl
medialyze IN CNAME traefik-cl01tl
movie-roulette IN CNAME traefik-cl01tl
music-grabber IN CNAME traefik-cl01tl
navidrome IN CNAME traefik-cl01tl

View File

@@ -4,12 +4,12 @@ dependencies:
version: 4.6.2
- name: mariadb-cluster
repository: https://helm.mariadb.com/mariadb-operator
version: 26.3.0
version: 25.10.4
- name: volsync-target
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.8.0
- name: volsync-target
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.8.0
digest: sha256:e65fa008c652092da5431e9780eb2a87c944298a12e58e432efad61c9e826da5
generated: "2026-03-14T23:57:22.721295098Z"
digest: sha256:d4c7bf75f72f7eab4ad968bf9f55daac9392c9b2df08f8a27c5dc4f8fffb5f57
generated: "2026-03-06T01:06:05.696573273Z"

View File

@@ -4,14 +4,11 @@ version: 1.0.0
description: booklore
keywords:
- booklore
- grimmory
- books
home: https://wiki.alexlebens.dev/
sources:
- https://github.com/booklore-app/BookLore
- https://github.com/grimmory-tools/grimmory
- https://github.com/booklore-app/booklore/pkgs/container/booklore
- https://github.com/grimmory-tools/grimmory/pkgs/container/grimmory
- https://github.com/bjw-s-labs/helm-charts/tree/main/charts/other/app-template
maintainers:
- name: alexlebens
@@ -21,7 +18,7 @@ dependencies:
repository: https://bjw-s-labs.github.io/helm-charts/
version: 4.6.2
- name: mariadb-cluster
version: 26.3.0
version: 25.10.4
repository: https://helm.mariadb.com/mariadb-operator
- name: volsync-target
alias: volsync-target-config
@@ -32,5 +29,5 @@ dependencies:
version: 0.8.0
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/booklore.png
# renovate: datasource=github-releases depName=grimmory-tools/grimmory
appVersion: v2.3.0
# renovate: datasource=github-releases depName=booklore-app/BookLore
appVersion: v2.2.0

View File

@@ -8,8 +8,8 @@ booklore:
containers:
main:
image:
repository: ghcr.io/grimmory-tools/grimmory
tag: v2.3.0
repository: ghcr.io/booklore-app/booklore
tag: v2.2.0
pullPolicy: IfNotPresent
env:
- name: TZ

View File

@@ -9,7 +9,7 @@ code-server:
main:
image:
repository: ghcr.io/linuxserver/code-server
tag: 4.112.0@sha256:4bb5b8ad22268001687c047f0f04933799fb03df1eb0e1e266ba15ed2d9f4e8b
tag: 4.110.0@sha256:8473aa16fba93fccc3ca772173d095bccd2e44d4d3104467fee923df10d57cd2
pullPolicy: IfNotPresent
env:
- name: TZ

View File

@@ -7,7 +7,7 @@ keywords:
- dns
- network
- kubernetes
home: https://wiki.alexlebens.dev/s/
home: https://wiki.alexlebens.dev/s/43947ec6-a034-449f-8c76-982ac493b072
sources:
- https://github.com/coredns/coredns
- https://github.com/coredns/helm

View File

@@ -1,7 +1,7 @@
coredns:
image:
repository: registry.k8s.io/coredns/coredns
tag: v1.14.2
tag: v1.14.1
replicaCount: 3
resources:
requests:

View File

@@ -4,9 +4,9 @@ dependencies:
version: 4.6.2
- name: postgres-cluster
repository: oci://harbor.alexlebens.net/helm-charts
version: 7.10.0
version: 7.9.1
- name: valkey
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.4.0
digest: sha256:7584c2a1613454bbd83b66df46170fd0157df5186842844d483e2dd131398574
generated: "2026-03-15T20:04:49.68456485Z"
digest: sha256:9524709cf393c01f28b0d073ef6870a2f1afd46f3bc5f564e73c55450aba8dd0
generated: "2026-03-11T22:56:11.749729235Z"

View File

@@ -18,7 +18,7 @@ dependencies:
version: 4.6.2
- name: postgres-cluster
alias: postgres-18-cluster
version: 7.10.0
version: 7.9.1
repository: oci://harbor.alexlebens.net/helm-charts
- name: valkey
alias: valkey
@@ -26,4 +26,4 @@ dependencies:
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://cdn.jsdelivr.net/gh/selfhst/icons@main/png/dawarich.png
# renovate: datasource=github-releases depName=Freika/dawarich
appVersion: 1.4.0
appVersion: 1.3.3

View File

@@ -9,7 +9,7 @@ dawarich:
main:
image:
repository: freikin/dawarich
tag: 1.4.0
tag: 1.3.3
pullPolicy: IfNotPresent
command: ["web-entrypoint.sh"]
args: ["bin/rails", "server", "-p", "3000", "-b", "::"]
@@ -106,7 +106,7 @@ dawarich:
sidekiq:
image:
repository: freikin/dawarich
tag: 1.4.0
tag: 1.3.3
pullPolicy: IfNotPresent
command: ["sidekiq-entrypoint.sh"]
args: ["sidekiq"]

View File

@@ -0,0 +1,6 @@
dependencies:
- name: app-template
repository: https://bjw-s-labs.github.io/helm-charts/
version: 4.6.2
digest: sha256:548ae1f8699100a2f6bac11a4a3137402b3eea340c7a3db4d9f1813ad6a11dca
generated: "2026-02-23T22:08:42.516245-06:00"

View File

@@ -0,0 +1,20 @@
apiVersion: v2
name: decluttarr
version: 1.0.0
description: decluttarr
keywords:
- decluttarr
- servarr
home: https://wiki.alexlebens.dev/s/
sources:
- https://github.com/ManiMatter/decluttarr
- https://github.com/bjw-s-labs/helm-charts/tree/main/charts/other/app-template
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: decluttarr
repository: https://bjw-s-labs.github.io/helm-charts/
version: 4.6.2
# renovate: datasource=github-releases depName=ManiMatter/decluttarr
appVersion: v2.0.0

View File

@@ -0,0 +1,21 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: decluttarr-config-secret
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: decluttarr-config-secret
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
data:
- secretKey: config.yaml
remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: /cl01tl/decluttarr/config
metadataPolicy: None
property: config.yaml

View File

@@ -0,0 +1,32 @@
decluttarr:
controllers:
main:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
containers:
main:
image:
repository: ghcr.io/manimatter/decluttarr
tag: v2.0.0
pullPolicy: IfNotPresent
env:
- name: TZ
value: America/Chicago
resources:
requests:
cpu: 10m
memory: 128Mi
persistence:
config:
enabled: true
type: secret
name: decluttarr-config-secret
advancedMounts:
main:
main:
- path: /app/config/config.yaml
readOnly: true
mountPropagation: None
subPath: config.yaml

View File

@@ -4,9 +4,9 @@ dependencies:
version: 4.6.2
- name: postgres-cluster
repository: oci://harbor.alexlebens.net/helm-charts
version: 7.10.0
version: 7.9.1
- name: valkey
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.4.0
digest: sha256:dfcb5d35e03ecdc4206227d206d36509319f0dcdaed54363840d71337debb3f7
generated: "2026-03-15T20:05:03.156596646Z"
digest: sha256:0b50b4938669a7210930d6ee86a9602611b54cd13774f3386dbad04b4771e7f4
generated: "2026-03-11T22:56:26.818980186Z"

View File

@@ -23,7 +23,7 @@ dependencies:
version: 4.6.2
- name: postgres-cluster
alias: postgres-18-cluster
version: 7.10.0
version: 7.9.1
repository: oci://harbor.alexlebens.net/helm-charts
- name: valkey
alias: valkey

View File

@@ -34,7 +34,27 @@ eraser:
request:
cpu: 100m
memory: 128Mi
config: ""
config: "" # |
# cacheDir: /var/lib/trivy
# dbRepo: ghcr.io/aquasecurity/trivy-db
# deleteFailedImages: true
# deleteEOLImages: true
# vulnerabilities:
# ignoreUnfixed: true
# types:
# - os
# - library
# securityChecks:
# - vuln
# severities:
# - CRITICAL
# - HIGH
# - MEDIUM
# - LOW
# ignoredStatuses:
# timeout:
# total: 23h
# perImage: 1h
remover:
request:
cpu: 10m

View File

@@ -1,6 +1,6 @@
dependencies:
- name: external-secrets
repository: https://charts.external-secrets.io
version: 2.2.0
digest: sha256:832fc3f8d3728bdea2b696a6044e4c18967cd9ab9c5cc74adbf40aaa270a84b4
generated: "2026-03-20T20:53:08.407747649Z"
version: 2.1.0
digest: sha256:b19563d51f1922403185979c6c442531a7bb13d302e8438b5a18d450259b7245
generated: "2026-03-07T18:02:23.908145348Z"

View File

@@ -12,8 +12,8 @@ sources:
- https://github.com/external-secrets/external-secrets/tree/main/deploy/charts/external-secrets
dependencies:
- name: external-secrets
version: 2.2.0
version: 2.1.0
repository: https://charts.external-secrets.io
icon: https://avatars.githubusercontent.com/u/68335991?s=48&v=4
# renovate: datasource=github-releases depName=external-secrets/external-secrets
appVersion: v2.2.0
appVersion: v2.1.0

View File

@@ -1,9 +0,0 @@
dependencies:
- name: app-template
repository: https://bjw-s-labs.github.io/helm-charts/
version: 4.6.2
- name: volsync-target
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.8.0
digest: sha256:59100c6fbfb829f9d703b9ee1cf869c4fd77b6ff53c63b0c644a757223027e58
generated: "2026-03-22T12:42:43.150705-05:00"

View File

@@ -1,25 +0,0 @@
apiVersion: v2
name: foldergram
version: 1.0.0
description: Foldergram
keywords:
- foldergram
- pictures
home: https://wiki.alexlebens.dev/
sources:
- https://github.com/foldergram/foldergram
- https://github.com/bjw-s-labs/helm-charts/tree/main/charts/other/app-template
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: foldergram
repository: https://bjw-s-labs.github.io/helm-charts/
version: 4.6.2
- name: volsync-target
alias: volsync-target-data
version: 0.8.0
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://raw.githubusercontent.com/foldergram/foldergram/refs/heads/main/client/public/icon-512.png
# renovate: datasource=github-releases depName=foldergram/foldergram
appVersion: v1.0.5

View File

@@ -1,17 +0,0 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: foldergram-pictures-nfs-storage
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: foldergram-pictures-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
volumeName: foldergram-pictures-nfs-storage
storageClassName: nfs-client
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi

View File

@@ -1,23 +0,0 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: foldergram-pictures-nfs-storage
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: foldergram-pictures-nfs-storage
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs-client
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
path: /volume2/Storage/Pictures
server: synologybond.alexlebens.net
mountOptions:
- vers=4
- minorversion=1
- noac

View File

@@ -1,87 +0,0 @@
foldergram:
controllers:
main:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
containers:
main:
image:
repository: ghcr.io/foldergram/foldergram
tag: 1.0.5
pullPolicy: IfNotPresent
env:
- name: IMAGE_DETAIL_SOURCE
value: original
- name: DERIVATIVE_MODE
value: lazy
- name: DATA_ROOT
value: ./data
- name: GALLERY_ROOT
value: /gallery
- name: CSRF_TRUSTED_ORIGINS
value: https://foldergram.alexlebens.net
resources:
requests:
cpu: 10m
memory: 128Mi
service:
main:
controller: main
ports:
http:
port: 80
targetPort: 4141
protocol: HTTP
route:
main:
kind: HTTPRoute
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- foldergram.alexlebens.net
rules:
- backendRefs:
- group: ''
kind: Service
name: foldergram
port: 80
weight: 100
matches:
- path:
type: PathPrefix
value: /
persistence:
cache:
forceRename: foldergram-data
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 10Gi
retain: false
advancedMounts:
main:
main:
- path: /app/data
readOnly: false
pictures:
existingClaim: foldergram-pictures-nfs-storage
advancedMounts:
main:
main:
- path: /gallery/pictures
readOnly: true
volsync-target-data:
pvcTarget: foldergram-data
local:
enabled: true
schedule: 46 11 * * *
remote:
enabled: true
schedule: 46 12 * * *
external:
enabled: true
schedule: 46 13 * * *

View File

@@ -7,9 +7,9 @@ dependencies:
version: 2.4.0
- name: postgres-cluster
repository: oci://harbor.alexlebens.net/helm-charts
version: 7.10.0
version: 7.9.1
- name: volsync-target
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.8.0
digest: sha256:a7bdbecd50433fedd65d3043102fe3c9e366dc98953c37eb0cfe762bce833e8e
generated: "2026-03-15T20:05:14.085780861Z"
digest: sha256:a3703e245881145524304af8a03c89d309c602479be3f7f8953c2fba120bf341
generated: "2026-03-11T22:56:41.856429843Z"

View File

@@ -26,7 +26,7 @@ dependencies:
version: 2.4.0
- name: postgres-cluster
alias: postgres-18-cluster
version: 7.10.0
version: 7.9.1
repository: oci://harbor.alexlebens.net/helm-charts
- name: volsync-target
alias: volsync-target-data

View File

@@ -34,7 +34,7 @@ garage:
debug:
image:
repository: ubuntu
tag: resolute-20260312
tag: resolute-20260108
pullPolicy: IfNotPresent
command:
- "sleep"

View File

@@ -4,9 +4,9 @@ dependencies:
version: 1.5.0
- name: postgres-cluster
repository: oci://harbor.alexlebens.net/helm-charts
version: 7.10.0
version: 7.9.1
- name: volsync-target
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.8.0
digest: sha256:83ec84774e0cc708f1cb5d83d657180159bfb75c9928784ebf0280e224b1cbca
generated: "2026-03-15T20:05:27.625292422Z"
digest: sha256:2fe7c088e99a11e0c6dd09fe48bb1e292eb58e22d9f8ff681bb6c6790945d54e
generated: "2026-03-11T22:56:56.957400817Z"

View File

@@ -22,7 +22,7 @@ dependencies:
version: 1.5.0
- name: postgres-cluster
alias: postgres-18-cluster
version: 7.10.0
version: 7.9.1
repository: oci://harbor.alexlebens.net/helm-charts
- name: volsync-target
alias: volsync-target-data

View File

@@ -161,9 +161,6 @@ gatus:
- name: photoview
url: https://photoview.alexlebens.net
<<: *defaults
- name: foldergram
url: https://foldergram.alexlebens.net
<<: *defaults
- name: booklore
url: https://booklore.alexlebens.net
<<: *defaults
@@ -194,9 +191,6 @@ gatus:
- name: excalidraw
url: https://excalidraw.alexlebens.net
<<: *defaults
- name: languagetool
url: https://languagetool.alexlebens.net
<<: *defaults
- name: gitea
url: https://gitea.alexlebens.net
<<: *defaults
@@ -233,9 +227,6 @@ gatus:
- name: jellystat
url: https://jellystat.alexlebens.net
<<: *defaults
- name: medialyze
url: https://medialyze.alexlebens.net
<<: *defaults
- name: authentik
url: https://authentik.alexlebens.net
<<: *defaults
@@ -310,9 +301,6 @@ gatus:
- name: tdarr
url: https://tdarr.alexlebens.net
<<: *defaults
- name: houndarr
url: https://houndarr.alexlebens.net
<<: *defaults
- name: sonarr
url: http://sonarr.sonarr:80
<<: *defaults

View File

@@ -1,6 +1,6 @@
dependencies:
- name: generic-device-plugin
repository: https://gitea.alexlebens.dev/api/packages/alexlebens/helm
version: 0.20.24
digest: sha256:36bf651c24198d299458046aaf449e9fb50942e1143389092a746357d402b731
generated: "2026-03-20T01:18:36.687250976Z"
version: 0.20.21
digest: sha256:4f1359a01b8b85722ab1805426a86f3ea64d0134513ce14fe9c55f3f918a21fb
generated: "2026-03-09T23:02:42.799515974Z"

View File

@@ -15,6 +15,6 @@ maintainers:
dependencies:
- name: generic-device-plugin
repository: https://gitea.alexlebens.dev/api/packages/alexlebens/helm
version: 0.20.24
version: 0.20.21
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/kubernetes.png
appVersion: 1.0.0

View File

@@ -7,13 +7,13 @@ dependencies:
version: 0.0.3
- name: meilisearch
repository: https://meilisearch.github.io/meilisearch-kubernetes
version: 0.28.0
version: 0.27.0
- name: cloudflared
repository: oci://harbor.alexlebens.net/helm-charts
version: 2.4.0
- name: postgres-cluster
repository: oci://harbor.alexlebens.net/helm-charts
version: 7.10.0
version: 7.9.1
- name: valkey
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.4.0
@@ -23,5 +23,5 @@ dependencies:
- name: volsync-target
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.8.0
digest: sha256:238b7653c9d12c4886a56350b6d66217dbe7ecbb76078a846c7cc2c8cb450eb3
generated: "2026-03-16T15:56:55.197735783Z"
digest: sha256:8f243465537fe443e97a8813e23e95d3608a6a2898b93209d03cf43f4ca8cc5d
generated: "2026-03-11T22:57:17.026946319Z"

View File

@@ -33,14 +33,14 @@ dependencies:
repository: https://dl.gitea.com/charts/
version: 0.0.3
- name: meilisearch
version: 0.28.0
version: 0.27.0
repository: https://meilisearch.github.io/meilisearch-kubernetes
- name: cloudflared
repository: oci://harbor.alexlebens.net/helm-charts
version: 2.4.0
- name: postgres-cluster
alias: postgres-18-cluster
version: 7.10.0
version: 7.9.1
repository: oci://harbor.alexlebens.net/helm-charts
- name: valkey
alias: valkey-gitea

View File

@@ -57,7 +57,6 @@ gitea:
ROOT_URL: https://gitea.alexlebens.dev
LOCAL_ROOT_URL: http://gitea-http.gitea.svc.cluster.local:3000
START_SSH_SERVER: true
HTTP_PORT: 3000
SSH_DOMAIN: gitea.alexlebens.net
SSH_PORT: 22
SSH_LISTEN_PORT: 22

View File

@@ -1,15 +1,15 @@
dependencies:
- name: grafana-operator
repository: https://grafana.github.io/helm-charts
version: 5.22.2
version: 5.22.0
- name: postgres-cluster
repository: oci://harbor.alexlebens.net/helm-charts
version: 7.10.0
version: 7.9.1
- name: valkey
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.4.0
- name: valkey
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.4.0
digest: sha256:a3bf183bcecb4d4b5354fe91a549075997dccb41c193da9daec9ccbe4d659fe2
generated: "2026-03-18T10:04:15.165729555Z"
digest: sha256:45cdb638fe815c3fc9703626b902d0f69ed8ffd0625e0f95bd7b33682126433b
generated: "2026-03-11T22:57:43.133815464Z"

View File

@@ -17,11 +17,11 @@ maintainers:
- name: alexlebens
dependencies:
- name: grafana-operator
version: 5.22.2
version: 5.22.0
repository: https://grafana.github.io/helm-charts
- name: postgres-cluster
alias: postgres-18-cluster
version: 7.10.0
version: 7.9.1
repository: oci://harbor.alexlebens.net/helm-charts
- name: valkey
alias: valkey-unified-alerting
@@ -33,4 +33,4 @@ dependencies:
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/grafana.png
# renovate: datasource=github-releases depName=grafana/grafana-operator
appVersion: v5.22.2
appVersion: v5.22.0

View File

@@ -362,10 +362,10 @@ spec:
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
name: grafana-dashboard-tdarr
name: grafana-dashboard-trivy
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: grafana-dashboard-tdarr
app.kubernetes.io/name: grafana-dashboard-trivy
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/part-of: {{ .Release.Name }}
spec:
@@ -375,7 +375,7 @@ spec:
contentCacheDuration: 1h
folderUID: grafana-folder-service
resyncPeriod: 1h
url: http://gitea-http.gitea:3000/alexlebens/grafana-dashboards/raw/branch/main/dashboards/service/tdarr.json
url: http://gitea-http.gitea:3000/alexlebens/grafana-dashboards/raw/branch/main/dashboards/service/trivy.json
---
apiVersion: grafana.integreatly.org/v1beta1

View File

@@ -1,12 +1,12 @@
dependencies:
- name: harbor
repository: https://helm.goharbor.io
version: 1.18.3
version: 1.18.2
- name: postgres-cluster
repository: https://gitea.alexlebens.net/api/packages/alexlebens/helm
version: 7.10.0
version: 7.9.1
- name: valkey
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.4.0
digest: sha256:e7a5cee56dddb4abc07ff18677cb6ddf55571b38da2eeb7e654e8ad8f7709bfa
generated: "2026-03-19T04:16:54.362332682Z"
digest: sha256:898f51eabee5959b9e7ebe90640cb915cb2dee446e6a6649a29499fecab8b6c7
generated: "2026-03-11T22:58:00.955579445Z"

View File

@@ -17,11 +17,11 @@ maintainers:
- name: alexlebens
dependencies:
- name: harbor
version: 1.18.3
version: 1.18.2
repository: https://helm.goharbor.io
- name: postgres-cluster
alias: postgres-18-cluster
version: 7.10.0
version: 7.9.1
repository: https://gitea.alexlebens.net/api/packages/alexlebens/helm
- name: valkey
alias: valkey
@@ -29,4 +29,4 @@ dependencies:
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/harbor.png
# renovate: datasource=github-releases depName=goharbor/harbor
appVersion: v2.15.0
appVersion: v2.14.3

View File

@@ -41,12 +41,12 @@ harbor:
portal:
image:
repository: goharbor/harbor-portal
tag: v2.15.0
tag: v2.14.3
replicas: 2
core:
image:
repository: goharbor/harbor-core
tag: v2.15.0
tag: v2.14.3
replicas: 2
existingSecret: harbor-secret
secretName: harbor-secret
@@ -54,7 +54,7 @@ harbor:
jobservice:
image:
repository: goharbor/harbor-jobservice
tag: v2.15.0
tag: v2.14.3
replicas: 2
jobLoggers:
- stdout
@@ -63,11 +63,11 @@ harbor:
registry:
image:
repository: goharbor/registry-photon
tag: v2.15.0
tag: v2.14.3
controller:
image:
repository: goharbor/harbor-registryctl
tag: v2.15.0
tag: v2.14.3
existingSecret: harbor-secret
relativeurls: true
credentials:
@@ -94,7 +94,7 @@ harbor:
exporter:
image:
repository: goharbor/harbor-exporter
tag: v2.15.0
tag: v2.14.3
replicas: 2
postgres-18-cluster:
mode: recovery

View File

@@ -25,6 +25,9 @@ headlamp:
- name: cert-manager
source: https://artifacthub.io/packages/headlamp/headlamp-plugins/headlamp_cert-manager
version: 0.1.0
- name: trivy
source: https://artifacthub.io/packages/headlamp/headlamp-trivy/headlamp_trivy
version: 0.3.1
- name: external-secrets-operator
source: https://artifacthub.io/packages/headlamp/external-secrets-operator-headlamp-plugin/external-secrets-operator
version: 0.1.0-beta7

View File

@@ -25,4 +25,4 @@ dependencies:
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/home-assistant.png
# renovate: datasource=github-releases depName=home-assistant/core
appVersion: 2026.3.3
appVersion: 2026.3.1

View File

@@ -9,7 +9,7 @@ home-assistant:
main:
image:
repository: ghcr.io/home-assistant/home-assistant
tag: 2026.3.3
tag: 2026.3.1
pullPolicy: IfNotPresent
env:
- name: TZ
@@ -21,7 +21,7 @@ home-assistant:
code-server:
image:
repository: ghcr.io/linuxserver/code-server
tag: 4.112.0@sha256:4bb5b8ad22268001687c047f0f04933799fb03df1eb0e1e266ba15ed2d9f4e8b
tag: 4.110.0@sha256:8473aa16fba93fccc3ca772173d095bccd2e44d4d3104467fee923df10d57cd2
pullPolicy: IfNotPresent
env:
- name: TZ

View File

@@ -19,4 +19,4 @@ dependencies:
version: 4.6.2
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/homepage.png
# renovate: datasource=github-releases depName=gethomepage/homepage
appVersion: v1.11.0
appVersion: v1.10.1

View File

@@ -16,7 +16,7 @@ homepage:
main:
image:
repository: ghcr.io/gethomepage/homepage
tag: v1.11.0
tag: v1.10.1
pullPolicy: IfNotPresent
env:
- name: HOMEPAGE_ALLOWED_HOSTS
@@ -202,15 +202,9 @@ homepage:
href: https://photoview.alexlebens.net
siteMonitor: http://photoview.photoview:80
statusStyle: dot
- Pictures:
icon: https://raw.githubusercontent.com/foldergram/foldergram/refs/heads/main/client/public/icon-512.png
description: Foldergram
href: https://foldergram.alexlebens.net
siteMonitor: http://foldergram.foldergram:80
statusStyle: dot
- Books:
icon: sh-booklore.webp
description: Grimmory
description: Booklore
href: https://booklore.alexlebens.net
siteMonitor: http://booklore.booklore:80
statusStyle: dot
@@ -483,12 +477,6 @@ homepage:
href: https://jellystat.alexlebens.net
siteMonitor: http://jellystat.jellystat:80
statusStyle: dot
- MediaLyze:
icon: https://raw.githubusercontent.com/frederikemmer/MediaLyze/d8f69c0628bac7c047b90f91a66341648029c273/frontend/public/favicon.svg
description: Jellyfin Media Monitoring
href: https://medialyze.alexlebens.net
siteMonitor: http://medialyze.medialyze:80
statusStyle: dot
- Services:
- Auth (Public):
icon: sh-authentik.webp
@@ -639,12 +627,6 @@ homepage:
href: https://bazarr.alexlebens.net
siteMonitor: http://bazarr.bazarr:80
statusStyle: dot
- Houndarr:
icon: https://raw.githubusercontent.com/av1155/houndarr/main/src/houndarr/static/img/houndarr-logo-dark.png
description: Media Searches
href: https://houndarr.alexlebens.net
siteMonitor: http://houndarr.houndarr:80
statusStyle: dot
- Tdarr:
icon: sh-tdarr.webp
description: Media transcoding and health checks
@@ -792,6 +774,9 @@ homepage:
- Digital Ocean:
- abbr: DO
href: https://www.digitalocean.com/
- AWS:
- abbr: AW
href: https://aws.amazon.com/console/
- Cloudflare:
- abbr: CF
href: https://dash.cloudflare.com/b76e303258b84076ee01fd0f515c0768
@@ -801,12 +786,12 @@ homepage:
- ProtonVPN:
- abbr: PV
href: https://account.protonvpn.com/
- AirVPN:
- abbr: AV
href: https://airvpn.org/
- Unifi:
- abbr: UF
href: https://unifi.ui.com/
- Pushover:
- abbr: PO
href: https://pushover.net
- ReCaptcha:
- abbr: RC
href: https://www.google.com/recaptcha/admin/site/698983587

View File

@@ -1,9 +0,0 @@
dependencies:
- name: app-template
repository: https://bjw-s-labs.github.io/helm-charts/
version: 4.6.2
- name: volsync-target
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.8.0
digest: sha256:375d6c2eb2f097717c44c5a28cb162da24f4ff154a971e5a68ccd0e0b77e936f
generated: "2026-03-21T22:31:01.142752-05:00"

View File

@@ -1,25 +0,0 @@
apiVersion: v2
name: houndarr
version: 1.0.0
description: Houndarr
keywords:
- houndarr
- servarr
home: https://wiki.alexlebens.dev/s/
sources:
- https://github.com/av1155/houndarr
- https://github.com/bjw-s-labs/helm-charts/tree/main/charts/other/app-template
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: houndarr
repository: https://bjw-s-labs.github.io/helm-charts/
version: 4.6.2
- name: volsync-target
alias: volsync-target-data
version: 0.8.0
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://raw.githubusercontent.com/av1155/houndarr/main/src/houndarr/static/img/houndarr-logo-dark.png
# renovate: datasource=github-releases depName=av1155/houndarr
appVersion: v1.6.1

View File

@@ -1,84 +0,0 @@
houndarr:
controllers:
main:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
containers:
main:
image:
repository: ghcr.io/av1155/houndarr
tag: v1.6.0
pullPolicy: IfNotPresent
env:
- name: TZ
value: America/Chicago
- name: PUID
value: 1000
- name: PGID
value: 1000
- name: HOUNDARR_SECURE_COOKIES
value: true
- name: HOUNDARR_TRUSTED_PROXIES
value: 10.96.0.0/12
resources:
requests:
cpu: 10m
memory: 128Mi
service:
main:
controller: main
ports:
http:
port: 80
targetPort: 8877
protocol: HTTP
route:
main:
kind: HTTPRoute
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- houndarr.alexlebens.net
rules:
- backendRefs:
- group: ''
kind: Service
name: houndarr
port: 80
weight: 100
matches:
- path:
type: PathPrefix
value: /
persistence:
data:
forceRename: houndarr-data
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 1Gi
advancedMounts:
main:
main:
- path: /data
readOnly: false
volsync-target-data:
pvcTarget: houndarr-data
moverSecurityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
local:
enabled: true
schedule: 40 11 * * *
remote:
enabled: true
schedule: 40 12 * * *
external:
enabled: true
schedule: 40 14 * * *

View File

@@ -4,12 +4,12 @@ dependencies:
version: 4.6.2
- name: postgres-cluster
repository: oci://harbor.alexlebens.net/helm-charts
version: 7.10.0
version: 7.9.1
- name: valkey
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.4.0
- name: volsync-target
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.8.0
digest: sha256:b79ea8c506f0172deed820247a33c79329f34426435c8b5eb27b206ac8831b13
generated: "2026-03-15T20:06:27.091094433Z"
digest: sha256:b886b0a1555ea75fbff52a58ccbf1659acbda20e933107bcbab9b00192aa25bd
generated: "2026-03-11T22:58:20.294240859Z"

View File

@@ -20,7 +20,7 @@ dependencies:
version: 4.6.2
- name: postgres-cluster
alias: postgres-18-cluster
version: 7.10.0
version: 7.9.1
repository: oci://harbor.alexlebens.net/helm-charts
- name: valkey
alias: valkey
@@ -32,4 +32,4 @@ dependencies:
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/immich.png
# renovate: datasource=github-releases depName=immich-app/immich
appVersion: v2.6.1
appVersion: v2.5.6

View File

@@ -9,7 +9,7 @@ immich:
main:
image:
repository: ghcr.io/immich-app/immich-server
tag: v2.6.1
tag: v2.5.6
pullPolicy: IfNotPresent
env:
- name: TZ

View File

@@ -4,9 +4,9 @@ dependencies:
version: 4.6.2
- name: meilisearch
repository: https://meilisearch.github.io/meilisearch-kubernetes
version: 0.28.0
version: 0.27.0
- name: volsync-target
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.8.0
digest: sha256:57b007c6e19dda1300f5025332d9e8104bfb9a50cd7124260bfa68ce2432628b
generated: "2026-03-16T15:57:13.466372254Z"
digest: sha256:ca384647a640ae717ac874a2627f00ac9a1e5c97ff5eeb8f326ebdd471ab1623
generated: "2026-03-09T15:04:08.648165537Z"

View File

@@ -25,7 +25,7 @@ dependencies:
repository: https://bjw-s-labs.github.io/helm-charts/
version: 4.6.2
- name: meilisearch
version: 0.28.0
version: 0.27.0
repository: https://meilisearch.github.io/meilisearch-kubernetes
- name: volsync-target
alias: volsync-target-config

View File

@@ -4,9 +4,9 @@ dependencies:
version: 4.6.2
- name: postgres-cluster
repository: oci://harbor.alexlebens.net/helm-charts
version: 7.10.0
version: 7.9.1
- name: volsync-target
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.8.0
digest: sha256:f779185ce82045b47fc75bf95c4a8215acbd387f44a4bdb764486406d9b03748
generated: "2026-03-15T20:06:38.720993367Z"
digest: sha256:29b92b08c230d5f3abc13949b299acccd1e9f8ff7df1f691a5dec41df5405595
generated: "2026-03-11T22:58:35.766813121Z"

View File

@@ -21,7 +21,7 @@ dependencies:
version: 4.6.2
- name: postgres-cluster
alias: postgres-18-cluster
version: 7.10.0
version: 7.9.1
repository: oci://harbor.alexlebens.net/helm-charts
- name: volsync-target
alias: volsync-target-data

View File

@@ -4,12 +4,12 @@ dependencies:
version: 4.6.2
- name: meilisearch
repository: https://meilisearch.github.io/meilisearch-kubernetes
version: 0.28.0
version: 0.27.0
- name: cloudflared
repository: oci://harbor.alexlebens.net/helm-charts
version: 2.4.0
- name: volsync-target
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.8.0
digest: sha256:49e37e17dc859927048c6474ce27cb063a020f291d6d2d24876d0427eddc3656
generated: "2026-03-16T15:57:28.156797159Z"
digest: sha256:75f92316d4b6229d00e3dfa39ed5026ad39a28f833321cd3887a2048cdac34c7
generated: "2026-03-09T22:04:48.630821646Z"

View File

@@ -22,7 +22,7 @@ dependencies:
repository: https://bjw-s-labs.github.io/helm-charts/
version: 4.6.2
- name: meilisearch
version: 0.28.0
version: 0.27.0
repository: https://meilisearch.github.io/meilisearch-kubernetes
- name: cloudflared
repository: oci://harbor.alexlebens.net/helm-charts

View File

@@ -4,6 +4,6 @@ dependencies:
version: 4.6.2
- name: postgres-cluster
repository: oci://harbor.alexlebens.net/helm-charts
version: 7.10.0
digest: sha256:a6f33512d929c5a1b70bde6c3294902f5d707855aabbaa815f32e23aa54b266f
generated: "2026-03-15T20:06:49.233053802Z"
version: 7.9.1
digest: sha256:833a88f82c14f78d63abea99244f2473bee2f5124a533a898a34844956f62b27
generated: "2026-03-11T22:58:51.287064579Z"

View File

@@ -23,7 +23,7 @@ dependencies:
version: 4.6.2
- name: postgres-cluster
alias: postgresql-17-fdb-cluster
version: 7.10.0
version: 7.9.1
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/komodo.png
# renovate: datasource=github-releases depName=moghtech/komodo

View File

@@ -1,12 +1,12 @@
dependencies:
- name: kube-prometheus-stack
repository: oci://ghcr.io/prometheus-community/charts
version: 82.13.0
version: 82.10.3
- name: app-template
repository: https://bjw-s-labs.github.io/helm-charts/
version: 4.6.2
- name: valkey
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.4.0
digest: sha256:1d90bebd9c0afd20f8ff780edd15da18b20f89cf35fd85832d6d8d44b2e0544b
generated: "2026-03-20T18:02:38.368086545Z"
digest: sha256:37ffa4a21ed29703cae9c9f3fb029566a1dd6af6e0fe8cc3862a2226d6644114
generated: "2026-03-10T19:02:41.11005238Z"

View File

@@ -20,7 +20,7 @@ maintainers:
- name: alexlebens
dependencies:
- name: kube-prometheus-stack
version: 82.13.0
version: 82.10.3
repository: oci://ghcr.io/prometheus-community/charts
- name: app-template
alias: ntfy-alertmanager
@@ -32,4 +32,4 @@ dependencies:
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/prometheus.png
# renovate: datasource=github-releases depName=prometheus-operator/prometheus-operator
appVersion: v0.90.0
appVersion: v0.89.0

View File

@@ -1,9 +0,0 @@
dependencies:
- name: app-template
repository: https://bjw-s-labs.github.io/helm-charts/
version: 4.6.2
- name: volsync-target
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.8.0
digest: sha256:cb14506ada77add5ffcb93d38763e2a5c962312e5754618265d15c4361fea783
generated: "2026-03-20T17:49:46.393059-05:00"

View File

@@ -1,27 +0,0 @@
apiVersion: v2
name: languagetool
version: 1.0.0
description: LanguageTool
keywords:
- languagetool
- spellchecking
home: https://wiki.alexlebens.dev/
sources:
- https://github.com/languagetool-org/languagetool
- https://github.com/Erikvl87/docker-languagetool
- https://hub.docker.com/r/erikvl87/languagetool
- https://github.com/bjw-s-labs/helm-charts/tree/main/charts/other/app-template
maintainers:
- name: alexlebens
dependencies:
- name: app-template
alias: languagetool
repository: https://bjw-s-labs.github.io/helm-charts/
version: 4.6.2
- name: volsync-target
alias: volsync-target-data
version: 0.8.0
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/languagetool.webp
# renovate: datasource=github-releases depName=Erikvl87/docker-languagetool
appVersion: "6.7"

View File

@@ -1,76 +0,0 @@
languagetool:
controllers:
main:
type: deployment
replicas: 1
strategy: Recreate
revisionHistoryLimit: 3
containers:
main:
image:
repository: erikvl87/languagetool
tag: 6.7
pullPolicy: IfNotPresent
env:
- name: langtool_languageModel
value: /ngrams
- name: Java_Xms
value: 512m
- name: Java_Xmx
value: 1g
resources:
requests:
cpu: 10m
memory: 128Mi
service:
main:
controller: main
ports:
http:
port: 80
targetPort: 8010
protocol: HTTP
route:
main:
kind: HTTPRoute
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: traefik-gateway
namespace: traefik
hostnames:
- languagetool.alexlebens.net
rules:
- backendRefs:
- group: ''
kind: Service
name: languagetool
port: 80
weight: 100
matches:
- path:
type: PathPrefix
value: /
persistence:
data:
forceRename: languagetool-data
storageClass: ceph-block
accessMode: ReadWriteOnce
size: 1Gi
retain: true
advancedMounts:
main:
main:
- path: /ngrams
readOnly: false
volsync-target-data:
pvcTarget: languagetool-data
local:
enabled: true
schedule: 38 11 * * *
remote:
enabled: true
schedule: 38 12 * * *
external:
enabled: true
schedule: 38 14 * * *

View File

@@ -24,4 +24,4 @@ dependencies:
repository: oci://harbor.alexlebens.net/helm-charts
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/png/libation.png
# renovate: datasource=github-releases depName=rmcrackan/Libation
appVersion: 13.3.2
appVersion: 13.3.0

View File

@@ -16,7 +16,7 @@ libation:
main:
image:
repository: rmcrackan/libation
tag: 13.3.2
tag: 13.3.0
pullPolicy: IfNotPresent
env:
- name: SLEEP_TIME
@@ -35,7 +35,7 @@ libation:
main:
image:
repository: ubuntu
tag: resolute-20260312
tag: resolute-20260108
pullPolicy: IfNotPresent
command:
- "sleep"

View File

@@ -4,9 +4,9 @@ dependencies:
version: 4.6.2
- name: postgres-cluster
repository: oci://harbor.alexlebens.net/helm-charts
version: 7.10.0
version: 7.9.1
- name: volsync-target
repository: oci://harbor.alexlebens.net/helm-charts
version: 0.8.0
digest: sha256:0f1a2923a7042b364a817edc64729d5e1c18b0552555c035d974de626f372692
generated: "2026-03-15T20:07:00.750754951Z"
digest: sha256:d43b95fa1fc70c93541b9d73180406b31059c6cc45aa57a0cc8d9386c64833c3
generated: "2026-03-11T22:59:07.151659257Z"

Some files were not shown because too many files have changed in this diff Show More