diff --git a/claudio-plugin/skills/konflux-release/SKILL.md b/claudio-plugin/skills/konflux-release/SKILL.md index a0769f7..a7fe98a 100644 --- a/claudio-plugin/skills/konflux-release/SKILL.md +++ b/claudio-plugin/skills/konflux-release/SKILL.md @@ -29,6 +29,7 @@ This skill includes helper scripts in `scripts/` directory. - **ReleasePlan** - defines how and where releases are deployed - **Application** - group of related components - **Component** - individual buildable/deployable unit +- **Stage-RC Release** - a release candidate deployed to a staging registry for validation before production. Follows the same workflow as production but uses stage-rc release plans ## Script Execution Requirements @@ -80,6 +81,8 @@ This pattern matches the script in any user directory or plugin cache location. Key principle: stage and production releases reference the same Snapshot because it points to the same built container images. +The same workflow applies to **stage-RC releases**: they use stage-rc release plans instead of production plans, targeting a staging registry for release candidate validation before production. + ### Step 1: Resolve Input to Commit SHA Three options depending on what the user provides: @@ -125,6 +128,8 @@ kubectl get releases -n -l "pac.test.appstudio.openshift.io/sha= -n -o json | jq -r '.status.artifacts.images[] | select(.name == "") | .urls[] | select(test("-[0-9]+$"))' +``` + +The filter `test("-[0-9]+$")` selects the URL whose tag ends with the numeric build timestamp, distinguishing it from `-source`, version-only, and digest tags. Include this URL in the release summary so reviewers can verify the exact image being promoted. -Query existing production releases to determine the next sequence number: +### Step 6: Auto-Increment Release Sequence + +Determine the next sequence number by counting existing releases whose name starts with the same prefix (base-component + version + release-type): ```bash -kubectl get releases -n --sort-by=.metadata.creationTimestamp -o json | jq '[.items[] | select(.metadata.name | startswith("--prod-"))] | length' +kubectl get releases -n -o json | jq '[.items[] | select(.metadata.name | startswith("---"))] | length' ``` -Use length + 1 as the next sequence number for the release name. +Use length + 1 as the next sequence number. + +For full-application releases, count by release plan instead: + +```bash +kubectl get releases -n -o json | jq '[.items[] | select(.spec.releasePlan == "")] | length' +``` ### Step 7: Generate Production Release YAMLs @@ -177,10 +198,9 @@ The script automatically creates the output directory. Use the provided script f ### Step 8: Generate Release Summary Create a summary document that includes: -- Release date +- Release date and release type (production, stage-rc, etc.) - Git commit SHA and source URL -- Component status table (component name, status, release name, release plan) -- Stage release information +- Component table with: component name, type (GA/TP), release name, release plan, stage image URL (from Step 5b), snapshot, and stage release - Generated YAML filenames - Links to Konflux UI for monitoring (if available) @@ -242,7 +262,8 @@ The script replaces all placeholders recursively through all string values. ### Release Types - **RHEA** (default) - Enhancement Advisory, standard feature releases -- **RHSA** - Security Advisory, requires `--cves-file` parameter +- **RHSA** - Security Advisory, requires `--cves-file` and `--component` parameters + - The script auto-constructs the versioned CVE component name from `--component` and `--version` (e.g., `my-component` + `3.2.2` → `my-component-3-2-2`) - CVE file format: one CVE per line (CVE-YYYY-NNNNN) - Comments starting with # are ignored - Empty lines are skipped @@ -251,52 +272,92 @@ The script replaces all placeholders recursively through all string values. ### Structure +`RELEASE_SUMMARY.md` is organised into **one section per release type** (production, stage-rc, etc.). Each section is appended when that type of release is created. Never mix release types in a single table. + ```markdown # Release Summary -## Release Information -- Date: YYYY-MM-DD -- Version: X.Y.Z -- Commit: -- Source: +## Production Release (YYYY-MM-DD) + +### Components -## Components +| Component | Type | Release Name | Release Plan | Stage Image | Snapshot | Stage Release | +|-----------|------|--------------|--------------|-------------|----------|---------------| +| component-1 | GA | name-prod-1 | plan-prod | quay.io/org/img:tag-ts | snap-name | stage-rel-name | +| component-2 | TP | name-tp-prod-1 | plan-tp-prod | quay.io/org/img:tag-ts | snap-name | stage-rel-name | -| Component | Status | Release Name | Release Plan | -|-----------|--------|--------------|--------------| -| component-1 | Ready | name-prod-1 | plan-prod | -| component-2 | Ready | name-prod-2 | plan-tp-prod | +### Commit SHA -## Generated Files +| Field | Value | +|-------|-------| +| SHA | abc123... | +| Source | | + +### Generated Files - component-1-prod.yaml - component-2-prod.yaml ``` +- **Stage Image** — the timestamped image URL extracted from `.status.artifacts.images[].urls[]` (see Step 5b) +- **Snapshot** and **Stage Release** — linked to Konflux UI if available +- Each release type (prod, stage-rc) gets its own heading and table + ### Storage In config-driven mode, follow the config repo's CLAUDE.md for where to store the summary. In manual mode, store it alongside the generated YAMLs in the output directory. +## Konflux UI Links + +When a Konflux UI base URL is available (provided by the config repo or user), construct monitoring links using these patterns: + +- **Prefix:** `/ns//applications/` +- **Releases list:** `/releases` +- **Snapshot:** `/snapshots/` +- **Release:** `/releases/` + +Include these links in the release summary and any merge request description to help reviewers verify the release. + ## Naming Conventions ### Release Names -Pattern: `--prod-` +**Single-component releases** (one Release CR per component — the default): + +Pattern: `---` + +Example: `my-comp-cuda-1-2-0-prod-1`, `my-comp-rocm-1-2-0-stage-rc-1` + +- `` - component name from the product config (without branch/version suffixes that Konflux appends to the Konflux component name) +- `` - semantic release version with dots replaced by dashes (e.g., `3.3.1` → `3-3-1`, `3.4.0-ea.2` → `3-4-0-ea-2`) +- `` - release type suffix (e.g., `prod`, `stage-rc`) +- `` - sequence number (auto-incremented per base-component + release-type, starting from 1) + +This makes it possible to identify which component/variant was released without opening the Release CR. Do NOT use the full Konflux component name (which includes branch version suffixes) — that causes version duplication in the release name. Keep names under 63 characters (Kubernetes limit). + +**Full-application releases** (one Release CR covers all components in a snapshot): + +Pattern: `-` + +- `` - the target release plan name +- `` - sequence number (auto-incremented per release plan, starting from 1) -Example: `my-component-1-2-0-prod-1` +### ReleasePlan Types -- `` - full component name -- `` - version with dots replaced by dashes -- `prod` - environment -- `` - sequence number (auto-incremented) +There are four types of release plans. The skill **creates** Release CRs targeting prod, tech-preview-prod, or stage-rc plans. It **reads** stage releases (created automatically by CI) to discover snapshots. -### ReleasePlan Names +| Type | Pattern | Purpose | Created by | +|------|---------|---------|------------| +| Stage | `-stage` | Automatic nightly/development builds | CI (on push) — skill only reads these | +| Stage-RC | `-stage-rc` | Release candidate validation on staging registry | Skill (manual trigger) | +| GA production | `-prod` | GA production release | Skill (manual trigger) | +| TP production | `-tech-preview-prod` | Tech preview production release | Skill (manual trigger) | -Common patterns: -- GA production: `-prod` -- Tech preview production: `-tech-preview-prod` -- Stage: `-stage` +**Which plan to use when creating a Release CR:** +- User asks for a **production release** → use `*-prod` (GA components) or `*-tech-preview-prod` (tech preview components) +- User asks for a **stage-rc release** → use `*-stage-rc` +- Never create Release CRs targeting `*-stage` — those are automatic ## Multi-Component Release diff --git a/claudio-plugin/skills/konflux-release/scripts/generate_release_yaml.py b/claudio-plugin/skills/konflux-release/scripts/generate_release_yaml.py index ab39e4d..0150528 100755 --- a/claudio-plugin/skills/konflux-release/scripts/generate_release_yaml.py +++ b/claudio-plugin/skills/konflux-release/scripts/generate_release_yaml.py @@ -19,7 +19,7 @@ --output out/my-product-cuda-ubi9-3.2.5-prod.yaml Arguments: - --component NAME Component name (required) + --component NAME Component name (required for RHSA with --cves-file) --version VERSION Semantic version (e.g., 3.2.5) (required) --snapshot NAME Snapshot name (required) --release-plan NAME Release plan name (required) @@ -157,7 +157,8 @@ def generate_prod_release_yaml(component_name, version, snapshot, release_plan, if release_type == 'RHSA' and cves_file: cve_ids = load_cves_from_file(cves_file) # Build CVE list with component name - release_notes['cves'] = [{'key': cve_id, 'component': component_name} for cve_id in cve_ids] + versioned_component = f"{component_name}-{version.replace('.', '-')}" + release_notes['cves'] = [{'key': cve_id, 'component': versioned_component} for cve_id in cve_ids] # Build production release YAML prod_release = { diff --git a/claudio-plugin/skills/konflux-release/tests/test_generate_release_yaml.py b/claudio-plugin/skills/konflux-release/tests/test_generate_release_yaml.py index 7a0daf2..7236c83 100644 --- a/claudio-plugin/skills/konflux-release/tests/test_generate_release_yaml.py +++ b/claudio-plugin/skills/konflux-release/tests/test_generate_release_yaml.py @@ -146,8 +146,8 @@ def test_rhsa_with_cves_file(self, tmp_path): cve_file.write_text("CVE-2024-1234\nCVE-2024-5678\n") cves = self._call(release_type="RHSA", cves_file=str(cve_file))["spec"]["data"]["releaseNotes"]["cves"] assert cves == [ - {"key": "CVE-2024-1234", "component": "my-comp"}, - {"key": "CVE-2024-5678", "component": "my-comp"}, + {"key": "CVE-2024-1234", "component": "my-comp-3-3-0"}, + {"key": "CVE-2024-5678", "component": "my-comp-3-3-0"}, ] def test_template_substitution_applied(self):