Skip to content

Release v0.11.0 (minor) - #501

Merged
slauger merged 42 commits into
mainfrom
develop
Aug 10, 2026
Merged

slauger merged 42 commits into
mainfrom
develop

Conversation

@github-actions

@github-actions github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Changes

Files changed

 .github/workflows/_conforma-validate.yaml          |  13 +-
 .github/workflows/_container-build.yaml            |  41 ++++++
 .github/workflows/_e2e-run.yaml                    |   7 +-
 .github/workflows/ci.yaml                          |  49 ++++++-
 .github/workflows/e2e-images.yaml                  |  42 +++++-
 .github/workflows/e2e.yaml                         |   9 ++
 .github/workflows/release.yaml                     |  74 ++++++++--
 Makefile                                           |  21 +--
 README.md                                          |  12 ++
 api/v1alpha1/config_types.go                       |  62 +++++++-
 api/v1alpha1/config_validation_test.go             |  59 +++++++-
 api/v1alpha1/server_types.go                       |  11 +-
 api/v1alpha1/signingpolicy_types.go                |   2 +
 api/v1alpha1/zz_generated.deepcopy.go              |   8 +-
 charts/openvox-operator/Chart.yaml                 |   4 +-
 .../crds/openvox.voxpupuli.org_configs.yaml        | 121 ++++++++++++----
 .../crds/openvox.voxpupuli.org_databases.yaml      |   2 +-
 .../crds/openvox.voxpupuli.org_servers.yaml        | 102 ++++++++++----
 .../openvox.voxpupuli.org_signingpolicies.yaml     |   8 +-
 charts/openvox-stack/Chart.yaml                    |   4 +-
 charts/openvox-stack/README.md                     |   8 +-
 charts/openvox-stack/ci/code-pvc-values.yaml       |   5 +-
 .../ci/puppet-command-overrides-values.yaml        |  50 +++++++
 charts/openvox-stack/templates/config.yaml         |  36 +++--
 charts/openvox-stack/templates/servers.yaml        |  17 +++
 charts/openvox-stack/tests/config_test.yaml        |  20 ++-
 charts/openvox-stack/tests/database_test.yaml      |   2 +-
 charts/openvox-stack/tests/servers_test.yaml       |   2 +-
 charts/openvox-stack/values.schema.json            |  21 ++-
 charts/openvox-stack/values.yaml                   |  26 +++-
 .../crd/bases/openvox.voxpupuli.org_configs.yaml   | 121 ++++++++++++----
 .../crd/bases/openvox.voxpupuli.org_databases.yaml |   2 +-
 .../crd/bases/openvox.voxpupuli.org_servers.yaml   | 102 ++++++++++----
 .../openvox.voxpupuli.org_signingpolicies.yaml     |   8 +-
 config/samples/config.yaml                         |   3 +-
 config/samples/database.yaml                       |   2 +-
 docs/concepts/code-deployment.md                   |   4 +-
 docs/concepts/config-rollout.md                    |   9 +-
 docs/concepts/database.md                          |  19 ++-
 docs/concepts/external-node-classification.md      |   4 +-
 docs/concepts/report-processing.md                 |   2 +-
 docs/examples/index.md                             |   6 +-
 docs/getting-started/quickstart.md                 |   2 +-
 docs/reference/config.md                           |  48 ++++++-
 docs/reference/database.md                         |   2 +-
 docs/reference/index.md                            |  32 ++++-
 docs/reference/server.md                           |   2 +-
 docs/reference/signingpolicy.md                    |   4 +-
 images/openvox-agent/Containerfile                 |  11 +-
 images/openvox-db/Containerfile                    |   6 +-
 images/openvox-e2e-code/Containerfile              |   2 +-
 images/openvox-mock/Containerfile                  |   2 +-
 images/openvox-operator/Containerfile              |   2 +-
 images/openvox-server-reference/Containerfile      |   2 +-
 images/openvox-server/Containerfile                |   8 +-
 images/openvox-versions.yaml                       |  38 +++++
 .../certificateauthority_controller_test.go        |   2 +-
 .../controller/certificateauthority_job_test.go    |   2 +-
 internal/controller/config_autosign.go             |  13 +-
 internal/controller/config_autosign_test.go        |  40 ++++--
 internal/controller/config_controller.go           |   7 +
 internal/controller/config_controller_test.go      | 118 +++++++++++++++-
 internal/controller/config_enc.go                  |   5 +
 internal/controller/config_rendering.go            |  57 +++++++-
 internal/controller/config_rendering_test.go       |  59 ++++++++
 internal/controller/helpers.go                     |  49 ++++++-
 internal/controller/helpers_test.go                |  62 ++++++--
 internal/controller/server_controller_test.go      |  44 ++++++
 internal/controller/server_deployment.go           | 156 +++++++++++++--------
 internal/controller/server_deployment_test.go      | 117 ++++++++++++++++
 internal/controller/testutil_test.go               |  26 +++-
 internal/webhook/config_webhook.go                 |   2 +
 internal/webhook/config_webhook_test.go            |  23 +++
 internal/webhook/helpers.go                        |  19 +++
 internal/webhook/server_webhook.go                 |   2 +
 internal/webhook/signingpolicy_webhook.go          |  15 ++
 internal/webhook/signingpolicy_webhook_test.go     |  51 +++++++
 renovate.json                                      |  29 +++-
 tests/e2e/agent-basic/chainsaw-test.yaml           |   6 +-
 tests/e2e/agent-broken/chainsaw-test.yaml          |   6 +-
 tests/e2e/agent-concurrent/chainsaw-test.yaml      |  10 +-
 tests/e2e/agent-enc/chainsaw-test.yaml             |   6 +-
 tests/e2e/agent-full/chainsaw-test.yaml            |   6 +-
 tests/e2e/agent-idempotent/chainsaw-test.yaml      |   8 +-
 tests/e2e/agent-report/chainsaw-test.yaml          |   6 +-
 tests/e2e/autosign-policy/chainsaw-test.yaml       |  38 ++++-
 tests/e2e/cert-rotation/chainsaw-test.yaml         |   4 +-
 tests/e2e/code-pvc/chainsaw-test.yaml              |  50 +++++--
 tests/e2e/database-cnpg/chainsaw-test.yaml         | 114 ++++++++++++++-
 tests/e2e/external-ca/chainsaw-test.yaml           |   8 +-
 tests/e2e/metrics/chainsaw-test.yaml               |   2 +-
 tests/e2e/multi-server/chainsaw-test.yaml          |   2 +-
 tests/e2e/pool-gateway/chainsaw-test.yaml          |   2 +-
 .../puppet-command-overrides/chainsaw-test.yaml    | 112 +++++++++++++++
 tests/e2e/readonly-rootfs/chainsaw-test.yaml       |   6 +-
 tests/e2e/single-node/chainsaw-test.yaml           |   2 +-
 .../webhook-validation-config/chainsaw-test.yaml   |   6 +-
 .../webhook-validation-database/chainsaw-test.yaml |  10 +-
 .../webhook-validation-server/chainsaw-test.yaml   |   2 +-
 99 files changed, 2186 insertions(+), 399 deletions(-)

