diff --git a/.ct.yaml b/.ct.yaml new file mode 100644 index 0000000..26c5f5a --- /dev/null +++ b/.ct.yaml @@ -0,0 +1,10 @@ +chart-dirs: + - charts +excluded-charts: + - template +validate-maintainers: false +check-version-increment: true +validate-chart-schema: true +validate-yaml: true +helm-extra-args: --timeout 10m +upgrade: true diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 78fdd58..70dfc28 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -3,8 +3,11 @@ name: pr on: pull_request: +permissions: + contents: read + jobs: - lint: + static: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -15,3 +18,50 @@ jobs: - name: Lint charts run: ./scripts/lint.sh + + - name: Install kubeconform + shell: bash + run: | + set -euo pipefail + ver=v0.6.7 + url="https://github.com/yannh/kubeconform/releases/download/${ver}/kubeconform-linux-amd64.tar.gz" + curl -fsSL "$url" -o /tmp/kubeconform.tar.gz + tar -xzf /tmp/kubeconform.tar.gz -C /tmp kubeconform + sudo install -m 0755 /tmp/kubeconform /usr/local/bin/kubeconform + + - name: Validate rendered manifests + shell: bash + run: | + set -euo pipefail + while IFS= read -r chart; do + dir="$(dirname "$chart")" + if [[ "$(basename "$dir")" == "_template" ]]; then + continue + fi + echo "[kubeconform] ${dir}" + helm template ci "$dir" | kubeconform -strict -summary -ignore-missing-schemas + done < <(find charts -mindepth 2 -maxdepth 2 -type f -name Chart.yaml | sort) + + install: + runs-on: ubuntu-latest + needs: [static] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: jdx/mise-action@v2 + with: + cache: true + + - uses: helm/chart-testing-action@v2.7.0 + + - uses: helm/kind-action@v1.12.0 + with: + version: v0.25.0 + + - name: Lint changed charts (ct) + run: ct lint --config .ct.yaml --target-branch "${{ github.event.pull_request.base.ref }}" + + - name: Install changed charts in kind (ct) + run: ct install --config .ct.yaml --target-branch "${{ github.event.pull_request.base.ref }}" diff --git a/README.md b/README.md index 52bff63..ed092b5 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,15 @@ Helm charts I maintain for my home cluster. - `charts//` contains a chart definition - `scripts/` contains local/CI helpers +## CI Testing + +PR workflow (`.github/workflows/pr.yml`) runs: + +- Layer 1 (static): `helm lint` + rendered manifest schema validation via `kubeconform` +- Layer 2 (integration): `ct lint` + `ct install` in a disposable `kind` cluster + +Recommended branch policy: require pull requests for `main` and require the `pr` workflow to pass before merge. + ## Local Lint ```bash diff --git a/charts/proton-bridge/Chart.yaml b/charts/proton-bridge/Chart.yaml index 45ab263..ae58870 100644 --- a/charts/proton-bridge/Chart.yaml +++ b/charts/proton-bridge/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: proton-bridge description: Proton Mail Bridge deployment for in-cluster SMTP/IMAP access type: application -version: 0.1.1 +version: 0.1.4 appVersion: "3.22.0" diff --git a/charts/proton-bridge/README.md b/charts/proton-bridge/README.md index 30ba82d..92d662f 100644 --- a/charts/proton-bridge/README.md +++ b/charts/proton-bridge/README.md @@ -5,7 +5,7 @@ Deploys `ghcr.io/mgarratt/docker-images/proton-bridge` as a single-replica Helm ## Defaults - Service type: `ClusterIP` -- Service ports: SMTP `25`, IMAP `143` +- Service ports: SMTP `25`, IMAP `143` (mapped to container ports `1025`/`1143` by default) - Image tag: `latest` - PVC: enabled, `ReadWriteOnce`, `2Gi` @@ -35,4 +35,15 @@ Common overrides: - `service.type` - `persistence.existingClaim` - `bridge.host`, `bridge.smtpPort`, `bridge.imapPort` +- `container.smtpPort`, `container.imapPort` +- `container.enablePrivilegedPortBinding` - `existingSecret` + +To bind directly on container ports `25` and `143`, enable privileged port binding: + +```yaml +container: + smtpPort: 25 + imapPort: 143 + enablePrivilegedPortBinding: true +``` diff --git a/charts/proton-bridge/templates/deployment.yaml b/charts/proton-bridge/templates/deployment.yaml index 22a875f..76804b3 100644 --- a/charts/proton-bridge/templates/deployment.yaml +++ b/charts/proton-bridge/templates/deployment.yaml @@ -30,6 +30,12 @@ spec: - name: proton-bridge image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.container.enablePrivilegedPortBinding }} + securityContext: + capabilities: + add: + - NET_BIND_SERVICE + {{- end }} env: - name: BRIDGE_MODE value: {{ .Values.bridge.mode | quote }} diff --git a/charts/proton-bridge/values.yaml b/charts/proton-bridge/values.yaml index 529dc69..f42f3a3 100644 --- a/charts/proton-bridge/values.yaml +++ b/charts/proton-bridge/values.yaml @@ -32,8 +32,10 @@ bridge: mode: noninteractive container: - smtpPort: 25 - imapPort: 143 + smtpPort: 1025 + imapPort: 1143 + # Set true to add NET_BIND_SERVICE capability so non-root process can bind <1024 (e.g. 25/143). + enablePrivilegedPortBinding: false existingSecret: "" secretName: ""