Commit Graph
83 Commits
Author SHA1 Message Date
jklein 69a280399c ci: run the freesailarr install-test for real instead of skipping it
freesailarr was excluded from the install-test because gluetun never becomes
healthy without a real Wireguard key and no app container behind its kill
switch can become Ready. The green "Install-test freesailarr pass" was a
25-second SKIP on the most complex chart in the repo - a signal that proved
nothing.

With a CI-only Mullvad key in 1Password the reason is gone:

- ci/run-install-test.sh learns a general rule: ci/<chart>/fixtures.env.yaml is
  rendered with envsubst before it is applied, restricted to the variable names
  a chart declares in REQUIRED_ENV. A missing or empty declared variable fails
  the run loudly and names the variable - it never skips the chart.
- The install-test job loads the key from 1Password Connect for freesailarr
  only, following the pattern publish-helm-chart.yml documents: values via
  steps.<id>.outputs.*, mapped into the step's own env, quoted, with ":?"
  guards that name the missing op:// field before a cluster is created.
- Fixtures for freesailarr: three media claims, the gluetun secret template
  with variable names only, firewallOutboundSubnets so the kill switch does not
  block cluster DNS, and INSTALL_TIMEOUT=900 for nine containers.

freesailarr/Chart.yaml goes 3.0.0+up1.0.0 -> 3.0.1+up1.0.0. That bump is
deliberately empty of content: the install-test matrix follows changed chart
directories, and without it this PR could not run the test it adds.
2026-08-26 14:30:42 +02:00
jklein 9c81061f92 Merge pull request #59 from jk-cluster/feat/freesailarr-chart
Add freesailarr chart: gluetun-tunneled media automation stack
2026-08-24 13:38:58 +00:00
jklein af5f9ed79b Pin gluetun in values too, so Renovate proposes it there
The chart bundles nine independently versioned upstreams, and eight of them
were already pinned in values.yaml while only gluetun took its tag from
appVersion. That split had no upside: it made gluetun the one image Renovate
could not reach through the built-in helm-values manager, and it implied a
"main app" the stack does not have.

gluetun now carries gluetun.image.repository/tag like every other image, and
the StatefulSet renders it from there. No tag comes from appVersion any more.
Renovate picks all nine up through helm-values - the manager the repo already
relies on for sidecar images - and ci/renovate-bump-chart.sh bumps the chart
version with each update.

Consequences, all documented where they bite:
- renovate.json5 deliberately gets no app-version block for this chart. One
  would either duplicate the helm-values updates or rewrite an appVersion that
  selects no image. The absence is commented so it does not read as an
  oversight.
- freesailarr leaves the change-app-version.yml choice list. That workflow
  rewrites appVersion and republishes, which for this chart would change no
  deployed image at all.
- appVersion becomes a hand-maintained marker for the gluetun line. Since
  renovate-bump-chart.sh bumps the patch level on an unchanged appVersion, a
  gluetun update has to be paired with a hand edit of appVersion, or the +up
  suffix stops describing what the chart deploys. Noted in Chart.yaml,
  values.yaml and README.
2026-08-24 15:01:34 +02:00
jklein 0fb6c30466 publish: read registry credentials from step outputs and validate them
Two defects kept the publish broken after the load-secrets-action v5 bump
in #140.

v5 no longer exports the loaded values as environment variables for later
steps the way v4 did; only the step outputs carry them. Every
"${{ env.JK_CR_* }}" reference therefore resolved to an empty string from
that bump on, and nothing reported it - the loading step logs "Populating
variable" and stays green either way. #149 moved three of the four
references to steps.<id>.outputs but left "-u ${{ env.JK_CR_USERNAME }}"
on the old form, and piped the username instead of the token into
--password-stdin.

The second defect is why this surfaced as a terminal error: an empty value
collapsed into a missing argument instead of failing. With an empty
username, "-u" swallowed the following "--password-stdin", helm stopped
reading the password from stdin, prompted interactively and died with
"inappropriate ioctl for device".