Release prediction

Predicted release: v0.10.0 -> v0.11.0 (minor)
3 feature(s) 4 fix(es)


Source: develop | Target: main | Trigger: Successful CI on develop

Auto-generated by GitHub Actions & AI - updated automatically on new commits.

slauger and others added 21 commits August 4, 2026 12:01
Introduce images/openvox-versions.yaml as the single source of truth for
the OpenVox versions baked into the content images, holding both the
stable 8.x line and the 9.x pre-release line. CI/release/e2e workflows
will read it (yq -o=json '.include') to build a per-major matrix and pass
the versions as build-args.

Add a Renovate custom manager for the new file and split the OpenVox
package rule into two per-major rules (matchCurrentValue ^8./ vs ^9./)
so the majors bump independently in separate grouped PRs, with
pre-releases enabled for the 9.x line.

Refs #472
Drop the '# renovate:' annotations from the server, db and agent
Containerfiles now that images/openvox-versions.yaml is the source of
truth; keep the ARG defaults (8.x) as a fallback for standalone local
builds. CI injects the real versions as build-args.

Parameterize the agent's hardcoded openvox8-release-el-9 RPM via a new
ARG OPENVOX_MAJOR=8 so the v9 agent can install from the openvox9 repo.

Refs #472
Wire a multiline build_args input into docker/build-push-action so
callers can inject the OpenVox versions (and OPENVOX_MAJOR for the agent)
per matrix entry. Refs #472
Add a prepare job to ci.yaml, release.yaml and e2e-images.yaml that reads
images/openvox-versions.yaml (yq -o=json '.include') and emits a per-major
build matrix. The server, db and agent build jobs now run once per major
with fail-fast: false, tagging images openvox-{server,db,agent}-{8,9} and
passing the pinned versions as build-args (agent also gets OPENVOX_MAJOR).

