Skip to content

Commit 1e0d1ed

Browse files
authored
Merge pull request #10 from rhdh-parasol/issue-5-todo-publish-pipeline
ci: publish only todo to fork GHCR until the pipeline is proven
2 parents 4e6e669 + 9b327ec commit 1e0d1ed

10 files changed

Lines changed: 306 additions & 61 deletions

‎.github/workflows/create-release-branch.yaml‎

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,19 +120,11 @@ jobs:
120120
contents: write
121121

122122
export:
123-
uses: redhat-developer/rhdh-plugin-export-utils/.github/workflows/export-workspaces-as-dynamic.yaml@main
123+
uses: ./.github/workflows/publish-release-branch-workspace-plugins.yaml
124124
needs:
125125
- create
126-
127126
with:
128-
publish-container: true
129-
image-repository-prefix: ${{ format('ghcr.io/{0}', github.repository) }}
130127
overlay-branch: ${{ inputs.release-branch }}
131-
image-registry-user: ${{ github.actor }}
132-
133-
secrets:
134-
image-registry-password: ${{ secrets.GITHUB_TOKEN }}
135-
136128
permissions:
137129
contents: write
138130
attestations: write

‎.github/workflows/export-workspaces-as-dynamic.yaml‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,24 @@ concurrency:
117117
cancel-in-progress: true
118118

119119
jobs:
120+
refuse-unscoped-publish:
121+
name: Refuse unscoped container publish
122+
if: >
123+
github.event_name == 'workflow_dispatch' &&
124+
inputs.publish-container &&
125+
inputs.workspace-path == ''
126+
runs-on: ubuntu-latest
127+
steps:
128+
- name: Fail if publishing every workspace
129+
run: |
130+
echo "::error::Refusing to publish all workspaces from workflow_dispatch."
131+
echo "Set workspace-path (for example workspaces/todo), or use the allow-listed main publish workflow."
132+
exit 1
133+
120134
export:
135+
needs:
136+
- refuse-unscoped-publish
137+
if: always() && needs.refuse-unscoped-publish.result != 'failure'
121138
uses: redhat-developer/rhdh-plugin-export-utils/.github/workflows/export-workspaces-as-dynamic.yaml@main
122139
with:
123140
node-version: ${{ inputs.node-version }}
@@ -127,7 +144,7 @@ jobs:
127144
overlay-branch: ${{ inputs.overlay-branch }}
128145
workspace-path: ${{ inputs.workspace-path }}
129146
publish-container: ${{ inputs.publish-container }}
130-
image-repository-prefix: ${{ inputs.image-repository-prefix }}
147+
image-repository-prefix: ${{ inputs.image-repository-prefix != '' && inputs.image-repository-prefix || (inputs.publish-container && format('ghcr.io/{0}', github.repository) || '') }}
131148
image-registry-user: ${{ inputs.image-registry-user || github.actor }}
132149

133150
secrets:

‎.github/workflows/generate-catalog-index.yaml‎

Lines changed: 15 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ on:
1111
- 'default.packages.yaml'
1212
- 'rhdh-supported-packages.txt'
1313
- 'rhdh-community-packages.txt'
14+
- 'parasol-publish-workspaces.txt'
1415
- 'scripts/**'
1516
- 'versions.json'
1617
- '.github/workflows/generate-catalog-index.yaml'
@@ -32,8 +33,9 @@ concurrency:
3233
cancel-in-progress: true
3334

3435
env:
35-
COMMUNITY_REGISTRY: 'ghcr.io/redhat-developer/rhdh-plugin-export-overlays'
36-
COMMUNITY_CATALOG_INDEX: 'ghcr.io/redhat-developer/rhdh-plugin-export-overlays/plugin-catalog-index'
36+
# Fork GHCR (issue #5). Do not push to redhat-developer or quay.io/rhdh-community.
37+
COMMUNITY_REGISTRY: ghcr.io/${{ github.repository }}
38+
COMMUNITY_CATALOG_INDEX: ghcr.io/${{ github.repository }}/plugin-catalog-index
3739
SUPPORTED_CATALOG_INDEX: 'quay.io/rhdh-community/plugin-catalog-index'
3840
YQ_VERSION: '4.53.2'
3941

