Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 72 additions & 11 deletions .claude/skills/release/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Release input: $ARGUMENTS
- **FLS tags** do NOT use a `v` prefix: `0.3.0`, `0.4.0` (repo: `jumpstarter-dev/fls`)
- Python packages are versioned automatically from git tags via `hatch-vcs` — no manual version files.
- The `bundle/` directory is NOT committed to the repo.
- `GITHUB_USER` env var controls the fork for community-operators (defaults to `mangelajo`).
- `GITHUB_USER` env var controls the fork for community-operators and for pushing version-bump PRs. Auto-detected via `gh api user -q .login` if not set.
- Do NOT modify `controller/deploy/operator/api/v1alpha1/jumpstarter_types.go` — the operator resolves `:latest` image defaults to its own version at runtime.

## Ordering constraint
Expand All @@ -36,9 +36,12 @@ If a new FLS version is needed, release FLS first so binaries exist before Jumps

### 1. Gather context and determine release type

Fetch the latest remote state first, then inspect:
Fetch the latest remote state and detect the GitHub user early:

```bash
GITHUB_USER="${GITHUB_USER:-$(gh api user -q .login)}"
echo "GitHub user: $GITHUB_USER"
Comment on lines 41 to +43

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Validate GITHUB_USER before reuse.

If gh api user -q .login fails, the assignment leaves GITHUB_USER empty. Later blocks still use it for fork PRs and make contribute; require a non-empty value before the workflow proceeds.

🧰 Tools
🪛 SkillSpector (2.5.1)

[error] 299: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/skills/release/SKILL.md around lines 41 - 43, Validate that
GITHUB_USER is non-empty immediately after its assignment from the existing
environment value or gh api user lookup. If resolution fails or produces an
empty value, stop the release workflow with a clear error before any later fork
PR or make contribute steps reuse GITHUB_USER.


git fetch origin --tags
git branch --show-current
git branch -r | grep 'origin/release-'
Expand Down Expand Up @@ -127,7 +130,7 @@ Using the git state and `$ARGUMENTS` (if provided), ask the user:
| SemVer(`CARGO`) != SemVer(`LATEST`) and `AHEAD == 0` | Warn: `Cargo.toml` version does not match the published release tag — ask the user before proceeding. |
| Pin files disagree with each other | Warn and fix pins to a single version before tagging. |

Present the recommendation with the supporting numbers (`PINNED`, `LATEST`, `CARGO`, `AHEAD`), then ask the user to confirm or override.
Present the recommendation with the supporting numbers (`PINNED`, `LATEST`, `CARGO`, `AHEAD`) and the detected `GITHUB_USER` (so the user can override via `export GITHUB_USER=...` if needed), then ask the user to confirm or override.

### 2A. Create a new release branch

Expand Down Expand Up @@ -257,11 +260,42 @@ git pull origin release-X.Y
make manifests generate
```

4. **Commit and push** the changes to the release branch. Files to include:
4. **Commit and push via PR** — release branches are protected and require merge queue, so direct pushes will be rejected. Files to include:
- `controller/deploy/operator/Makefile`
- Any files changed by `make manifests generate`
- FLS pin files (if bumped): `python/Containerfile`, `python/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py`

Push to the user's fork and create a PR targeting the release branch:

```bash
BUMP_BRANCH="release-X.Y-version-bump-X.Y.Z"
git checkout -b "$BUMP_BRANCH"
git add -A
git commit -m "chore: bump version to X.Y.Z"
Comment on lines +272 to +274

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Stage only the intended release files.

Line [273] stages every tracked and untracked change in the checkout. This can include unrelated changes in the version-bump PR, despite the explicit file list in lines [264-266]. Use explicit paths or abort when unexpected worktree changes exist.

🧰 Tools
🪛 SkillSpector (2.5.1)

[error] 299: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/skills/release/SKILL.md around lines 272 - 274, Update the release
workflow around the git add step after creating BUMP_BRANCH so it stages only
the explicitly listed release files from the earlier file list, rather than
using git add -A. Alternatively, validate that the worktree contains no
unexpected changes and abort before staging when it does; preserve the
version-bump commit behavior for the intended files.


# Push to fork — use the remote pointing to GITHUB_USER's fork.
# Common names: "upstream" or the user's username. Check with `git remote -v`.
git push <fork-remote> "$BUMP_BRANCH"

gh pr create \
--title "chore: bump version to X.Y.Z" \
--body "Version bump for release X.Y.Z" \
--head "${GITHUB_USER}:${BUMP_BRANCH}" \
--base release-X.Y
```
Comment on lines +276 to +285

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
git ls-files | grep -F '.claude/skills/release/SKILL.md' || true