Only major 8 is tagged :latest (matrix.latest); major 9 is built and
pushed but never latest and never the default. Release conforma validate
jobs are matrixed over both majors; since matrixed reusable-workflow job
outputs collapse, they reconstruct the per-major image reference and let
ec resolve the digest (digest input on _conforma-validate.yaml is now
optional).

Refs #472
Point the default OpenVox content images at the new major-suffixed names
so the operator ships OpenVox 8 by default: the ImageSpec repository
default (and regenerated CRDs), the openvox-stack chart values and unit
tests, the config/database samples, and the Makefile image vars, local
build tags and STACK_HELM_SET.

Switching a Config to OpenVox 9 is now an explicit opt-in via
spec.image.repository (openvox-server-9). Note: the old unsuffixed images
(openvox-server, openvox-db) are no longer published — hand-pinned
references must move to the -8 variants (release-notes migration).

Refs #472
Parameterize the chainsaw e2e suite so it targets the -8 images by
default and can run against -9 via OPENVOX_MAJOR. helm --set repositories
use ${OPENVOX_MAJOR:-8}; agent image assertions use a new 'major' chainsaw
binding (env('OPENVOX_MAJOR') || '8'). Static webhook-validation specs are
pinned to the -8 variants. Makefile forwards OPENVOX_MAJOR (default 8)
into E2E_CHAINSAW.

Refs #472
Add an 'OpenVox 8 and 9' section to the README and a note to the Config
reference explaining the per-major image naming (openvox-server-8/-9),
that 8 is the default and only 8 is tagged :latest, and that 9 is a beta.
Update inline image examples to the -8 variants (the unsuffixed images
are no longer published) and note the migration for hand-pinned refs.

Refs #472
Complete the image rename for the static webhook-validation specs, which
are version-agnostic schema tests. Refs #472
The shared ImageSpec default flows into the Server and Database CRDs too;
regenerate them so the committed manifests match. Refs #472
The ArtifactHub 'images' annotations in both Chart.yaml files still
pointed at the unsuffixed openvox-server:latest / openvox-db:latest, which
are no longer published (would 404); repoint them to the -8 variants.
Sync the helm-docs generated openvox-stack README defaults to match the
updated values.yaml.

Refs #472
The unicode lint rejects em-dashes (U+2014) as AI watermark characters.
Refs #472
Append a 'OpenVox component versions' table (read from
images/openvox-versions.yaml) to each GitHub release's notes so every
operator release records the exact server/db/agent versions it ships.
README and the Config reference point at openvox-versions.yaml as the
live source, kept current by Renovate. Avoids a hand-maintained,
drift-prone version matrix.

Refs #472
The OpenVox 9 pre-release tarballs are not published on
artifacts.voxpupuli.org yet, so the -9 image builds 404 on ADD. Since
fail-fast only prevents cancellation (not job failure), the whole run
went red on the v9 leg despite v8 passing.

Add an allow_failure input to _container-build.yaml (continue-on-error on
the build step and manifest job) and set allow_failure: matrix.major != 8
on the matrixed server/db/agent build jobs, so v9 is built best-effort and
never blocks. It turns green automatically once the 9.x artifacts land.
Release conforma validation now targets only the -8 (released, :latest)
images.

Refs #472
Add an openvox_major input to e2e.yaml and _e2e-run.yaml (default 8) and
pass it to 'make e2e-run-test' as OPENVOX_MAJOR, completing the chain
e2e.yaml -> _e2e-run.yaml -> Makefile -> chainsaw. The existing tests
already select the image variant via ${OPENVOX_MAJOR:-8} and the 'major'
binding, so dispatching E2E with openvox_major: 9 runs the suite against
the -9 images once they are published upstream.

Refs #472
The <ca>-autosign-policy Secret is subPath-mounted, which kubelet does not
live-sync, and unlike the ENC and report-webhook Secrets it was not hashed
into the pod template. A SigningPolicy change therefore reached neither the
running file nor triggered a rollout, so it only took effect after a manual
CA pod restart.

Hash the autosign policy Secret into an autosign-policy-secret-hash annotation
on CA pods, mirroring the existing enc-secret-hash/report-webhook-secret-hash
handling, so a SigningPolicy edit rolls the CA pod and applies automatically.