@@ -130,54 +132,23 @@ jobs:
130132
echo "Backstage version: $BS_VERSION"
131133
echo "RHDH version: $RHDH_VERSION (from upstream RHDH $RHDH_BRANCH package.json: $RHDH_FULL_VERSION)"
132134
133-
- name: Generate supported catalog
135+
- name: Skip supported catalog (fork community slice)
134136
id: gen-supported
135-
env:
136-
RHDH_VERSION: ${{ steps.versions.outputs.rhdh-version }}
137137
run: |
138-
RHDH_VERSION_ARG=""
139-
if [[ -n "$RHDH_VERSION" ]]; then
140-
RHDH_VERSION_ARG="--rhdh-version $RHDH_VERSION"
141-
fi
142-
143-
# shellcheck disable=SC2086
144-
if scripts/update-index.sh \
145-
--overlays-dir . \
146-
--registry "$COMMUNITY_REGISTRY" \
147-
--output-dir catalog-index/supported \
148-
--plugin-builds-dir plugin_builds/supported \
149-
--packages-file default.packages.yaml \
150-
--packages-file rhdh-supported-packages.txt \
151-
--report-file catalog-index/supported/build-report.json \
152-
$RHDH_VERSION_ARG; then
153-
echo "ok=true" >> "$GITHUB_OUTPUT"
154-
else
155-
echo "::warning::Supported catalog generation failed"
156-
echo "ok=false" >> "$GITHUB_OUTPUT"
157-
echo "clean=false" >> "$GITHUB_OUTPUT"
158-
fi
159-
160-
# Check if the catalog is clean (no fallbacks or missing plugins)
161-
REPORT="catalog-index/supported/build-report.json"
162-
if [[ -f "$REPORT" ]]; then
163-
FAILED=$(jq '.summary.failed // 0' "$REPORT" 2>/dev/null || echo 0)
164-
FALLBACKS=$(jq '[.plugins[] | select(.stages["image-metadata-fetch"].fallback == true)] | length' "$REPORT" 2>/dev/null || echo 0)
165-
if [[ "$FAILED" -eq 0 && "$FALLBACKS" -eq 0 ]]; then
166-
echo "clean=true" >> "$GITHUB_OUTPUT"
167-
else
168-
echo "clean=false" >> "$GITHUB_OUTPUT"
169-
fi
170-
fi
138+
echo "ok=false" >> "$GITHUB_OUTPUT"
139+
echo "clean=false" >> "$GITHUB_OUTPUT"
140+
echo "Skipping supported/Quay catalog on this fork until QUAY_TOKEN is configured (issue #8)."
171141
172142
- name: Generate community catalog
173143
id: gen-community
174144
run: |
145+
python3 scripts/parasol-allow-list.py --packages-file /tmp/parasol-packages.txt
175146
if scripts/update-index.sh \
176147
--overlays-dir . \
177148
--registry "$COMMUNITY_REGISTRY" \
178149
--output-dir catalog-index/community \
179150
--plugin-builds-dir plugin_builds/community \
180-
--packages-file rhdh-community-packages.txt \
151+
--packages-file /tmp/parasol-packages.txt \
181152
--report-file catalog-index/community/build-report.json; then
182153
echo "ok=true" >> "$GITHUB_OUTPUT"
183154
else
@@ -268,10 +239,13 @@ jobs:
268239
SUPPORTED_CLEAN: ${{ steps.gen-supported.outputs.clean }}
269240
COMMUNITY_CLEAN: ${{ steps.gen-community.outputs.clean }}
270241
run: |
271-
if [[ "${SUPPORTED_OK}" != "true" || "${COMMUNITY_OK}" != "true" ]]; then
272-
echo "::error::Catalog generation failed (supported=$SUPPORTED_OK, community=$COMMUNITY_OK)"
242+
if [[ "${COMMUNITY_OK}" != "true" ]]; then
243+
echo "::error::Community catalog generation failed (community=$COMMUNITY_OK)"
273244
exit 1
274245
fi
246+
if [[ "${SUPPORTED_OK}" != "true" ]]; then
247+
echo "::notice::Supported/Quay catalog skipped on this fork (issue #8)"
248+
fi
275249
276250
# Surface fallbacks and missing plugins as warnings
277251
HAS_ISSUES=false

‎.github/workflows/publish-release-branch-workspace-plugins.yaml‎

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,43 @@
1-
name: Publish RHDH Release Dynamic Plugin Images
1+
name: Publish RHDH Release Dynamic Plugin Images
22
on:
33
workflow_call:
4+
inputs:
5+
workspace-path:
6+
description: >
7+
Single overlay workspace (e.g. workspaces/todo). When set, the allow-list
8+
file is ignored. When empty, workspaces are read from
9+
parasol-publish-workspaces.txt (empty file = publish nothing).
10+
type: string
11+
required: false
12+
default: ''
13+
overlay-branch:
14+
description: Overlay git ref to export. Defaults to the caller ref.
15+
type: string
16+
required: false
17+
default: ''
418