echo "== relevant sections =="
if [ -f .claude/skills/release/SKILL.md ]; then
  sed -n '240,310p' .claude/skills/release/SKILL.md | cat -n -v
  echo "----"
  sed -n '360,430p' .claude/skills/release/SKILL.md | cat -n -v
fi

echo "== search GITHUB_USER and fork remotes =="
rg -n "GITHUB_USER|github|fork|gh repo fork|pr create|contribute" .claude/skills/release/SKILL.md || true

echo "== git diff stat/name =="
git diff --stat || true
git diff -- .claude/skills/release/SKILL.md | sed -n '1,220p' || true

Repository: jumpstarter-dev/jumpstarter

Length of output: 8959


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== upstream and contribute files =="
git ls-files | rg '(^|/)Contribution|contribute|Makefile|SKILL\.md$' | sed -n '1,120p'

echo "== search contribute/user/remote/user =="
rg -n "contribute|GITHUB_USER|user=|remote.*user|git remotes|git remote -v|github_pr_create|community-operators|community-operators-prod|user" .claude/skills/release/SKILL.md Makefile Makefile.* controller .github 2>/dev/null || true

echo "== read likely contribute files =="
for f in $(git ls-files | rg 'Contribution|contribute|Makefile' | sed -n '1,30p'); do
  echo "---- $f ($(wc -l < "$f") lines) ----"
  sed -n '1,260p' "$f" | cat -n | sed -n '1,240p'
done

Repository: jumpstarter-dev/jumpstarter

Length of output: 50384


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== contribution scripts =="
f=controller/deploy/operator/contribute/update-contributions.sh
if [ -f "$f" ]; then
  wc -l "$f"
  sed -n '1,160p' "$f" | cat -n
fi

echo "== release script environment section =="
f=.claude/skills/release/SKILL.md
if [ -f "$f" ]; then
  sed -n '1,60p' "$f" | cat -n
fi

Repository: jumpstarter-dev/jumpstarter

Length of output: 9344


🌐 Web query:

GitHub CLI gh repo fork forked repo default branch owner authenticated user --clone=false

💡 Result:

The command gh repo fork with the --clone=false flag creates a fork of the specified repository on your authenticated GitHub account without cloning it locally to your machine [1][2]. By default, the gh repo fork command targets your authenticated user account as the owner of the new fork [1][2]. When running the command: - If you provide a repository argument (e.g., gh repo fork OWNER/REPO --clone=false), it creates a fork of that repository in your account [1][2]. - If you run it without an argument inside a git repository, it forks the current repository to your account [1][2]. The --default-branch-only flag, when included, ensures that only the default branch is copied over to the new fork instead of all branches [1][3][4]. Example command: gh repo fork OWNER/REPO --default-branch-only --clone=false This command is particularly useful for automation and scripting, as it skips interactive prompts that would otherwise appear when running the command without explicit flag settings [5][2].

Citations:


Fail before creating or using community-ops forks when GitHub accounts differ. The community operator flow sets up and reads user remotes from ${GITHUB_USER}, but the pre-check gh repo view "${GITHUB_USER}/..." / gh repo fork "$REPO" only checks the authenticated account state. If those differ, make contribute can create a fork under someone else and later push to ${GITHUB_USER}’s nonexistent fork.

🧰 Tools
🪛 SkillSpector (2.5.1)

[error] 299: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

📍 Affects 1 file
  • .claude/skills/release/SKILL.md#L276-L285 (this comment)
  • .claude/skills/release/SKILL.md#L399-L406
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/skills/release/SKILL.md around lines 276 - 285, Update the
community-operator pre-checks and fork setup in .claude/skills/release/SKILL.md
at lines 276-285 and 399-406 to verify that the authenticated GitHub account
matches GITHUB_USER before running gh repo view, gh repo fork, or using the
configured fork remote; fail with a clear error when they differ, preventing
creation or use of a fork under the wrong account.


Wait for the merge queue to complete. Monitor with `gh pr view <PR_URL> --json state,mergeStateStatus` or watch for the merge notification.

#### Phase 1.5: Sync local branch after merge

After the merge queue merges the PR, the local branch diverges from the merge commit. Sync before tagging:

```bash
git checkout release-X.Y
git fetch origin
git reset --hard origin/release-X.Y
```
Comment on lines +289 to +297

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Guard the destructive reset.

Line [296] can discard tracked worktree changes and move the local branch away from local commits. Users can modify the checkout while the merge queue runs. Abort on a dirty worktree and preserve or confirm local state before running git reset --hard.

🧰 Tools
🪛 SkillSpector (2.5.1)