All four values now come from steps.<id>.outputs, are mapped into each
step's own env block and used as quoted shell variables guarded with ":?".
An empty or unset value aborts the job naming the op:// path to fix,
quoting keeps it from shifting arguments, and the token no longer appears
on the command line.
2026-08-24 14:03:09 +02:00
jklein f6f04d27fe fix(publish-action): fixed 1Password secret access 2026-08-24 13:47:01 +02:00
jklein 914c2d0205 Add freesailarr chart: gluetun-tunneled media automation stack
Single-pod StatefulSet running gluetun (appVersion 3.41.1) as Wireguard
VPN gateway with qbittorrent, prowlarr, flaresolverr, radarr, recyclarr,
sonarr, seerr and bazarr sharing its network namespace. Config volumes
via volumeClaimTemplates, media libraries as existing claims, per-app
enable/ingress toggles, computed FIREWALL_INPUT_PORTS, hardened
security contexts with documented per-image deviations. Wires up
publish workflow, change-app-version choice, install-test exclusion
and README overview.
2026-08-24 13:41:46 +02:00
jklein 2e0e37d838 renovate: automerge minor updates, make the install-test blocking
The two open Renovate PRs (#138 alpine 3.22 -> 3.24, #139 nginx 1.30.4 ->
1.31.4) never automerged because both are minor updates while the rule
only covered patch and digest. Sidecar images barely move in patch steps,
so patch-only would practically never fire.

