diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..0b499a4
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,23 @@
+---
+name: Bug report
+about: Create a report to help us improve
+labels: bug, kind/bug
+
+---
+
+**What steps did you take and what happened:**
+[A clear and concise description of what the bug is.]
+
+**What did you expect to happen:**
+
+**Anything else you would like to add:**
+[Miscellaneous information that will assist in solving the issue.]
+
+**Environment:**
+- OS (e.g. from `/etc/os-release`):
+- Kubernetes version: (use `kubectl version`):
+- Chart version:
+
+Values
+
+
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..0283fab
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,13 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+labels: enhancement, kind/feature
+
+---
+
+**Describe the solution you'd like:**
+[A clear and concise description of what you want to happen.]
+
+
+**Anything else you would like to add:**
+[Miscellaneous information that will assist in solving the issue.]
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..5b0e85c
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,14 @@
+## What does this fix or implement?
+
+
+
+## Checklist
+
+
+
+
+- [ ] PR title contains [conventional commit](https://www.conventionalcommits.org/en/v1.0.0/) markers (`feat:`, `fix:`, `docs:`, etc.)
+- [ ] Helm chart version bumped
+- [ ] Tests added or updated
+- [ ] Documentation updated
+- [ ] GitHub issue linked if any
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..e4d27ff
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,16 @@
+---
+version: 2
+updates:
+- package-ecosystem: "docker"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ commit-message:
+ prefix: "chore:"
+
+- package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ commit-message:
+ prefix: "chore:"
diff --git a/.github/workflows/chart-ci.yml b/.github/workflows/chart-ci.yml
new file mode 100644
index 0000000..85e4620
--- /dev/null
+++ b/.github/workflows/chart-ci.yml
@@ -0,0 +1,84 @@
+name: Chart CI
+
+on:
+ pull_request:
+ paths:
+ - 'charts/**'
+ - .github/workflows/chart-verify.yml
+
+jobs:
+ helm-lint-test:
+ name: Helm chart
+ runs-on: ubuntu-latest
+ env:
+ CT_TARGET_BRANCH: ${{ github.event.repository.default_branch }}
+ CT_CHART_DIRS: charts
+ CT_GITHUB_GROUPS: "true"
+ CT_USE_HELMIGNORE: "true"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4.1.4
+ with:
+ fetch-depth: 0
+
+ - name: Set up Helm
+ uses: azure/setup-helm@v4.2.0
+
+ - name: Set up python
+ uses: actions/setup-python@v5.1.0
+ with:
+ python-version: '3.x'
+
+ - name: Set up chart-testing
+ uses: helm/chart-testing-action@v2.6.1
+
+ - name: Run chart-testing (lint)
+ run: ct lint
+
+ - name: Prepare host path mounts
+ run: |
+ mkdir -p ${{ runner.temp }}/run/udev/data
+ cat > ${{ runner.temp }}/kind-config.yaml <
+ helm show crds $CHART | kubectl apply -f -;
+ helm install ionoscloud-blockstorage-csi-driver $CHART -n kube-system -n kube-system -f $CHART/ci/ct-values.yaml --dry-run -o json | jq -r '.manifest' |
+ kubectl apply --dry-run=server --validate=true -f -
+ env:
+ CHART: ./charts/ionoscloud-blockstorage-csi-driver
+
+
+ helm-docs-validate:
+ name: Helm docs
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4.1.4
+ - name: Run helm-docs
+ uses: docker://jnorwood/helm-docs:v1.13.1
+ - name: Check for changes
+ run: git diff --quiet charts/*/README.md
diff --git a/.github/workflows/chart-release.yml b/.github/workflows/chart-release.yml
new file mode 100644
index 0000000..28fbaee
--- /dev/null
+++ b/.github/workflows/chart-release.yml
@@ -0,0 +1,36 @@
+name: Chart release
+
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - 'charts/**/Chart.yaml'
+
+jobs:
+ publish-chart:
+ name: Publish chart
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4.1.4
+
+ - name: Configure Git
+ run: |
+ git config user.name "$GITHUB_ACTOR"
+ git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
+
+ - name: Set up Helm
+ uses: azure/setup-helm@v4.2.0
+
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v3.1.0
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Publish chart to GitHub Container Registry
+ run: ./hack/publish-chart.sh
diff --git a/charts/ionoscloud-blockstorage-csi-driver/ci/ct-values.yaml b/charts/ionoscloud-blockstorage-csi-driver/ci/ct-values.yaml
new file mode 100644
index 0000000..9ff47ba
--- /dev/null
+++ b/charts/ionoscloud-blockstorage-csi-driver/ci/ct-values.yaml
@@ -0,0 +1 @@
+tokenSecretName: dummy
diff --git a/hack/publish-chart.sh b/hack/publish-chart.sh
new file mode 100755
index 0000000..acb99c2
--- /dev/null
+++ b/hack/publish-chart.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+set -o errexit
+set -o pipefail
+set -o nounset
+if [[ "${TRACE-0}" == "1" ]]; then
+ set -o xtrace
+fi
+
+OCI_HELM_CHART_REPO=ghcr.io/ionos-cloud/helm-charts
+
+for chart in charts/*; do
+ chart_name=${chart#*/}
+ chart_version=$(yq -r '.version' "$chart/Chart.yaml")
+ if ! helm show chart "oci://$OCI_HELM_CHART_REPO/$chart_name" --version "$chart_version" >/dev/null; then
+ helm package "$chart"
+ echo "Publish $chart_name $chart_version"
+ if [[ -n ${DRY_RUN-} ]]; then
+ continue
+ fi
+ helm push "$chart_name-$chart_version" "oci://$OCI_HELM_CHART_REPO/$chart_name"
+ fi
+done
diff --git a/hack/update-crds.sh b/hack/update-crds.sh
new file mode 100755
index 0000000..90b7ed5
--- /dev/null
+++ b/hack/update-crds.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+
+set -o errexit
+set -o pipefail
+set -o nounset
+if [[ "${TRACE-0}" == "1" ]]; then
+ set -o xtrace
+fi
+
+BASE_DIR=$(mktemp -d)
+trap 'rm -rf $BASE_DIR' EXIT
+
+if [[ $# -eq 0 ]]; then
+ TAG=$(yq -r '.snapshotter.image.tag' charts/ionoscloud-csi-driver/values.yaml)
+else
+ TAG=$1
+fi
+
+git clone https://github.com/kubernetes-csi/external-snapshotter --no-checkout "$BASE_DIR"
+(
+ cd "$BASE_DIR"
+ git sparse-checkout set client/config/crd
+ git checkout "$TAG"
+)
+cp "$BASE_DIR/client/config/crd/"snapshot.*.yaml charts/ionoscloud-csi-driver/crds/