[error] 299: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/skills/release/SKILL.md around lines 289 - 297, Update the Phase 1.5
sync instructions around the git reset sequence to check for a clean worktree
and confirm local state before executing the destructive reset. Abort when
tracked changes or unreviewed local commits are present, and only run reset
--hard after the user explicitly confirms or preserves that state.

Source: Linters/SAST tools


#### Phase 2: Tag and GitHub Release

5. **Create and push the git tag:**
Expand Down Expand Up @@ -325,6 +359,20 @@ gh run list --workflow=build-images.yaml --limit 5

The user can also check `quay.io/jumpstarter-dev/jumpstarter-controller:X.Y.Z` directly.

#### Verify correct branch state

During long CI waits, the user may have switched branches. Before generating the bundle, verify the branch and version are correct — `make bundle` silently uses whatever is checked out:

```bash
CURRENT_BRANCH=$(git branch --show-current)
CURRENT_VERSION=$(grep '^VERSION ?= ' controller/deploy/operator/Makefile | awk '{print $3}')
if [ "$CURRENT_BRANCH" != "release-X.Y" ] || [ "$CURRENT_VERSION" != "X.Y.Z" ]; then
echo "ERROR: Expected branch release-X.Y with VERSION=X.Y.Z"
echo "Got branch=$CURRENT_BRANCH VERSION=$CURRENT_VERSION"
git checkout release-X.Y && git pull origin release-X.Y
fi
Comment on lines +362 to +373

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Abort when checkout correction fails.

If git checkout or git pull fails, the && chain stops but the workflow continues to make bundle. The bundle can then use the wrong branch or version, which is the failure this guard is intended to prevent. Exit on either failure and re-check the branch and version after correction.

🧰 Tools
🪛 SkillSpector (2.5.1)

[error] 299: [YR1] YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.

(YARA Match (YR1))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/skills/release/SKILL.md around lines 362 - 373, Update the
branch/version guard in the release verification section to abort before make
bundle when git checkout or git pull fails, and re-check CURRENT_BRANCH and
CURRENT_VERSION after a successful correction. Continue only when the
post-correction values match release-X.Y and X.Y.Z; otherwise exit with an
error.

```

#### Generate the OLM bundle

```bash
Expand All @@ -346,14 +394,27 @@ Show the output to the user and ask them to confirm it looks correct before cont

#### Contribute to community-operators

**Note:** `make contribute` depends on `make bundle` internally and will re-run bundle generation. This means the branch state guard above is critical — if the wrong branch is checked out, `make contribute` will silently produce a wrong bundle.

**Pre-check: Ensure forks exist** under `GITHUB_USER`. If they don't, `make contribute` will fail mid-way:

```bash
cd controller/deploy/operator
for REPO in k8s-operatorhub/community-operators redhat-openshift-ecosystem/community-operators-prod; do
if ! gh repo view "${GITHUB_USER}/$(basename $REPO)" &>/dev/null; then
echo "Forking $REPO..."
gh repo fork "$REPO" --clone=false
fi
done
```

# Set GITHUB_USER if different from default (mangelajo):
# export GITHUB_USER=yourusername
Then run the contribute script:

```bash
cd controller/deploy/operator

# GITHUB_USER controls which fork the contribute script uses
# AUTO_CONFIRM=1 skips the interactive y/N prompt
AUTO_CONFIRM=1 make contribute
GITHUB_USER="${GITHUB_USER}" AUTO_CONFIRM=1 make contribute
```

After the script completes, push to the fork and create PRs using `gh`:
Expand All @@ -376,17 +437,17 @@ cd controller/deploy/operator/contribute/community-operators
gh pr create --repo k8s-operatorhub/community-operators \
--title "operator jumpstarter-operator (X.Y.Z)" \
--body "Release X.Y.Z of the jumpstarter-operator for the alpha channel." \
--head ${GITHUB_USER:-mangelajo}:$BRANCH --base main
--head ${GITHUB_USER}:$BRANCH --base main

# PR for community-operators-prod
cd ../community-operators-prod
gh pr create --repo redhat-openshift-ecosystem/community-operators-prod \
--title "operator jumpstarter-operator (X.Y.Z)" \
--body "Release X.Y.Z of the jumpstarter-operator for the alpha channel." \
--head ${GITHUB_USER:-mangelajo}:$BRANCH --base main
--head ${GITHUB_USER}:$BRANCH --base main
```

Replace `GITHUB_USER` with the actual GitHub username (default: `mangelajo`).
The `GITHUB_USER` variable was detected in step 1 and is used throughout.

### 3. Post-release steps

Expand Down
Loading