Refs #492
The code comments and docs claimed a SigningPolicy change synced into the CA
pod without a restart via kubelet. That was never true for the subPath-mounted
policy Secret, and after the autosign-policy-secret-hash fix the mechanism is
an explicit pod rollout, mirroring how the ENC and report-webhook Secrets
already work.

Correct the autosign comments in config_rendering.go and config_autosign.go,
update the SigningPolicy reference and the config-rollout concept doc to list
the new hash annotation and rollout behaviour, and fix the external node
classification doc which made the same inaccurate live-sync claim for ENC.

Refs #493
Add spec.puppet.autosignCommand and spec.puppet.externalNodesCommand to Config
as escape hatches for teams that need to run their own autosign or ENC script
instead of the built-in binaries.

When set, puppet.conf points autosign / external_nodes at the given executable
and the corresponding declarative flow is disabled: the policy / ENC Secret is
neither rendered by the Config controller nor mounted by the Server controller,
and the hash annotation is dropped. Unset, behaviour is unchanged and the
built-in SigningPolicy / NodeClassifier flow drives the shipped binaries.

The executable must live in the server image or be mounted via the Server's
extraVolumes; credentials come in the same way via extraVolumes/extraEnv. This
is the override half of the request only -- a native webhook policy type on
SigningPolicy/NodeClassifier remains a follow-up.

Includes CRD regeneration, openvox-stack chart values/schema/README, docs and
unit tests for both the rendered puppet.conf and the skipped mounts/Secrets.

Refs #490, #491
Change spec.code on Config and Server from a single object to a list of code
sources, so a Server can assemble its codedir from several independent volumes:
per-environment control repos from different OCI images, plus a global modules
directory or hieradata that live next to environments/.

Each entry sets one source (image or claimName) and an optional mount target:
  - environment -> mounted at <environmentpath>/<environment>
  - mountPath   -> mounted at an absolute path, which must be under the Puppet
                   codedir (/etc/puppetlabs/code), enforced via CEL
Backwards compatible: 0 entries keeps the emptyDir bootstrap; a single entry
without a target is mounted as the whole environments tree at environmentpath,
exactly as before. With more than one entry each must set a unique environment
or a mountPath (uniqueness enforced by the admission webhook, the rest by CEL).
A Server's code replaces the Config's code (not merged).

Being on v1alpha1, this is the cheap moment for the breaking object->array CRD
change. String fields and the list carry maxLength/maxItems bounds so the
per-item CEL rules stay within the API server cost budget.

The openvox-stack chart accepts config.code / servers[].code as either the
existing object (rendered as a one-element list, so --set config.code.image and
the CI values files keep working) or a full list for multiple sources.

Includes CRD/deepcopy regeneration, chart template/values/schema/README, docs,
and unit, webhook and envtest CEL coverage.

Refs #489. Closes #476
The unicode lint check flags em-dashes as suspicious watermark characters.
Replace the five in the config and CodeSpec reference docs with ASCII hyphens.
…-autosign-fix

feat: code list, custom autosign/ENC commands, and autosign policy rollout fix
feat: support running OpenVox 8 and 9 in parallel (matrix build + image rename)
slauger and others added 6 commits August 4, 2026 22:41
The OpenVox 9 content images fail to build on every CI run because the 9.0
pre-release artifacts are inconsistent: the agent RPM is published only as
9.0.0~beta1 (tilde, not the -beta1 GitHub tag), the server/db images install
from a release tarball but the 9.0 betas ship only RPMs/DEBs (no tarball), and
the openvox gem uses yet another form (9.0.0.pre.beta1). Building 9 today would
require reworking the server/db Containerfiles plus per-artifact version
normalisation for a moving beta target.

Comment out the major "9" entry in the version matrix so only major 8 builds.
The workflows derive the matrix from this file, so no workflow changes are
needed. The commented-out 9 renovate annotations no longer match the custom
manager, so Renovate stops opening 9-bump PRs. Re-enable at 9.0 GA by
uncommenting the entry (and switching server/db to an RPM-based install).
PR #487 renamed the content images to openvox-server-8 / openvox-db-8 and
stopped publishing the old unsuffixed names, breaking consumers that pinned
ghcr.io/slauger/openvox-server.

