Initial Commit

This commit is contained in:
2026-08-16 21:04:27 +02:00
commit 95dba5662e
14 changed files with 2795 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = false
[Makefile]
indent_style = tab
+44
View File
@@ -0,0 +1,44 @@
name: Markdown linter
on:
pull_request:
paths: [ "**/*.md" ]
types: [ "opened", "reopened", "synchronize" ]
push:
branches:
- '**'
paths: [ "**/*.md" ]
tags-ignore:
- '**'
workflow_dispatch: {}
jobs:
markdown-link-checker:
container:
image: docker.io/library/node:26.7.0-alpine
runs-on: ubuntu-latest
steps:
- name: Install tooling
run: |
apk update
apk add git npm
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
- name: Verify links in markdown files
run: |
npm install
npm run readme:link
markdown-lint:
container:
image: docker.io/library/node:26.7.0-alpine
runs-on: ubuntu-latest
steps:
- name: Install tooling
run: |
apk update
apk add git
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
- name: Lint markdown files
run: |
npm install
npm run readme:lint
+1
View File
@@ -0,0 +1 @@
node_modules/
+155
View File
@@ -0,0 +1,155 @@
# markdownlint YAML configuration
# https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.yaml
# Default state for all rules
default: true
# Path to configuration file to extend
extends: null
# MD003/heading-style/header-style - Heading style
MD003:
# Heading style
style: "atx"
# MD004/ul-style - Unordered list style
MD004:
style: "dash"
# MD007/ul-indent - Unordered list indentation
MD007:
# Spaces for indent
indent: 2
# Whether to indent the first level of the list
start_indented: false
# MD009/no-trailing-spaces - Trailing spaces
MD009:
# Spaces for line break
br_spaces: 2
# Allow spaces for empty lines in list items
list_item_empty_lines: false
# Include unnecessary breaks
strict: false
# MD010/no-hard-tabs - Hard tabs
MD010:
# Include code blocks
code_blocks: true
# MD012/no-multiple-blanks - Multiple consecutive blank lines
MD012:
# Consecutive blank lines
maximum: 1
# MD013/line-length - Line length
MD013:
# Number of characters
line_length: 120
# Number of characters for headings
heading_line_length: 120
# Number of characters for code blocks
code_block_line_length: 80
# Include code blocks
code_blocks: false
# Include tables
tables: false
# Include headings
headings: true
# Strict length checking
strict: false
# Stern length checking
stern: false
# MD022/blanks-around-headings/blanks-around-headers - Headings should be surrounded by blank lines
MD022:
# Blank lines above heading
lines_above: 1
# Blank lines below heading
lines_below: 1
# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content
MD024:
# Only check sibling headings
siblings_only: true
# MD025/single-title/single-h1 - Multiple top-level headings in the same document
MD025:
# Heading level
level: 1
# RegExp for matching title in front matter
front_matter_title: "^\\s*title\\s*[:=]"
# MD026/no-trailing-punctuation - Trailing punctuation in heading
MD026:
# Punctuation characters
punctuation: ".,;:!。,;:!"
# MD029/ol-prefix - Ordered list item prefix
MD029:
# List style
style: "one_or_ordered"
# MD030/list-marker-space - Spaces after list markers
MD030:
# Spaces for single-line unordered list items
ul_single: 1
# Spaces for single-line ordered list items
ol_single: 1
# Spaces for multi-line unordered list items
ul_multi: 1
# Spaces for multi-line ordered list items
ol_multi: 1
# MD033/no-inline-html - Inline HTML
MD033:
# Allowed elements
allowed_elements: []
# MD035/hr-style - Horizontal rule style
MD035:
# Horizontal rule style
style: "---"
# MD036/no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading
MD036:
# Punctuation characters
punctuation: ".,;:!?。,;:!?"
# MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading
MD041:
# Heading level
level: 1
# RegExp for matching title in front matter
front_matter_title: "^\\s*title\\s*[:=]"
# MD044/proper-names - Proper names should have the correct capitalization
MD044:
# List of proper names
names:
- Git
- GitDevOps
- Gitea
- GitHub
- GitLab
- GitOps
- kube-prometheus-stack
- Memcached
- Oracle
- PostgreSQL
- Prometheus
- prometheus-exporter
- SSL
- TLS
# Include code blocks
code_blocks: false
# MD046/code-block-style - Code block style
MD046:
# Block style
style: "fenced"
# MD048/code-fence-style - Code fence style
MD048:
# Code fence syle
style: "backtick"
+1
View File
@@ -0,0 +1 @@
* @volker.raschek
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Markus Pesch
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+56
View File
@@ -0,0 +1,56 @@
# CONTAINER_RUNTIME
CONTAINER_RUNTIME?=$(shell which podman)
# NODE_IMAGE
NODE_IMAGE_REGISTRY_HOST?=docker.io
NODE_IMAGE_REPOSITORY?=library/node
NODE_IMAGE_VERSION?=25.2.1-alpine # renovate: datasource=docker registryUrl=https://docker.io depName=docker.io/library/node packageName=library/node
NODE_IMAGE_FULLY_QUALIFIED=${NODE_IMAGE_REGISTRY_HOST}/${NODE_IMAGE_REPOSITORY}:${NODE_IMAGE_VERSION}
# README
# ==============================================================================
readme: readme/link readme/lint
readme/link:
npm install && npm run readme:link
readme/lint:
npm install && npm run readme:lint
# CONTAINER RUN - README
# ==============================================================================
PHONY+=container-run/readme
container-run/readme: container-run/readme/link container-run/readme/lint
container-run/readme/link:
${CONTAINER_RUNTIME} run \
--rm \
--volume $(shell pwd):$(shell pwd) \
--workdir $(shell pwd) \
${NODE_IMAGE_FULLY_QUALIFIED} \
npm install && npm run readme:link
container-run/readme/lint:
${CONTAINER_RUNTIME} run \
--rm \
--volume $(shell pwd):$(shell pwd) \
--workdir $(shell pwd) \
${NODE_IMAGE_FULLY_QUALIFIED} \
npm install && npm run readme:lint
# CONTAINER RUN - MARKDOWN-LINT
# ==============================================================================
PHONY+=container-run/helm-lint
container-run/helm-lint:
${CONTAINER_RUNTIME} run \
--rm \
--volume $(shell pwd):$(shell pwd) \
--workdir $(shell pwd) \
${HELM_IMAGE_FULLY_QUALIFIED} \
lint --values values.yaml .
# PHONY
# ==============================================================================
# Declare the contents of the PHONY variable as phony. We keep that information
# in a variable so we can use it in if_changed.
.PHONY: ${PHONY}
+59
View File
@@ -0,0 +1,59 @@
# ah-annotation
GitHub Action to generate ArtifactHub changelog annotations from Git commit history and add them to `Chart.yaml`.
The action parses conventional commit messages between two Git tags and produces an `artifacthub.io/changes` annotation.
Pre-release tags (matching `-rc`) are detected automatically and result in an `artifacthub.io/prerelease` annotation
instead.
## Usage
### Auto-detect tags
Without explicit inputs the action determines the two most recent non-RC tags from the Git history:
```yaml
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: volker.raschek/ah-annotation@v1
```
### Explicit tags
Pass `old-tag` and `new-tag` to control the commit range:
```yaml
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: volker.raschek/ah-annotation@v1.0.0
with:
old-tag: v1.0.0
new-tag: v2.0.0
```
## Inputs
| Name | Required | Default | Description |
| --------- | -------- | ------------- | ------------------------------------ |
| `old-tag` | no | auto-detected | Start tag for changelog generation. |
| `new-tag` | no | auto-detected | End tag for changelog generation. |
## Requirements
- The repository must be checked out with full history (`fetch-depth: 0`).
- A `Chart.yaml` file must exist in the working directory.
- Commit messages must follow the [Conventional Commits](https://www.conventionalcommits.org/) format.
## Commit type mapping
| Commit type | ArtifactHub kind |
| ------------------------------------------------ | ---------------- |
| `feat` | added |
| `fix` | fixed |
| `chore`, `style`, `test`, `ci`, `docs`, `refac` | changed |
| `revert` | removed |
| `sec` | security |
+55
View File
@@ -0,0 +1,55 @@
name: "ArtifactHub Annotations"
description: "Generate ArtifactHub changelog annotations from git commit history and add them to Chart.yaml"
inputs:
old-tag:
description: "Start tag for changelog generation. If not set, auto-detected from git tags."
required: false
default: ""
new-tag:
description: "End tag for changelog generation. If not set, auto-detected from git tags."
required: false
default: ""
yq-arch:
description: "Architecture of yq binary to download. If not set, auto-detected from system architecture."
required: false
default: ""
yq-os:
description: "Operating system of yq binary to download. If not set, auto-detected from system OS."
required: false
default: ""
yq-binary-name:
description: "Name of the yq binary to download. If not set, defaults to 'yq'."
required: false
default: "yq"
yq-download-url:
description: |
URL to download yq from. Name of the binary must be 'yq'. The distribution and architecture are automatically
detected if undefined. The distribution and architecture will we underscore separated in the URL, e.g. `yq_linux_amd64`
required: false
default: ""
yq-version:
description: "Version of yq to install"
required: false
default: "v4.44.6"
runs:
using: "composite"
steps:
- name: Install yq
shell: bash
env:
YQ_ARCH: ${{ inputs.yq-arch }}
YQ_BINARY_NAME: ${{ inputs.yq-binary-name }}
YQ_DOWNLOAD_URL: ${{ inputs.yq-download-url }}
YQ_OS: ${{ inputs.yq-os }}
YQ_VERSION: ${{ inputs.yq-version }}
run: "${GITHUB_ACTION_PATH}/install-yq.sh"
- name: Add ArtifactHub annotations
shell: bash
env:
INPUT_OLD_TAG: ${{ inputs.old-tag }}
INPUT_NEW_TAG: ${{ inputs.new-tag }}
run: "${GITHUB_ACTION_PATH}/add-annotations.sh"
+112
View File
@@ -0,0 +1,112 @@
#!/bin/bash
# ============================================================================
# Generate ArtifactHub changelog annotations from git commit history
# ============================================================================
set -euo pipefail
readonly CHART_FILE="Chart.yaml"
readonly RC_PATTERN="\-rc([-\.][0-9]+)?$"
CHANGE_LOG_YAML=""
cleanup() {
if [[ -n "${CHANGE_LOG_YAML:-}" && -f "${CHANGE_LOG_YAML}" ]]; then
rm -f "${CHANGE_LOG_YAML}"
fi
}
trap cleanup EXIT
if [[ ! -f "${CHART_FILE}" ]]; then
echo "ERROR: ${CHART_FILE} not found!" >&2
exit 1
fi
# Determine old and new tags
DEFAULT_NEW_TAG="$(git tag --sort=-version:refname | grep --invert-match --perl-regexp "${RC_PATTERN}" | head --lines 1)"
DEFAULT_OLD_TAG="$(git tag --sort=-version:refname | grep --invert-match --perl-regexp "${RC_PATTERN}" | head --lines 2 | tail --lines 1)"
if [[ -n "${INPUT_OLD_TAG:-}" ]]; then
OLD_TAG="${INPUT_OLD_TAG}"
else
OLD_TAG="${DEFAULT_OLD_TAG}"
fi
if [[ -n "${INPUT_NEW_TAG:-}" ]]; then
NEW_TAG="${INPUT_NEW_TAG}"
else
NEW_TAG="${DEFAULT_NEW_TAG}"
fi
if [[ -z "$(git tag --list "${OLD_TAG}")" ]]; then
echo "ERROR: Tag '${OLD_TAG}' not found!" >&2
exit 1
fi
if [[ -z "$(git tag --list "${NEW_TAG}")" ]]; then
echo "ERROR: Tag '${NEW_TAG}' not found!" >&2
exit 1
fi
if [[ "${NEW_TAG}" =~ ${RC_PATTERN} ]]; then
echo "INFO: Tag '${NEW_TAG}' is a prerelease, setting prerelease annotation and skipping changelog."
yq --no-colors --inplace ".annotations.\"artifacthub.io/prerelease\" = \"true\" | sort_keys(.)" "${CHART_FILE}"
exit 0
fi
CHANGE_LOG_YAML="$(mktemp)"
echo "[]" > "${CHANGE_LOG_YAML}"
map_type_to_kind() {
case "${1}" in
feat)
echo "added"
;;
fix)
echo "fixed"
;;
chore|style|test|ci|docs|refac)
echo "changed"
;;
revert)
echo "removed"
;;
sec)
echo "security"
;;
*)
echo "skip"
;;
esac
}
COMMIT_TITLES="$(git log --pretty=format:"%s" "${OLD_TAG}..${NEW_TAG}")"
echo "INFO: Generate change log entries from ${OLD_TAG} until ${NEW_TAG}"
while IFS= read -r line; do
if [[ "${line}" =~ ^([a-zA-Z]+)(\([^\)]+\))?\:\ (.+)$ ]]; then
TYPE="${BASH_REMATCH[1]}"
KIND="$(map_type_to_kind "${TYPE}")"
if [[ "${KIND}" == "skip" ]]; then
continue
fi
DESC="${BASH_REMATCH[3]}"
echo "- ${KIND}: ${DESC}"
jq --arg kind "${KIND}" --arg description "${DESC}" '. += [ $ARGS.named ]' < "${CHANGE_LOG_YAML}" > "${CHANGE_LOG_YAML}.new"
mv "${CHANGE_LOG_YAML}.new" "${CHANGE_LOG_YAML}"
fi
done <<< "${COMMIT_TITLES}"
if [[ -s "${CHANGE_LOG_YAML}" ]]; then
yq --inplace --input-format json --output-format yml "${CHANGE_LOG_YAML}"
yq --no-colors --inplace ".annotations.\"artifacthub.io/changes\" |= loadstr(\"${CHANGE_LOG_YAML}\") | sort_keys(.)" "${CHART_FILE}"
else
echo "ERROR: Changelog file is empty: ${CHANGE_LOG_YAML}" >&2
exit 1
fi
Executable
+80
View File
@@ -0,0 +1,80 @@
#!/bin/bash
set -euo pipefail
internal_yq_version=v4.44.6 # renovate: datasource=github-releases depName=mikefarah/yq versioning=semver
# Use :- for unset and handle empty strings from composite action inputs
YQ_BINARY_NAME="${YQ_BINARY_NAME:="yq"}"
YQ_OS="${YQ_OS:="$(uname -s | tr '[:upper:]' '[:lower:]')"}"
YQ_ARCH="${YQ_ARCH:="$(uname -m)"}"
YQ_VERSION="${YQ_VERSION:="${internal_yq_version}"}"
# Determine OS
case "${YQ_OS:-}" in
linux*) ;;
darwin*) ;;
*) echo "Unsupported OS: $(uname -s)"; exit 1;;
esac
# Determine architecture
case "${YQ_ARCH:-}" in
amd64* | x86_64*) YQ_ARCH="amd64" ;;
aarch64 | arm64*) YQ_ARCH="arm64" ;;
*) echo "Unsupported architecture: $(uname -m)"; exit 1;;
esac
# Build download URL if not explicitly provided
if [[ -z "${YQ_DOWNLOAD_URL:-}" ]]; then
YQ_DOWNLOAD_URL="https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/${YQ_BINARY_NAME}_${YQ_OS}_${YQ_ARCH}.tar.gz"
fi
# Determine install path
if [[ "$(id -u)" != "0" ]]; then
home="$(getent passwd "$(id -u)" | cut --delimiter ":" --field "6")"
mkdir --parents "${home}/.local/bin"
bin_path="${home}/.local/bin/yq"
else
bin_path="/usr/local/bin/yq"
fi
# Download and extract yq binary from .tar.gz
if [[ "${YQ_DOWNLOAD_URL}" =~ \.tar\.gz$ ]]; then
echo "Downloading and extracting yq from ${YQ_DOWNLOAD_URL}..."
tmp_dir="$(mktemp -d)"
trap 'rm -rf "${tmp_dir}"' EXIT
curl \
--fail \
--location \
--output /dev/stdout \
--silent \
--show-error "${YQ_DOWNLOAD_URL}" | \
tar \
--extract \
--gzip \
--directory "${tmp_dir}" \
--file /dev/stdin
mv "${tmp_dir}/${YQ_BINARY_NAME}_${YQ_OS}_${YQ_ARCH}" "${bin_path}"
# Download yq binary directly
else
echo "Downloading yq from ${YQ_DOWNLOAD_URL}..."
curl \
--fail \
--location \
--output "${bin_path}" \
--silent \
--show-error "${YQ_DOWNLOAD_URL}"
fi
chmod +x "${bin_path}"
echo "Installed yq version $(${bin_path} --version) in ${bin_path}"
# Ensure yq is in PATH for subsequent steps
if [[ -n "${GITHUB_PATH:-}" ]]; then
echo "$(dirname "${bin_path}")" >> "${GITHUB_PATH}"
fi
+2118
View File
File diff suppressed because it is too large Load Diff
+19
View File
@@ -0,0 +1,19 @@
{
"name": "ah-annotations",
"homepage": "https://git.cryptic.systems/volker.raschek/ah-annotations.git",
"license": "MIT",
"private": true,
"engineStrict": true,
"engines": {
"node": ">=16.0.0",
"npm": ">=8.0.0"
},
"scripts": {
"readme:link": "markdown-link-check *.md",
"readme:lint": "markdownlint *.md -f"
},
"devDependencies": {
"markdown-link-check": "^3.13.6",
"markdownlint-cli": "^0.49.0"
}
}
+62
View File
@@ -0,0 +1,62 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"local>volker.raschek/renovate-config:default#master",
"local>volker.raschek/renovate-config:actions#master",
"local>volker.raschek/renovate-config:npm#master",
"local>volker.raschek/renovate-config:regexp#master"
],
"customManagers": [
{
"customType": "regex",
"fileMatch": [
"^README\\.md$"
],
"matchStrings": [
"volker.raschek/ah-annotations@(?<currentValue>\\d+\\.\\d+\\.\\d+)"
],
"depNameTemplate": "volker.raschek/ah-annotations",
"datasourceTemplate": "git-tags",
"versioningTemplate": "semver"
},
{
"customType": "regex",
"fileMatch": [
"^README\\.md$"
],
"matchStrings": [
"actions/checkout@(?<currentValue>.*)"
],
"depNameTemplate": "actions/checkout",
"datasourceTemplate": "github-releases",
"versioningTemplate": "semver"
}
],
"packageRules": [
{
"addLabels": [
"renovate/automerge",
"renovate/documentation"
],
"automerge": true,
"matchDepNames": [
"volker.raschek/ah-annotations"
],
"matchUpdateTypes": [
"major",
"minor",
"patch"
]
}
],
"postUpgradeTasks": {
"commands": [
"install-tool node",
"make readme"
],
"fileFilters": [
"README.md"
],
"executionMode": "update"
}
}