Automerging a chart update publishes it, so the install-test can no
longer report failures without blocking: continue-on-error is gone and
issue #22's stabilization phase ends here. Majors stay manual.
2026-08-24 12:01:08 +02:00
jklein 6b25d082a7 renovate: chart-aware config with an automatic version bump
Renovate only ever rewrites appVersion or an image tag, so every PR it
opened against a chart directory failed the build-chart version check
(#138, #139). ci/renovate-bump-chart.sh recomputes
version: <semver>+up<appVersion> as a postUpgradeTasks hook: chart major
when the app major moves, chart patch otherwise.

Each chart renders its main image as <repo>:{{ .Chart.AppVersion }}, so
repository and version live in different files and Renovate cannot join
them. The mapping is one customManager per chart in renovate.json5,
deliberately not a comment inside each Chart.yaml - that would touch all
20 chart directories and force 20 publishes for a comment change.

Patch and digest updates automerge after a 3-day minimumReleaseAge once
the pipeline is green; majors arrive one line at a time to match the
stepwise app-major procedure. ci/** stays excluded: the install-test
fixtures pin throwaway infrastructure to major lines on purpose.
2026-08-24 11:42:43 +02:00
jklein e730a81b17 Merge pull request #140 from jk-cluster/renovate/1password-load-secrets-action-5.x
Update 1password/load-secrets-action action to v5
2026-08-24 09:20:12 +00:00
jklein a176c7576c Merge pull request #142 from jk-cluster/renovate/azure-setup-helm-5.x
Update azure/setup-helm action to v5
2026-08-24 09:20:01 +00:00
jlab-renovate[bot] 5026622763 Update azure/setup-helm action to v5 2026-08-24 00:01:19 +00:00
jlab-renovate[bot] 35d381432c Update actions/checkout action to v7 2026-08-23 23:01:23 +00:00
jlab-renovate[bot] f65f31bed8 Update 1password/load-secrets-action action to v5 2026-08-23 23:01:15 +00:00
jklein 3fa67d55ef rss-bridge: new chart
Takes over the four loose manifests in cluster-config/rss-bridge/ as a
proper chart, on the current template-chart standard: strict values
schema, null-safe helpers, computed limits, replicas/scaleDown,
checksum/config, NOTES.txt.

Two things deviate from the repo standard on purpose:

- The Ingress models host AND TLS secret name per entry instead of the
  single conventional tls-<release>-<chart>-ingress. The installation
  this replaces has grown three separate certificates, one per host.
  Renaming them would make cert-manager issue three new ones and leave
  each host unreachable until it did - a self-inflicted outage on a
  deployment that has been up for over a year. Entries sharing a secret
  name are grouped into one tls entry, and omitting the name falls back
  to the convention, so consolidating later is a values change.

- Requests and limits are decoupled. The old manifest requested 2Gi of
  ephemeral storage, identical to its limit, reserving two gigabytes for
  a workload measured at 2.2 MB after fetching all five whitelisted
  bridges. The request drops to 64Mi; the limit stays at 2Gi.

Hardening was verified rather than assumed. The image ships no USER and
runs as root by default, but runs fully hardened once its writable paths
are provided: uid/gid 33, readOnlyRootFilesystem, all capabilities
dropped, seccompProfile RuntimeDefault. The writable paths were found by
running the image with a writable rootfs, exercising every bridge and
reading its diff layer - /app/cache, /run, /run/php, /var/lib/nginx.
/tmp did not show up that way, because PHP's opcache creates its lock
file there and unlinks it immediately; it only surfaced when the
hardened container died at startup. Stopping at the first writable path
would have shipped a chart that cannot start.

Probes use the app's own /?action=health, which renders fixed JSON
without touching the cache or any remote site, so neither a scraped site
going down nor an unwritable cache can restart the pod.

Fixes #128
2026-08-23 23:33:23 +02:00
jklein 1ae5e1a7c3 CI: report Trivy misconfiguration findings for changed charts
Adds a trivy-config job to the PR pipeline that renders each changed chart
with Helm and runs `trivy config` over the rendered manifests. Reporting
only - TRIVY_CONFIG_MODE=report always exits 0, so the job never blocks a PR.

Rendered manifests rather than the chart directory: `trivy config <chart-dir>`
renders with default values, which fails on every chart here because of their
required() values - and Trivy does not fail with it, it logs "Skipping chart"
and prints an empty, green report.

Values come from the install-test fixtures (ci/<chart>/test-values.yaml), the
only committed per-chart values in the repo; none of them touches
securityContext, images or capabilities, so the scan sees the chart's own
hardening. Charts without fixtures get ci/trivy/values/<chart>.yaml.

Exceptions live in ci/trivy/trivyignore.yaml in Trivy's native ignore-file
schema, each with a statement - the script refuses to run without one and
reports suppressed findings with their reason instead of hiding them.
AVD-KSV-0125 is configured instead of excepted: ci/trivy/data/ksv0125.yaml
lists the trusted registries, so the check stays able to flag a genuinely
foreign source.

Refs #84.
2026-08-23 23:14:12 +02:00
jklein a68192e5fb Import minecraft-server chart for Fleet migration stage 1 (java8 line)
Imports the chart from cluster-config functionally unchanged, wires it into
the publish/validate/install-test pipelines and publishes it as the first of
three Java lines (0.4.0+upjava8).

The only deviation from the source chart is the chart-global scaleDown flag
plus a server.replicas value, following the satisfactory pattern: two of the
three servers stand at 0 replicas in the cluster, which the chart could not
express, and Fleet would otherwise start them on reconcile. The default
(scaleDown: false) still renders replicas: 1, so the rendering of the running
server is unchanged - verified byte-identical against the three real values
files for all three Java lines.

Known deficiencies (hardening, probes, naming scheme, hardcoded values,
missing icon, the misleading mc-router auto-discovery annotations) are left
untouched on purpose and are scheduled for stage 2.
2026-08-23 15:57:17 +02:00
jklein 3be5111630 Import minecraft-router chart unchanged (Fleet migration stage 1)
Takes the existing mc-router chart over from cluster-config as-is so the
deployment can move to Fleet without any change to the rolled-out state.
Convention alignment follows in stage 2, the app update in stage 3.

The only deviation from "unchanged": Chart.yaml carried name:
minecraft-server (copy-paste from the sister chart). The publish job pushes
by the glob <directory>-*.tgz while helm package names the archive after the
Chart.yaml name, so without this correction the push finds no file.

Version 0.1.1+up1.25.1 - chart semver stays at 0.1.1, the +up suffix is repo
policy and does not affect rendering.

Also wires up CI: publish workflow, change-app-version choice list,
install-test values (CI-only node-port override, since 25565 is outside the
k3d default range) and the README chart table.
2026-08-23 12:58:21 +02:00
jklein c668780fd3 Fix satisfactory publish workflow name 2026-08-22 15:15:21 +02:00
jklein cc6084ca58 Add install-test stage to the PR pipeline (k3d)
New install-test job in validate-charts.yml: for exactly the charts a PR
changes, install them into an ephemeral k3d cluster (pinned k3d v5.9.0,
k3s v1.35.5-k3s1) and require every Deployment/StatefulSet to become
Ready. Runs non-blocking (continue-on-error) during the stabilization
phase.

Fixtures live at the repo root under ci/ (not inside chart directories,
so they neither trigger publishes on merge nor get packaged): a stub
OnePasswordItem CRD, per-chart test values and fixtures (dummy secrets
with in-cluster DSNs, throwaway postgres/redis/dex, synapse-generate
seed job, static hostPath PVs where charts pin storage classes or need
RWX), plus a shared ci/run-install-test.sh harness that also runs
locally.

Excluded with documented reasons (ci/excluded-charts.txt): satisfactory
(multi-GB image), teamspeak-server (TS6 beta license expired, image
crashes on start), template-chart (placeholder image).

All 14 non-excluded charts verified locally in k3d using only the
committed fixtures.
2026-08-21 23:12:38 +02:00
jklein ded2f59020 Rename detect job output to any-chart-changed for clarity 2026-08-21 17:03:22 +02:00
jklein 79f9260f56 Add PR pipeline validating changed helm charts
On every pull request, detect which chart directories were touched and
run helm lint --strict, helm package, and a chart-version bump check
for exactly those charts. PRs without chart changes skip the build.

Fixes #5
2026-08-21 16:55:47 +02:00
jklein 3c7e7f8e00 Remove unused music-assistant-skill chart
The chart is no longer needed. Removes the chart directory, its publish
workflow, and its row in the README chart table. Already published
versions remain in the registry.

Fixes #7
2026-08-21 16:50:43 +02:00
jklein 1b56c4bdb2 Upgrade actions/checkout from v2 to v4
Fixes #6
2026-08-21 16:47:29 +02:00
jklein 3bed5a1717 Merge pull request #13 from jk-cluster/fix/publish-branch-filter
Restrict publish workflows to pushes on main
2026-08-21 16:42:21 +02:00
jkleinandClaude Fable 5 62d2caae66 Restrict publish workflows to pushes on main
Without a branch filter, any push on any branch touching a chart
directory packaged and published the chart to the registry.

Fixes #4

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 16:40:20 +02:00
jkleinandClaude Fable 5 04283df8c4 Remove non-functional dependabot config
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 16:20:49 +02:00
jklein 41e1f62ede feat(voucher-vault): added publish workflow 2026-04-13 20:15:32 +02:00
jklein 81743b23ed feat(dependabot): update appVersion in Helm Charts 2026-04-08 19:33:57 +02:00
jklein ab78e0f9e7 feat(dependabot): changes 2026-04-08 17:56:21 +02:00
jklein 4c74d13866 feat(dependabot): changed directory to only update homeassistant 2026-04-08 17:48:32 +02:00
jklein 0d6bd05db2 feat(dependabot): Fixed directory search pattern 2026-04-08 17:41:44 +02:00
jklein c9634bca91 feat(dependabot): enabled version-updates for helm-charts
Added support for Helm updates with daily checks.
2026-04-08 17:37:11 +02:00
jklein ce0ecc66e5 feat(rallly): fixed path in publish-workflow 2026-04-08 15:44:01 +02:00
jklein 106dd5cf62 feat(rallly): fixed path in publish-workflow 2026-04-08 15:08:22 +02:00
jklein b01946f755 feat(rallly): added publish-workflow 2026-04-08 15:04:54 +02:00
jklein 627b841e61 feat(patchmon): added publish workflow 2026-04-03 19:26:59 +02:00
jklein 48db701078 feat(paperless-ngx): added to update version script 2026-03-23 19:06:49 +01:00
jklein 69d16c2112 feat(paperless-ngx): added to update version script 2026-03-23 17:48:59 +01:00
jklein 8d0f3eaf96 feat(paperless-ngx): added publish workflow 2026-03-23 17:42:01 +01:00
jklein 332a370c4b feat(outline): added publish workflow 2026-03-19 13:33:25 +01:00
jklein 0a9d7dfa5a feat(deployment): moved to fleet-cd deployment 2026-03-19 11:50:23 +01:00
jklein 146bf6ef9a feat(change-version): fixed chart versioning 2026-03-18 12:30:28 +01:00
jklein e60ccb7d34 feat(matrix-synapse): fixed publish workflow 2026-03-17 22:08:50 +01:00
jklein 8495540551 feat(matrix-synapse): added publish workflow 2026-03-17 22:07:23 +01:00
jklein eefc9345cf feat(cyberchef): added publish workflow 2026-03-17 17:33:33 +01:00
jklein 952088b3fb feat(satisfactory): added publish workflow 2026-03-16 21:20:33 +01:00
jklein 3ff932dc1f feat(charts): moved to other chart-version format 2026-03-09 23:15:16 +01:00
jklein 329b7ab22b feat(homeassistant): added publish-workflow 2026-03-03 18:03:04 +01:00
jklein 20ead042cb feat(music-assistant-skill): added publish-workflow 2026-02-25 20:56:36 +01:00
jklein e8c963c7d5 feat(gotenberg): added publish/deploy workflow 2026-02-23 16:33:03 +01:00