Re-publish openvox-server and openvox-db (unsuffixed) as backward-compat
aliases of the current default major. Add an optional alias_image_name input to
the reusable container-build workflow: when set, the manifest job creates the
alias tags from the same per-arch sources (so the alias shares the primary
manifest digest) and cosign-signs + attests the alias name. ci.yaml (develop)
and release.yaml (version + :latest) pass the alias name for server and db,
gated on matrix.latest so only the default major produces it. The agent image
stays -8-only, and the chart/CRD defaults remain on -8.
Update the README image table and the Config reference note: OpenVox 9 builds
are paused until 9.0 GA (the -9 images are not currently published, though the
operator still supports them), and openvox-server / openvox-db (unsuffixed) are
published as aliases of the default -8 major for backward compatibility.
The OpenVox 8/9 image rename and the v9 build never shipped in a release, so
user-facing docs don't need to explain why v9 is paused. Trim the README and
Config reference to just describe the published images (unsuffixed name +
optional major suffix), and shorten the version-matrix comment to a one-line
note pointing at the re-enable issue #503.
…ixed-aliases

ci: disable OpenVox 9 builds until GA, republish unsuffixed server/db aliases
@github-actions github-actions Bot changed the title Release v0.10.0 (minor) Release v0.11.0 (minor) Aug 4, 2026
Drive config.code as a list (a PVC production environment plus an image
mountPath), populate the PVC as a single environment, and assert both the
environment and mountPath code volumes are mounted on the server pod.
slauger and others added 3 commits August 5, 2026 09:25
Cover spec.puppet.autosignCommand and externalNodesCommand together: with a
SigningPolicy and NodeClassifier also configured, assert puppet.conf points at
the custom commands and the built-in policy/ENC Secrets are neither rendered nor
mounted. Registered in the base e2e group.
Add a final step to the autosign-policy test: change the SigningPolicy, then
assert the CA deployment's autosign-policy-secret-hash annotation changes and
the pod rolls out, guarding the fix that makes policy changes apply without a
manual restart.
…errides

test(e2e): cover code list, puppet command overrides, and autosign rollout
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

renovate Bot and others added 11 commits August 5, 2026 20:38
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
PuppetDB has three independent commands: replace catalog, store report, and
replace facts. storeconfigs_backend=puppetdb and reports=puppetdb trigger the
first two, but neither switches the facts indirector terminus -- that is only
configured via routes.yaml. The operator rendered no routes.yaml, so the
replace facts command was never issued and PuppetDB's fact tables stayed empty
(breaking PQL/puppetdb_query on facts, inventory, fact age and dashboards).

Render routes.yaml (facts terminus -> puppetdb, cache json) into the Config
ConfigMap and mount it at $confdir/routes.yaml (Puppet's default route_file)
whenever PuppetDB is the active backend: a databaseRef or puppetdb.serverUrls is
set and storeBackend/reports use puppetdb. It is part of the ConfigMap that is
already hashed into the pod template, so a change rolls the Server pods
automatically. When PuppetDB is not the active backend, neither the key nor the
mount is emitted.
Extend the database-cnpg test to run a Puppet agent and then poll the PuppetDB
query API until the node's facts appear, proving the rendered routes.yaml routes
the facts terminus to PuppetDB. Also assert routes.yaml is rendered into the
Config ConfigMap and mounted into the server pod.

Fix the database image tag (latest -> IMAGE_TAG) so the stack pulls the build
under test instead of a non-existent openvox-db-<major>:latest.
Add a Fact Storage section to the Database concept explaining that catalogs,
reports and facts are wired independently and that the operator renders
routes.yaml to route the facts terminus to PuppetDB, and note routes.yaml in the
Config reference's created resources.
The autosign policy renderer wrote the policy and attribute names
unquoted (%s), while the values were already quoted (%q). A user able
to create SigningPolicy resources could set a csrAttributes[].name such
as "x\n    any: true" and inject an extra YAML key into the rendered
policy that the autosign binary interprets — effectively an allow-all
rule (privilege escalation).

- Render policy and attribute names with %q so crafted names can no
  longer break out of the scalar and inject structural YAML.
- Validate csrAttributes[].name in the SigningPolicy webhook: reject
  empty names and names that are not a known Puppet OID. The autosign
  binary only matches known OIDs, so unknown names were dead config
  anyway; this also blocks injection payloads (defense in depth).
- Enforce mutual exclusivity of value/valueFrom on CSRAttributeMatch via
  a CEL XValidation rule, mirroring HTTPHeader.

Closes #507
fix: prevent YAML injection via csrAttributes name in autosign policy
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…r tag to v9.8-1786323074 (#519)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
… v9.8-1786339177 (#520)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
@slauger
slauger merged commit c758bc1 into main Aug 10, 2026
97 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants