publish-helm-chart.yml composed the upload target as "${REGISTRY_CHARTS_URL%/}/api/charts", so op://GitHub-Actions/jlab-registry-access/charts-url had to hold the full registry URL including the owner and the package type.
It now holds only the base up to /api/packages, and the owner comes from ${{ github.repository_owner }}:
No caller changes: the 26 thin publish-<chart>.yml are untouched, and no value pointing at the registry — not even the owner path segment — enters the repository.
Measured, not assumed: is github.repository_owner populated on this forge?
Yes. Observed value: jlab-cluster, 12 characters.
How: a temporary step at the head of detect-changed-charts in validate-charts.yml printed the context value on the pull_request run of this PR. Read off run 282:
The step has since been removed again (second commit on this branch — validate-charts.yml is now byte-identical to main), and the measured value is recorded in the comment above the upload step so the fact outlives the step that produced it.
Guards
Guard
Rejects
charts-url must not end in /api/charts
the old, full URL; the error names /api/packages as the new shape
charts-url must not contain a /helm segment
the old URL's package-type segment
charts-url must end in /api/packages
everything else, including a base that already carries the owner (…/api/packages/<owner>) or no path at all
derived owner non-empty (:?)
an empty github.repository_owner, which would build <base>//helm/api/charts
derived owner matches [A-Za-z0-9._-] only
a /, a space or a ? in the owner, which would build a different URL entirely
Each of the three charts-url errors says what to change in the vault item, because the only other signal is a 404 against a URL 1Password has masked.
Verified locally against 12 inputs (good base with and without a trailing slash, both owners of the instance, the old full URL in three stages of truncation, an owner-bearing base, a bare host, an empty owner, an owner with / and with a space) — every case lands in the intended branch.
What deliberately stayed
Everything the upload step already had, each paid for once: the per-field :? guards, the whitespace check on the credentials (curl --config truncates an unquoted value at the first space), the host masking via ::add-mask::, the built file name <chart>-<version>.tgz instead of a glob, and --fail-with-body. The long comment block above the step keeps explaining all of them; it gained a paragraph on the composition and lost nothing.
Migration — hard cut, and in this order
Vault item and workflow have to match. Both mismatches fail loudly with a 404; neither publishes to a wrong place.
The maintainer shortens op://GitHub-Actions/jlab-registry-access/charts-url to the base, i.e. everything up to and including /api/packages.
Then merge.
Why this PR cannot prove itself, and what does
Merging triggers no publish — the PR touches no chart directory, so the new path stays unproven until the next chart change.
The end-to-end check is one manual workflow_dispatch of publish-helm-chart.yml for any chart. The registry accepts a re-upload of an already published version (HTTP 201) and replaces the artifact (#160), so it is a safe test of the whole path.
Only the maintainer can trigger it — the bot account has no write permission on the repository.
Docs
README, the publish-helm-chart.yml bullet: "the workflow appends /api/charts to charts-url" is gone. "No registry address ever appears in this repository" stays, and now carries the reason — the owner is derived, not stored.
Wiki, CI-CD → Publishing: new section "The target URL is composed, not stored" with the same correction, the guard table, the order of the cut and the manual-dispatch proof. Already pushed (d7ce205).
Scope
Two files: publish-helm-chart.yml and README.md. No chart directory — no version bump, no install-test, no publish from this PR.
Fixes #63
`publish-helm-chart.yml` composed the upload target as `"${REGISTRY_CHARTS_URL%/}/api/charts"`, so `op://GitHub-Actions/jlab-registry-access/charts-url` had to hold the full registry URL including the owner and the package type.
It now holds only the **base up to `/api/packages`**, and the owner comes from `${{ github.repository_owner }}`:
```
op://GitHub-Actions/jlab-registry-access/charts-url = https://<host>/api/packages
target = <base>/<owner>/helm/api/charts
```
No caller changes: the 26 thin `publish-<chart>.yml` are untouched, and no value pointing at the registry — not even the owner path segment — enters the repository.
## Measured, not assumed: is `github.repository_owner` populated on this forge?
**Yes.** Observed value: **`jlab-cluster`**, 12 characters.
How: a temporary step at the head of `detect-changed-charts` in `validate-charts.yml` printed the context value on the `pull_request` run of this PR. Read off **run 282**:
```
github.repository_owner = [jlab-cluster]
github.repository = [jlab-cluster/helm-charts]
length = 12
```
The step has since been **removed again** (second commit on this branch — `validate-charts.yml` is now byte-identical to `main`), and the measured value is recorded in the comment above the upload step so the fact outlives the step that produced it.
## Guards
| Guard | Rejects |
| --- | --- |
| `charts-url` must not end in `/api/charts` | the old, full URL; the error names `/api/packages` as the new shape |
| `charts-url` must not contain a `/helm` segment | the old URL's package-type segment |
| `charts-url` must end in `/api/packages` | everything else, including a base that already carries the owner (`…/api/packages/<owner>`) or no path at all |
| derived owner non-empty (`:?`) | an empty `github.repository_owner`, which would build `<base>//helm/api/charts` |
| derived owner matches `[A-Za-z0-9._-]` only | a `/`, a space or a `?` in the owner, which would build a different URL entirely |
Each of the three `charts-url` errors says what to change in the vault item, because the only other signal is a 404 against a URL 1Password has masked.
Verified locally against 12 inputs (good base with and without a trailing slash, both owners of the instance, the old full URL in three stages of truncation, an owner-bearing base, a bare host, an empty owner, an owner with `/` and with a space) — every case lands in the intended branch.
## What deliberately stayed
Everything the upload step already had, each paid for once: the per-field `:?` guards, the whitespace check on the credentials (`curl --config` truncates an unquoted value at the first space), the host masking via `::add-mask::`, the **built** file name `<chart>-<version>.tgz` instead of a glob, and `--fail-with-body`. The long comment block above the step keeps explaining all of them; it gained a paragraph on the composition and lost nothing.
## Migration — hard cut, and in this order
Vault item and workflow have to match. Both mismatches fail loudly with a 404; neither publishes to a wrong place.
1. **The maintainer shortens `op://GitHub-Actions/jlab-registry-access/charts-url` to the base**, i.e. everything up to and including `/api/packages`.
2. Then merge.
## Why this PR cannot prove itself, and what does
**Merging triggers no publish** — the PR touches no chart directory, so the new path stays unproven until the next chart change.
The end-to-end check is one manual **`workflow_dispatch` of `publish-helm-chart.yml`** for any chart. The registry accepts a re-upload of an already published version (HTTP 201) and replaces the artifact (#160), so it is a safe test of the whole path.
**Only the maintainer can trigger it** — the bot account has no write permission on the repository.
## Docs
- **README**, the `publish-helm-chart.yml` bullet: "the workflow appends `/api/charts` to `charts-url`" is gone. "No registry address ever appears in this repository" stays, and now carries the reason — the owner is derived, not stored.
- **Wiki, `CI-CD` → Publishing**: new section "The target URL is composed, not stored" with the same correction, the guard table, the order of the cut and the manual-dispatch proof. Already pushed (`d7ce205`).
## Scope
Two files: `publish-helm-chart.yml` and `README.md`. **No chart directory** — no version bump, no install-test, no publish from this PR.
charts-url in op://GitHub-Actions/jlab-registry-access held the full
registry URL and publish-helm-chart.yml appended /api/charts to it. It
now holds only the base up to /api/packages, and the owner segment comes
from github.repository_owner, so the target is composed as
<base>/<owner>/helm/api/charts.
Nothing in this repository points at the registry any more, not even a
path segment, and the second owner on the same instance needs no second
setting. The 26 thin publish-<chart>.yml callers are unchanged.
Two guards keep the switch from the old shape loud rather than a 404
against a masked URL: charts-url is rejected unless it ends in
/api/packages, naming /helm, /api/charts or an included owner
explicitly; and the derived owner is rejected when empty or when it is
not a usable URL path segment. Everything the upload step already had
is untouched - the per-field :? guards, the whitespace check on the
credentials, the host masking, the built file name, --fail-with-body.
The probe step in validate-charts.yml is temporary and measures whether
this forge populates github.repository_owner at all; it is removed again
once the value has been read off the run.
github.repository_owner is populated on this Gitea instance: measured as
"jlab-cluster" (12 characters) in run 282 of validate-charts.yml. The
value is now in the comment above the upload step, so the fact survives
without the step that produced it.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Fixes #63
publish-helm-chart.ymlcomposed the upload target as"${REGISTRY_CHARTS_URL%/}/api/charts", soop://GitHub-Actions/jlab-registry-access/charts-urlhad to hold the full registry URL including the owner and the package type.It now holds only the base up to
/api/packages, and the owner comes from${{ github.repository_owner }}:No caller changes: the 26 thin
publish-<chart>.ymlare untouched, and no value pointing at the registry — not even the owner path segment — enters the repository.Measured, not assumed: is
github.repository_ownerpopulated on this forge?Yes. Observed value:
jlab-cluster, 12 characters.How: a temporary step at the head of
detect-changed-chartsinvalidate-charts.ymlprinted the context value on thepull_requestrun of this PR. Read off run 282:The step has since been removed again (second commit on this branch —
validate-charts.ymlis now byte-identical tomain), and the measured value is recorded in the comment above the upload step so the fact outlives the step that produced it.Guards
charts-urlmust not end in/api/charts/api/packagesas the new shapecharts-urlmust not contain a/helmsegmentcharts-urlmust end in/api/packages…/api/packages/<owner>) or no path at all:?)github.repository_owner, which would build<base>//helm/api/charts[A-Za-z0-9._-]only/, a space or a?in the owner, which would build a different URL entirelyEach of the three
charts-urlerrors says what to change in the vault item, because the only other signal is a 404 against a URL 1Password has masked.Verified locally against 12 inputs (good base with and without a trailing slash, both owners of the instance, the old full URL in three stages of truncation, an owner-bearing base, a bare host, an empty owner, an owner with
/and with a space) — every case lands in the intended branch.What deliberately stayed
Everything the upload step already had, each paid for once: the per-field
:?guards, the whitespace check on the credentials (curl --configtruncates an unquoted value at the first space), the host masking via::add-mask::, the built file name<chart>-<version>.tgzinstead of a glob, and--fail-with-body. The long comment block above the step keeps explaining all of them; it gained a paragraph on the composition and lost nothing.Migration — hard cut, and in this order
Vault item and workflow have to match. Both mismatches fail loudly with a 404; neither publishes to a wrong place.
op://GitHub-Actions/jlab-registry-access/charts-urlto the base, i.e. everything up to and including/api/packages.Why this PR cannot prove itself, and what does
Merging triggers no publish — the PR touches no chart directory, so the new path stays unproven until the next chart change.
The end-to-end check is one manual
workflow_dispatchofpublish-helm-chart.ymlfor any chart. The registry accepts a re-upload of an already published version (HTTP 201) and replaces the artifact (#160), so it is a safe test of the whole path.Only the maintainer can trigger it — the bot account has no write permission on the repository.
Docs
publish-helm-chart.ymlbullet: "the workflow appends/api/chartstocharts-url" is gone. "No registry address ever appears in this repository" stays, and now carries the reason — the owner is derived, not stored.CI-CD→ Publishing: new section "The target URL is composed, not stored" with the same correction, the guard table, the order of the cut and the manual-dispatch proof. Already pushed (d7ce205).Scope
Two files:
publish-helm-chart.ymlandREADME.md. No chart directory — no version bump, no install-test, no publish from this PR.