chore: add reusable workflow for publishing OCM component versions#1901
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a GitHub Actions workflow to publish OCM component versions and accompanying Node.js utilities plus tests that parse/patch component-constructor YAML, build package URLs, and write GitHub Actions summaries. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant GH Actions as "GitHub Actions (workflow)"
participant ArtifactSvc as "Artifact storage (actions/artifact)"
participant Runner as "Actions runner"
participant GHCR as "GitHub Container Registry"
participant Docker as "Docker (runs CLI image)"
participant OCM_CLI as "OCM CLI inside container"
participant Scripts as "component-constructor.js"
rect rgba(100,150,240,0.5)
GH Actions->>ArtifactSvc: download constructor artifact
GH Actions->>ArtifactSvc: optionally download build artifact
end
rect rgba(120,200,80,0.5)
GH Actions->>Runner: validate files (constructor/component-constructor.yaml, resources/bin)
Runner->>Scripts: parse & extract name/version
Scripts->>Runner: return name, version, package URL
end
rect rgba(240,140,60,0.5)
GH Actions->>GHCR: docker/login-action (authenticate using GITHUB_TOKEN)
GH Actions->>Docker: run CLI image with mounted constructor
Docker->>OCM_CLI: ocm add component-version --repository ...
OCM_CLI-->>Docker: publish result
Docker-->>GH Actions: exit status
end
GH Actions->>Runner: append Markdown summary with package link
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/publish-ocm-component-version.yml:
- Around line 117-123: The workflow builds COMPONENT_REF using values parsed
into COMPONENT_NAME and COMPONENT_VERSION from CONSTRUCTOR_FILE but doesn't
guard against empty parses; add a validation after extracting COMPONENT_NAME and
COMPONENT_VERSION (the variables in the diff) that checks both are non-empty,
and if either is empty echo a clear error including CONSTRUCTOR_FILE and the
missing field(s) then exit 1 so the job fails early instead of composing an
invalid COMPONENT_REF/PKG_PATH/PACKAGE_URL.
- Around line 56-58: The workflow currently hardcodes a check for
"${GITHUB_WORKSPACE}/constructor/resources/bin" when inputs.build_artifact_name
is set, which rejects valid artifacts that place resources elsewhere; change the
verification in the conditional that checks inputs.build_artifact_name to
validate the generic constructor resources presence (e.g., test that
"${GITHUB_WORKSPACE}/constructor/resources" exists and is non-empty or that at
least one entry matches "${GITHUB_WORKSPACE}/constructor/resources/*") instead
of specifically testing for "constructor/resources/bin" so arbitrary file-based
resources are accepted.
- Around line 14-18: The workflow currently assumes GHCR in
inputs.ocm_repository and hardcodes GHCR auth and a GitHub package URL shape;
add a fail-fast guard at the start of the workflow to validate
inputs.ocm_repository is the GHCR host (e.g., startsWith "ghcr.io" or equals the
default "ghcr.io/open-component-model") and explicitly exit with an error if it
is not GHCR to avoid running GHCR-specific auth/publish steps, and also replace
any hardcoded GitHub package URL usage with a conditional or template that uses
inputs.ocm_repository when building URLs (or skip that step when non-GHCR) so
the GHCR-only steps (the GHCR auth step and the publish/summary URL generation)
do not run for non-GHCR registries.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 7e691571-367e-4bcd-be33-a1cd7d968a54
📒 Files selected for processing (1)
.github/workflows/publish-ocm-component-version.yml
On-behalf-of: Gerald Morrison (SAP) <gerald.morrison@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
On-behalf-of: Gerald Morrison (SAP) <gerald.morrison@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
ae5e3ce to
3c3e840
Compare
frewilhelm
left a comment
There was a problem hiding this comment.
As this is a reusable workflow we might make it a bit more generic regarding constructor/artifact-paths. There could be other users who want to use this as well.
But I would be fine using this in the first iteration.
On-behalf-of: Gerald Morrison (SAP) <gerald.morrison@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
On-behalf-of: Gerald Morrison (SAP) <gerald.morrison@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
On-behalf-of: Gerald Morrison (SAP) <gerald.morrison@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
.github/workflows/publish-ocm-component-version.yml (2)
140-141: Add a brief comment explaining the URL encoding.The shell parameter expansion
${COMPONENT_NAME//\//%2F}URL-encodes forward slashes. A brief comment would help readers unfamiliar with this syntax.📝 Proposed comment
+ # URL-encode slashes in component name: ${var//pattern/replacement} replaces all '/' with '%2F' PKG_PATH="component-descriptors%2F${COMPONENT_NAME//\//%2F}" PACKAGE_URL="https://github.com/${GITHUB_REPOSITORY}/pkgs/container/${PKG_PATH}"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/publish-ocm-component-version.yml around lines 140 - 141, Add a brief inline comment above the PKG_PATH/PACKAGE_URL assignments explaining that the shell parameter expansion ${COMPONENT_NAME//\//%2F} replaces all forward slashes with "%2F" to URL-encode the component name for the GitHub Packages path; reference the PKG_PATH and PACKAGE_URL variables and place the comment directly next to the PKG_PATH line so readers understand why the expansion is used.
129-130: Clarify expected constructor format or adjust parsing.The
sedpatterns^name:and^version:assume these fields appear at the start of lines, but typical component constructors nest these under acomponents:list:components: - name: github.com/acme.org/myapp version: 1.0.0If the workflow expects a different single-component format (e.g., flat YAML without the
components:wrapper), please add a comment documenting the expected structure to aid future maintainers.♻️ Option A: Add a comment documenting expected format
+ # Expected constructor format (single component, flat structure): + # name: <component-name> + # version: <component-version> + # ... COMPONENT_NAME=$(sed -n 's/^name:[[:space:]]*//p' "${CONSTRUCTOR_FILE}" | head -n 1) COMPONENT_VERSION=$(sed -n 's/^version:[[:space:]]*//p' "${CONSTRUCTOR_FILE}" | head -n 1)♻️ Option B: Adjust regex to handle nested YAML format
- COMPONENT_NAME=$(sed -n 's/^name:[[:space:]]*//p' "${CONSTRUCTOR_FILE}" | head -n 1) - COMPONENT_VERSION=$(sed -n 's/^version:[[:space:]]*//p' "${CONSTRUCTOR_FILE}" | head -n 1) + # Handle both flat and nested component constructor formats + COMPONENT_NAME=$(sed -n 's/^-\{0,1\}[[:space:]]*name:[[:space:]]*//p' "${CONSTRUCTOR_FILE}" | head -n 1) + COMPONENT_VERSION=$(sed -n 's/^[[:space:]]*version:[[:space:]]*//p' "${CONSTRUCTOR_FILE}" | head -n 1)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/publish-ocm-component-version.yml around lines 129 - 130, The sed extraction for COMPONENT_NAME and COMPONENT_VERSION assumes fields start at column 0; either document the expected flat constructor YAML format near the COMPONENT_NAME/COMPONENT_VERSION assignment (mentioning CONSTRUCTOR_FILE must contain top-level name: and version: keys) or change the sed patterns used to strip leading whitespace and an optional list dash so they match nested entries like "- name:" and "version:" indented under components; update the two sed invocations that produce COMPONENT_NAME and COMPONENT_VERSION to use the more permissive pattern that accepts leading spaces and an optional leading '-' before the key.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/publish-ocm-component-version.yml:
- Around line 79-88: The heredoc being written to "${HOME}/.ocmconfig" is
indented, so those leading spaces will be written into the file and produce
invalid YAML; fix this by left-aligning the heredoc body (remove the leading
spaces before "type:", "configurations:", etc.) and use a quoted delimiter to
prevent expansion (change the opener to <<'EOF') so the content is written
exactly as intended without variable expansion; alternatively, if you prefer
indented source, switch to a <<-EOF style and ensure you use tabs (not spaces)
for indentation so the shell strips them.
---
Nitpick comments:
In @.github/workflows/publish-ocm-component-version.yml:
- Around line 140-141: Add a brief inline comment above the PKG_PATH/PACKAGE_URL
assignments explaining that the shell parameter expansion
${COMPONENT_NAME//\//%2F} replaces all forward slashes with "%2F" to URL-encode
the component name for the GitHub Packages path; reference the PKG_PATH and
PACKAGE_URL variables and place the comment directly next to the PKG_PATH line
so readers understand why the expansion is used.
- Around line 129-130: The sed extraction for COMPONENT_NAME and
COMPONENT_VERSION assumes fields start at column 0; either document the expected
flat constructor YAML format near the COMPONENT_NAME/COMPONENT_VERSION
assignment (mentioning CONSTRUCTOR_FILE must contain top-level name: and
version: keys) or change the sed patterns used to strip leading whitespace and
an optional list dash so they match nested entries like "- name:" and "version:"
indented under components; update the two sed invocations that produce
COMPONENT_NAME and COMPONENT_VERSION to use the more permissive pattern that
accepts leading spaces and an optional leading '-' before the key.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 06ad6512-1eda-46f1-ac4a-fd318ab7fc07
📒 Files selected for processing (1)
.github/workflows/publish-ocm-component-version.yml
On-behalf-of: Gerald Morrison (SAP) <gerald.morrison@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
On-behalf-of: Gerald Morrison (SAP) <gerald.morrison@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
.github/workflows/publish-ocm-component-version.yml (1)
34-37: Add explicitcontents: readpermission for checkout.The job uses
actions/checkouton Line [121]. Declaringcontents: readexplicitly avoids permission brittleness when token defaults are restricted.💡 Proposed fix
permissions: actions: read + contents: read packages: write # Required for pushing to GHCR via docker login + OCM CLIAlso applies to: 121-126
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/publish-ocm-component-version.yml around lines 34 - 37, The workflow's job permissions block currently sets actions: read and packages: write but omits contents: read, which can break actions/checkout; update the job-level permissions to include contents: read so the actions/checkout step can access repository contents (modify the permissions block that contains actions: read and packages: write to add contents: read) and mirror the same change for the other similar permissions block used around the actions/checkout step..github/scripts/component-constructor.test.js (1)
172-186: Usetry/finallyaround temp-file blocks to guarantee cleanup.If an assertion fails before cleanup, temp artifacts remain behind.
💡 Proposed fix pattern
{ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "ocm-test-")); const tmpFile = path.join(tmpDir, "component-constructor.yaml"); - - const testDoc = { name: "ocm.software/test", version: "0.1.0", provider: { name: "test" } }; - fs.writeFileSync(tmpFile, yaml.dump(testDoc), "utf8"); - - const parsed = parseConstructorFile(tmpFile); - assert.strictEqual(parsed.name, "ocm.software/test", "Should parse name from YAML file"); - assert.strictEqual(parsed.version, "0.1.0", "Should parse version from YAML file"); - - // Cleanup - fs.unlinkSync(tmpFile); - fs.rmdirSync(tmpDir); + try { + const testDoc = { name: "ocm.software/test", version: "0.1.0", provider: { name: "test" } }; + fs.writeFileSync(tmpFile, yaml.dump(testDoc), "utf8"); + + const parsed = parseConstructorFile(tmpFile); + assert.strictEqual(parsed.name, "ocm.software/test", "Should parse name from YAML file"); + assert.strictEqual(parsed.version, "0.1.0", "Should parse version from YAML file"); + } finally { + if (fs.existsSync(tmpFile)) fs.unlinkSync(tmpFile); + if (fs.existsSync(tmpDir)) fs.rmdirSync(tmpDir); + } }Apply the same pattern to the empty-file block.
Also applies to: 196-209
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/scripts/component-constructor.test.js around lines 172 - 186, The test creates temp dirs/files and cleans them up manually but can leak artifacts if assertions fail; wrap the temp-file test blocks that call parseConstructorFile (the block creating tmpDir/tmpFile and the similar "empty-file" block) in a try/finally where the finally always calls fs.unlinkSync(tmpFile) and fs.rmdirSync(tmpDir) (guarding existence checks as needed) so cleanup runs even on assertion failures; update both the block using parseConstructorFile and the other empty-file test to use this try/finally pattern..github/scripts/component-constructor.js (1)
154-156: Harden failure reporting for non-Errorthrows.
error.messagecan be empty/undefined if a non-Errorvalue is thrown.💡 Proposed fix
} catch (error) { - core.setFailed(error.message); + const message = error instanceof Error ? error.message : String(error); + core.setFailed(message); } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/scripts/component-constructor.js around lines 154 - 156, The catch block currently calls core.setFailed(error.message) which can be empty for non-Error throws; update the catch handling in the catch (error) block to normalize the thrown value before passing to core.setFailed (e.g., if error is an Error use error.message or error.stack, otherwise convert to a string/JSON via String(error) or JSON.stringify(error) and include it in the message) so core.setFailed always receives a meaningful string; ensure you reference the existing catch (error) and core.setFailed invocation when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/scripts/component-constructor.js:
- Around line 75-82: The CLI-path branch currently assumes resource.input.path
is a valid string and calls .split("/"), which throws if missing; in the
resource-name === "cli" && resource.input?.type === "file" block validate that
resource.input.path exists and is a non-empty string before splitting (e.g., if
(!resource.input?.path || typeof resource.input.path !== "string") throw a
constructor/validation error), then compute parts/filename and set
resource.input.path = `resources/bin/${filename}`; ensure the thrown error is a
clear constructor validation error mentioning the resource id/name and
missing/invalid input.path so callers can handle it.
---
Nitpick comments:
In @.github/scripts/component-constructor.js:
- Around line 154-156: The catch block currently calls
core.setFailed(error.message) which can be empty for non-Error throws; update
the catch handling in the catch (error) block to normalize the thrown value
before passing to core.setFailed (e.g., if error is an Error use error.message
or error.stack, otherwise convert to a string/JSON via String(error) or
JSON.stringify(error) and include it in the message) so core.setFailed always
receives a meaningful string; ensure you reference the existing catch (error)
and core.setFailed invocation when making the change.
In @.github/scripts/component-constructor.test.js:
- Around line 172-186: The test creates temp dirs/files and cleans them up
manually but can leak artifacts if assertions fail; wrap the temp-file test
blocks that call parseConstructorFile (the block creating tmpDir/tmpFile and the
similar "empty-file" block) in a try/finally where the finally always calls
fs.unlinkSync(tmpFile) and fs.rmdirSync(tmpDir) (guarding existence checks as
needed) so cleanup runs even on assertion failures; update both the block using
parseConstructorFile and the other empty-file test to use this try/finally
pattern.
In @.github/workflows/publish-ocm-component-version.yml:
- Around line 34-37: The workflow's job permissions block currently sets
actions: read and packages: write but omits contents: read, which can break
actions/checkout; update the job-level permissions to include contents: read so
the actions/checkout step can access repository contents (modify the permissions
block that contains actions: read and packages: write to add contents: read) and
mirror the same change for the other similar permissions block used around the
actions/checkout step.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0ca10dfb-2a88-4174-808d-fecae3146f9c
📒 Files selected for processing (3)
.github/scripts/component-constructor.js.github/scripts/component-constructor.test.js.github/workflows/publish-ocm-component-version.yml
On-behalf-of: Gerald Morrison (SAP) <gerald.morrison@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
On-behalf-of: Gerald Morrison (SAP) <gerald.morrison@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
On-behalf-of: Gerald Morrison (SAP) <gerald.morrison@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
…component-model into add-cv-creation-workflow On-behalf-of: Gerald Morrison (SAP) <gerald.morrison@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
…pen-component-model#1901) On-behalf-of: Gerald Morrison (SAP) <gerald.morrison@sap.com> <!-- markdownlint-disable MD041 --> #### What this PR does / why we need it Create a reusable workflow that can build component versions based on a component constructor that can be used in cli/controller build and cli/controller promotion step. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Added a CI workflow to publish OCM component versions: verifies artifacts, handles GHCR auth, supports configurable repository/CLI image and optional conflict policy, runs the publish step, and appends a Markdown summary with a link to the published package. * **Tests** * Added unit tests covering constructor parsing, name/version extraction, URL construction, and constructor patching logic. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com> Co-authored-by: Gerald Morrison (SAP) <gerald.morrison@sap.com> Co-authored-by: Piotr Janik <piotr.janik@sap.com>
…pen-component-model#1901) On-behalf-of: Gerald Morrison (SAP) <gerald.morrison@sap.com> <!-- markdownlint-disable MD041 --> #### What this PR does / why we need it Create a reusable workflow that can build component versions based on a component constructor that can be used in cli/controller build and cli/controller promotion step. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Added a CI workflow to publish OCM component versions: verifies artifacts, handles GHCR auth, supports configurable repository/CLI image and optional conflict policy, runs the publish step, and appends a Markdown summary with a link to the published package. * **Tests** * Added unit tests covering constructor parsing, name/version extraction, URL construction, and constructor patching logic. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com> Co-authored-by: Gerald Morrison (SAP) <gerald.morrison@sap.com> Co-authored-by: Piotr Janik <piotr.janik@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
On-behalf-of: Gerald Morrison (SAP) gerald.morrison@sap.com
What this PR does / why we need it
Create a reusable workflow that can build component versions based on a component constructor that can be used in cli/controller build and cli/controller promotion step.
Summary by CodeRabbit