The bundled `postgresql-ha` sub-chart was the only HA-ready database option, but it pinned us to a Bitnami chart
whose images are no longer freely distributed, and it bundled repmgr and pgpool into the release. Operating a
Postgres cluster through a Helm release also means the chart has to reimplement failover, backup and upgrade
orchestration that a dedicated operator already solves.
CloudNativePG is the de-facto standard operator for Postgres on Kubernetes and handles instance management,
streaming replication, switchover and rolling upgrades itself. The operator is deliberately *not* part of this
chart: cluster-scoped CRDs and controllers do not belong into an application release and would conflict with an
operator that is already installed. The chart only renders the namespaced `Cluster` resource, so the operator can
be managed independently.
Because the operator cannot be assumed to be present, `cloudnativePG.enabled` defaults to `false`. Existing users
of `postgresql` or an external database are therefore unaffected.
Credentials follow the chart-wide `secrets.*` convention. Only the password is read from a Secret, because
CloudNativePG requires `bootstrap.initdb.database` and `bootstrap.initdb.owner` as literals in the `Cluster` spec
and cannot resolve them from a Secret. The password is injected into the `init-app-ini` container as
`GITEA__database__PASSWD` instead of being written into the generated `app.ini`.
BREAKING CHANGE: The `postgresql-ha` sub-chart and all `postgresql-ha.*` values have been removed. There is no
in-place migration path between the two deployments: dump the database of the old `postgresql-ha` release with
`pg_dump`, remove the `postgresql-ha` values, deploy the chart with `cloudnativePG.enabled=true` and restore the
dump. Setting `postgresql-ha` now fails the release with a pointer to the changelog.
Co-authored-by: Copilot <copilot@github.com>
The chart conventions demand camelCase file names, forbid short names like `svc` and require the unit tests to
mirror the template structure. The unit tests followed none of that consistently. Four casings existed side by
side - camelCase (extraInitContainers.yaml), kebab-case (checksum-annotations.yaml), a snake and kebab mix
(init_directory_structure.sh-rootless.yaml) and all caps (HA.yaml) - so there was no pattern to copy when
adding a suite, which is how the inconsistency kept growing.
Three groups of problems are fixed:
- svc-configuration.yaml used exactly the short name the conventions forbid for files and keys.
- Several file names repeated their own directory, for example deployment/deployment-additional-config.yaml and
metric-secret/metrics-secret-servicemonitor-disabled.yaml, which names the subject three times. The directory
already carries that information, so the file name now only carries the scenario. The default scenario of a
template is named basics.yaml.
- Four suites lived in a directory of a template they do not assert on. They were filed under deployment/
because the deployment is rendered as a side effect, not because it is the subject:
deployment/deprecations.yaml -> deprecation/deployment.yaml
deployment/inline-config.yaml -> config/inlineConfig.yaml
deployment/storage-class-configuration.yaml -> persistentVolumeClaim/storageClass.yaml
deployment/svc-configuration.yaml -> service/configuration.yaml
storage-class-configuration.yaml is the clearest case: a persistentVolumeClaim directory already existed next
to it. The suite titles of the two suites whose subject changed are adjusted accordingly.
The Makefile passed `--file unittests/helm/values-conflicting-checks.yaml`, but that file does not exist in the
tree. `helm unittest` ignores a missing path without a warning, so the flag has been dead for an unknown amount
of time while still suggesting the checks run. It is removed; the `unittests/helm/**/*.yaml` glob would pick
the file up anyway if it ever returns.
The naming rule is written down in the copilot instructions, together with the constraint that the glob matches
only a single directory level, so a suite can never be placed directly in unittests/helm/.
All 49 suites and 267 tests still pass.
Co-authored-by: Copilot <copilot@github.com>
The contributor guidelines never defined how a `suite` title has to look, only how an `it` title has to look.
Without a rule five competing schemes grew side by side: `config template | cache config`, `deployment
template (probes)`, `ServiceMonitor template (basic)`, `Test Gateway API httpRoute.yaml` and `Dependency checks
| Customization integrity | valkey`. 24 of the 49 titles started with a lowercase letter, which contradicts the
sentence rule that already applies to the test titles.
More than cosmetics, the missing rule produced three concrete defects:
- `deployment template` was used by both deployment-additional-config.yaml and extraInitContainers.yaml, and
`Init template` by both init_directory_structure.sh.yaml and its rootless counterpart. `helm unittest`
identifies a failing suite by its title, so a failure in either file printed the same header and the report
did not say which file to open.
- deployment/inline-config.yaml was titled `config template`, although it lives in the deployment directory and
asserts on secret_inlineConfig.yaml. It read like a sixth member of the `config template | ...` group.
- persistentVolumeClaim.yaml was titled `PVC template`, using exactly the short name the chart conventions
forbid for files and keys.
All suites now follow `Test <subject> <scenario>`, for example `Test deployment probes` or `Test gateway API
httpRoute`. The subject is the template under test, the scenario is what distinguishes the suite from its
siblings, so every title is unique and sorts next to its related suites. The `Test ` prefix of the Gateway API,
ingress and route suites is kept, because it is the only part of the old schemes that already read as a
sentence; the redundant `.yaml` suffix and the `tests` suffix of the storage class suite are dropped.
The rule is written down in the Unit Tests section of the copilot instructions, so the next suite does not have
to guess which of the five schemes was meant.
Co-authored-by: Copilot <copilot@github.com>
The inline-config Secret rendered its payload via `stringData`. That field is write-only: the API server
decodes it into `data` and does not persist `stringData` itself. As a result Helm's three-way merge could
never prune a key that was removed from the values, because the generated patch targets `stringData` while
the live object only has `data`. Stale sections therefore survived every upgrade and the init container kept
writing them back into `app.ini` on each start.
To prevent this class of bug from being reintroduced, document the rule explicitly: render Secret payloads as
base64 `data`, and assert Secret content in unit tests via `data.*` with `decodeBase64: true` plus a
`notExists` assertion for `stringData`.
See: https://gitea.com/gitea/helm-gitea/issues/1109
See: https://gitea.com/gitea/helm-gitea/pulls/1110
Co-authored-by: Copilot <copilot@github.com>
The `templates/gitea` subdirectory did not group anything meaningful, since every template of this chart belongs to
Gitea. It only duplicated the chart name in every path and forced the unit tests to spell out
`templates/gitea/<name>.yaml`, while `_helpers.tpl` and `NOTES.txt` already lived directly in `templates`.
All templates now live in `templates`, which matches the layout of the bundled sub-charts and the Helm defaults.
The checksum helper in `templates/_secrets.tpl` built its include path from `$root.Template.BasePath` and therefore
carried the subdirectory in a `printf` format string instead of a literal path. Without adjusting it the chart failed to
render with "no template gitea/templates/gitea/secret_config.yaml associated with template gotpl".
Co-authored-by: Copilot <copilot@github.com>
The Makefile targets were renamed to a `<group>/<action>` scheme and a `missing-dot` target was added, but the Copilot
instructions still referenced the old `unittests-*` targets and a non-existent `unittests` target. Contributors and
agents following these instructions therefore ran commands that no longer exist.
Also correct the yamllint configuration file name to `.yamllint.yaml`.
Co-authored-by: Copilot <copilot@github.com>
An Ingress that points at a Service which the chart does not render is broken by definition: the backend reference
cannot resolve and the ingress controller reports the rule as unavailable. The render condition therefore now also
requires `service.http.enabled` and lives in the new `gitea.ingress.enabled` helper, so the same rule can be reused
by other templates instead of being duplicated.
The namespace is taken from `.Release.Namespace` again. The `namespace` value is not a documented chart parameter,
and letting a single resource opt out of the release namespace breaks `helm uninstall` and Argo CD pruning, because
neither tracks objects outside the release namespace.
The `ingress.className` default changes from an empty string to `nginx`. An empty class makes the cluster fall back
to the default IngressClass, which silently produces a different result per cluster; naming the controller the chart
is tested against makes the rendered output predictable.
The scattered ingress suites are consolidated into a single `unittests/helm/ingress/ingress.yaml` that pins the
release name, namespace and appVersion, as required by the testing conventions, and covers the enable/disable matrix,
annotations, labels, TLS and a custom HTTP port.
BREAKING CHANGE: The Ingress is no longer rendered when `service.http.enabled` is `false`. `ingress.className` now
defaults to `nginx` instead of the cluster's default IngressClass. The undocumented `namespace` value no longer
applies to the Ingress.
Co-authored-by: Copilot <copilot@github.com>
The chart-managed init containers were hardcoded inside `deployment.yaml`. Their image, environment, resources,
security context and volume mounts could not be adjusted individually, and custom init containers could only be
prepended or appended as a whole via `preExtraInitContainers`/`postExtraInitContainers`.
The init containers are now rendered from `deployment.initContainers`, an ordered list whose entries either `link` a
chart-managed init container (`initDirectories`, `initAppIni`, `initConfigureGPG`, `initConfigureGitea`) or provide a
free-form `container` definition. This allows custom containers at any position and makes the execution order
explicit. Each linked init container has its own configuration block in `values.yaml` and falls back to
`deployment.gitea.securityContext` and `initContainers.resources` when unset.
To support per-container images, `gitea.image` was split into the generic helper `gitea.image.name`, which renders an
arbitrary `image` dict instead of only `deployment.gitea.image`.
The pod annotations moved from `deployment.yaml` into the new helper `gitea.pod.annotations`. The SHA sum annotations
now also cover user-provided Secrets: their content is unknown to the chart, so the Secret is read from the cluster via
Helm's `lookup` function. Chart-managed Secrets keep using the rendered manifest, because the cluster still holds their
pre-upgrade state during rendering.
Because `lookup` requires `get` permission on Secrets and silently returns nothing during client-side rendering
(`helm template`, `--dry-run`, Argo CD without a live cluster), `addSHASumAnnotation` now defaults to `false`. The
trade-offs are documented in the README so users can make an informed decision.
BREAKING CHANGE: `preExtraInitContainers` and `postExtraInitContainers` have been removed. Add an entry with a
`container` key before or after the linked init containers in `deployment.initContainers` instead.
BREAKING CHANGE: `secrets.<secret>.addSHASumAnnotation` now defaults to `false`. Set it to `true` explicitly to keep
the rollout trigger on Secret changes.
Co-authored-by: Copilot <copilot@github.com>
Add full Gateway API support for exposing Gitea via HTTPRoute, TCPRoute, BackendTLSPolicy, and ClientSettingsPolicy resources.
New templates:
- `httpRoute.yaml` — renders an HTTPRoute with configurable
parentRefs, hostnames, and rules (defaults to PathPrefix `/`)
- `tcpRoute.yaml` — renders a TCPRoute for SSH traffic
- `backendTLSPolicy.yaml` — renders a BackendTLSPolicy for
encrypted backend connections with required validation config
- `clientSettingsPolicy.yaml` — renders an NGINX Gateway Fabric
ClientSettingsPolicy to raise the request body size limit
Infrastructure:
- `gatewayAPI.enabled` global toggle gates all resources
- Resources grouped under `gatewayAPI.core.*` and `gatewayAPI.nginx.*`
- Helper templates extracted into dedicated `_*.tpl` files
- Service name helpers (`gitea.service.http.name`, `gitea.service.ssh.name`)
extracted into `_services.tpl`; service templates renamed to camelCase
- `ROOT_URL`, `DOMAIN`, and `SSH_DOMAIN` auto-resolve from
`httpRoute.hostnames[0]`; `httpRoute.tls` switches to `https`
Documentation:
- New `docs/gateway-api.md` with topology examples, BackendTLSPolicy
setup, sectionName guidance, SSH considerations, and NGINX body
size limit configuration
- `.github/copilot-instructions.md` with project conventions
- README parameter table auto-generated via `make readme`
Tests:
- Helm unit tests for all four new resource templates
- Config tests for hostname/TLS resolution from Gateway API values
Co-authored-by: Todd Marimon <toddmarimon@gmail.com>