519
concurrency:
6-
group: ${{ github.workflow_ref }}-${{ github.ref }}
20+
group: ${{ github.workflow_ref }}-${{ github.ref }}-${{ inputs.overlay-branch }}-${{ inputs.workspace-path }}
721
cancel-in-progress: true
822

923
jobs:
24+
resolve-workspaces:
25+
runs-on: ubuntu-latest
26+
name: Resolve workspaces
27+
outputs:
28+
workspaces: ${{ steps.list.outputs.workspaces }}
29+
steps:
30+
- name: Checkout overlay
31+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
32+
with:
33+
ref: ${{ inputs.overlay-branch || github.ref }}
34+
35+
- name: Read publish allow-list
36+
id: list
37+
env:
38+
WORKSPACE_PATH: ${{ inputs.workspace-path }}
39+
run: python3 scripts/parasol-allow-list.py --workspaces-json
40+
1041
prepare:
1142
runs-on: ubuntu-latest
1243
name: Prepare
@@ -18,7 +49,7 @@ jobs:
1849
id: get-last-published-commit
1950
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
2051
env:
21-
INPUT_RELEASE_BRANCH: ${{ github.ref_name }}
52+
INPUT_RELEASE_BRANCH: ${{ github.ref_name }}
2253
with:
2354
script: |
2455
core.info(`Getting latest commit on branch ${core.getInput('release_branch')}`);
@@ -41,7 +72,7 @@ jobs:
4172
});
4273
4374
for (const run of runs.data.workflow_runs) {
44-
if (context.payload.commits.some(c => c.id === run.head_sha)) {
75+
if (context.payload.commits && context.payload.commits.some(c => c.id === run.head_sha)) {
4576
core.info(`Skipping run ${run.id} for commit ${run.head_sha}, it's part of the push`);
4677
continue;
4778
}
@@ -53,7 +84,9 @@ jobs:
5384
filter: 'latest',
5485
});
5586
56-
const exportJobs = jobs.data.jobs.filter(j => j.name.startsWith('export /'));
87+
const exportJobs = jobs.data.jobs.filter(j =>
88+
j.name.startsWith('export') && j.conclusion !== 'skipped'
89+
);
5790
if (exportJobs.length > 0 && exportJobs.every(j => j.conclusion === 'success')) {
5891
core.info(`Last published commit to compare with: ${run.head_sha}`);
5992
core.setOutput('last-published-commit', run.head_sha);
@@ -64,14 +97,22 @@ jobs:
6497
6598
core.info('Last published commit not found');
6699
core.setOutput('last-published-commit', '');
67-
100+
68101
export:
69102
uses: redhat-developer/rhdh-plugin-export-utils/.github/workflows/export-workspaces-as-dynamic.yaml@main
70103
needs:
104+
- resolve-workspaces
71105
- prepare
106+
if: needs.resolve-workspaces.outputs.workspaces != '[]'
107+
strategy:
108+
fail-fast: false
109+
matrix:
110+
workspace: ${{ fromJSON(needs.resolve-workspaces.outputs.workspaces) }}
72111

73112
with:
74113
publish-container: true
114+
workspace-path: ${{ matrix.workspace }}
115+
overlay-branch: ${{ inputs.overlay-branch }}
75116
image-repository-prefix: ${{ format('ghcr.io/{0}', github.repository) }}
76117
last-publish-commit: ${{ needs.prepare.outputs.last-published-commit }}
77118
# use empty prefix so that we will prepend bs_1.yy.z__ instead of next__
@@ -80,7 +121,7 @@ jobs:
80121

81122
secrets:
82123
image-registry-password: ${{ secrets.GITHUB_TOKEN }}
83-
124+
84125
permissions:
85126
contents: write
86127
attestations: write

‎.github/workflows/publish-workspace-plugins.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77

88
jobs:
99
export:
10-
uses: redhat-developer/rhdh-plugin-export-overlays/.github/workflows/publish-release-branch-workspace-plugins.yaml@main
10+
uses: ./.github/workflows/publish-release-branch-workspace-plugins.yaml
1111
permissions:
1212
contents: write
1313
attestations: write
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
name: Set GHCR packages public
2+
3+
# Experiment: GitHub's documented REST API has no "set visibility" operation
4+
# (org package routes are GET/DELETE only). This job tries the unofficial
5+
# PATCH that some projects use, with GITHUB_TOKEN + packages:write.
6+
on:
7+
# Push runs this on the PR branch (workflow_dispatch only exists after merge to main).
8+
push:
9+
paths:
10+
- ".github/workflows/set-ghcr-packages-public.yaml"
11+
workflow_dispatch:
12+
inputs:
13+
package_names:
14+
description: >-
15+
Newline-separated container package names under this org
16+
(include the repo prefix).
17+
required: false
18+
default: |
19+
rhdh-plugin-export-overlays/backstage-community-plugin-todo
20+
rhdh-plugin-export-overlays/backstage-community-plugin-todo-backend
21+
22+
permissions:
23+
contents: read
24+
packages: write
25+
26+
jobs:
27+
set-public:
28+
runs-on: ubuntu-latest
29+
steps:
30+
- name: Try PATCH visibility on each package
31+
env:
32+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33+
GH_HOST: github.com
34+
ORG: ${{ github.repository_owner }}
35+
PACKAGE_NAMES: ${{ inputs.package_names }}
36+
run: |
37+
set -u
38+
python3 - <<'PY'
39+
import json, os, subprocess, sys, urllib.parse
40+
41+
org = os.environ["ORG"]
42+
raw = os.environ.get("PACKAGE_NAMES", "")
43+
names = []
44+
for line in raw.splitlines():
45+
line = line.split("#", 1)[0].strip()
46+
if line:
47+
names.append(line)
48+
49+
if not names:
50+
names = [
51+
"rhdh-plugin-export-overlays/backstage-community-plugin-todo",
52+
"rhdh-plugin-export-overlays/backstage-community-plugin-todo-backend",
53+
]
54+
55+
def gh_api(method, path, *extra):
56+
cmd = ["gh", "api", "--method", method, "-i", path, *extra]
57+
print(f"\n===== {method} {path} {extra} =====", flush=True)
58+
proc = subprocess.run(cmd, capture_output=True, text=True)
59+
out = (proc.stdout or "") + (proc.stderr or "")
60+
print(out[:4000], flush=True)
61+
return proc.returncode, out
62+
63+
any_ok = False
64+
for name in names:
65+
encoded = urllib.parse.quote(name, safe="")
66+
base = f"orgs/{org}/packages/container/{encoded}"
67+
print(f"\n########## {name} ##########", flush=True)
68+
gh_api("GET", base)
69+
for method, path, extra in [
70+
("PATCH", base, ["-f", "visibility=public"]),
71+
("PATCH", f"{base}/visibility", ["-f", "visibility=public"]),
72+
("POST", f"{base}/visibility", ["-f", "visibility=public"]),
73+
]:
74+
code, out = gh_api(method, path, *extra)
75+
if code == 0 and ("\"visibility\": \"public\"" in out or "204" in out[:80]):
76+
any_ok = True
77+
preview = [
78+
"-H",
79+
"Accept: application/vnd.github.package-deletes-preview+json",
80+
"-f",
81+
"visibility=public",
82+
]
83+
gh_api("PATCH", base, *preview)
84+
85+
print("\n########## GET after attempts ##########", flush=True)
86+
failed = False
87+
for name in names:
88+
encoded = urllib.parse.quote(name, safe="")
89+
path = f"orgs/{org}/packages/container/{encoded}"
90+
proc = subprocess.run(
91+
["gh", "api", path, "--jq", ".visibility"],
92+
capture_output=True,
93+
text=True,
94+
)
95+
vis = (proc.stdout or proc.stderr or "").strip()
96+
print(f"{name}: visibility={vis!r} exit={proc.returncode}", flush=True)
97+
if vis != "public":
98+
failed = True
99+
100+
if failed:
101+
print(
102+
"\nCONCLUSION: GITHUB_TOKEN could not set packages public.",
103+
file=sys.stderr,
104+
)
105+
sys.exit(1)
106+
print("\nCONCLUSION: packages report visibility=public")
107+
PY

‎parasol-publish-workspaces.txt‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# One workspace directory name per line (under workspaces/).
2+
# To publish another: add the name here, and point that workspace's
3+
# metadata spec.dynamicArtifact at ghcr.io/rhdh-parasol/rhdh-plugin-export-overlays/...
4+
todo

0 commit comments

Comments
 (0)