Skip to content

chore(skills): add release-widget skill - #2370

Open
yordan-st wants to merge 15 commits into
mainfrom
skill/release-widget
Open

chore(skills): add release-widget skill#2370
yordan-st wants to merge 15 commits into
mainfrom
skill/release-widget

Conversation

@yordan-st

Copy link
Copy Markdown
Contributor

Summary

  • Adds `.agents/skills/release-widget/SKILL.md` — automates widget/module release pipeline (version bump → GitHub draft release → OSS clearance → Marketplace publish)
  • Previously ran as private trial (untracked); opening as draft for team feedback before promoting to shared skill set

Test plan

  • Used successfully for image-web v1.6.0 and charts-web v6.3.2 releases

@yordan-st
yordan-st marked this pull request as ready for review August 4, 2026 09:30
@yordan-st
yordan-st requested a review from a team as a code owner August 4, 2026 09:30
@github-actions

This comment has been minimized.

Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
@yordan-st
yordan-st force-pushed the skill/release-widget branch 2 times, most recently from fbe06a0 to 7773a8b Compare August 21, 2026 13:57
@github-actions

This comment has been minimized.

@yordan-st
yordan-st force-pushed the skill/release-widget branch from 74a8e99 to cce0a0d Compare September 7, 2026 12:36
@github-actions

This comment has been minimized.

Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
@github-actions

This comment has been minimized.

Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread automation/utils/bin/rui-bump-version.ts Outdated
  Automates widget/module release pipeline: version bump, GitHub draft
  release, OSS clearance SBOM, Marketplace publish. Sharing for team
  feedback before promoting out of private trial.
@yordan-st
yordan-st force-pushed the skill/release-widget branch from 50fbf1e to 1ac50b0 Compare September 8, 2026 13:34
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Comment thread automation/utils/src/changelog-parser/index.ts
Comment thread automation/utils/bin/rui-bump-version.ts Outdated
Comment thread automation/utils/bin/rui-bump-version.ts Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated
Comment thread .agents/skills/release-widget/SKILL.md Outdated

Find the run matching this tag/branch.

- `conclusion: success` → means the API call didn't error, not that the version is live (`createDraft`/`publishDraft` are write-only, no read-back). Confirm with a read: `marketplace-mcp`'s `get_content_versions` with `contentId` = `appNumber` from Phase 0, and check `<version>` is listed. If `marketplace-mcp` isn't connected or errors, ask the user to check Marketplace → package page → Manage Versions. Don't declare the release done until one of the two confirms it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Marketplace → package page → Manage Versions

User can simply go to the front page to see it, no need to login and open admin panel.

@r0b1n r0b1n Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

createDraft/publishDraft are write-only, no read-back)

I don't think this is any useful information, rather internal details. Instruct it to simply confirm the version appeared in the marketplace.

Comment thread .agents/skills/release-widget/SKILL.md Outdated
…helpers

- skill: user merges the changelog PR, not the agent (needs team approvals)
- skill: drop gh pr merge from the autonomy carve-out
- skill: clarify why a successful publish call doesn't guarantee the version is live
- skill: check the public Marketplace listing instead of the admin panel
- skill: find a wrapped widget's owner in pluggableWidgets too, not just modules
- skill: correct which phases reuse appNumber vs npm-package-name
- skill: drop the unnecessary rui-helpers-not-linked check
- rui-bump-version: accept only an explicit x.y.z version, no bump-type shorthand
- rui-bump-version: keep the @mendix/ scope in bumpedPackages output
- bump-version: getNewVersion now uses Version's bump methods instead of manual math
- rui-changelog: read each wrapped widget's own CHANGELOG.md for module unreleased work
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

AI Code Review

🔶 Changes requested — one or more medium-severity items must be addressed


What was reviewed

File Change
.agents/skills/release-widget/SKILL.md New skill: full release pipeline (version bump → draft release → OSS clearance → Marketplace publish)
automation/utils/bin/rui-bump-version.ts New CLI: bumps version in package.json + package.xml for a package and its wrapped dependencies
automation/utils/bin/rui-changelog.ts New CLI: reads unreleased changelog entries (supports both widget and module formats)
automation/utils/bin/rui-create-jira-version.ts New CLI: creates Jira version, exits 0 on API failure so it never blocks a release
automation/utils/bin/rui-generate-oss-sbom.ts New CLI: downloads MPK from draft release and generates SBOM zip via generator jar
automation/utils/bin/rui-package-info.ts New CLI: prints name/version/appNumber/appName from the current directory's package.json
automation/utils/bin/rui-upload-readme-oss.ts New CLI: uploads READMEOSS HTML to a GitHub release; idempotent on re-run
automation/utils/bin/rui-oss-clearance.ts Refactor: replaced inline computeHash with shared computeSha256 + verifyAssetDigest
automation/utils/package.json Registered 6 new bin entries
automation/utils/src/bump-version.ts Refactor: use Version class for arithmetic; add hasPackageXml/packageXmlPath; verify write-back in bumpPackageJson
automation/utils/src/changelog-parser/index.ts New getPackageChangelog dispatcher (widget vs module format auto-detection)
automation/utils/src/github.ts Rename GitHubDraftReleaseGitHubRelease (alias kept); new getReleaseByTag with draft fallback; listReleases helper
automation/utils/src/monorepo.ts New resolvePackagePath wrapper
automation/utils/src/oss-clearance.ts Extracted computeSha256 and verifyAssetDigest from the interactive wizard
automation/utils/src/package-info.ts New isReleasable predicate
automation/utils/src/prepare-release-helpers.ts Use getPackageChangelog instead of inline if/else
automation/utils/src/version.ts Bug fix: bumpMajor was bumping minor instead of major; new isGreaterThan method

Skipped (out of scope): none — no dist/, pnpm-lock.yaml, or generated files in this diff.

CI checks: could not retrieve (permission denied in this environment) — author should confirm checks are green before merge.


Findings

🔶 Medium — listReleases fetches only the first 100 releases; getReleaseByTag can silently miss a draft

File: automation/utils/src/github.ts line 198
Problem: listReleases requests ?per_page=100 with no Link-header pagination. The GitHub REST API caps at 100 per page. getReleaseByTag falls back to this list specifically to find draft releases (which have no tag yet). As the monorepo accumulates releases across dozens of widgets, this list will eventually exceed 100 and a fresh draft for an older widget will not appear, causing getReleaseByTag to return undefined → downstream helpers that call it (e.g. rui-generate-oss-sbom, rui-upload-readme-oss) would throw "No GitHub release found for tag".
Fix:

async listReleases(): Promise<GitHubRelease[]> {
    const all: GitHubRelease[] = [];
    let page = 1;
    while (true) {
        const page_results = await fetch<GitHubRelease[]>(
            "GET",
            `https://api.github.com/repos/${this.owner}/${this.repo}/releases?per_page=100&page=${page}`,
            undefined,
            { ...this.ghAPIHeaders }
        );
        all.push(...page_results);
        if (page_results.length < 100) break;
        page++;
    }
    return all;
}

Or, since the fallback is only needed for drafts and those are typically very recent, filter to the latest N pages and document the assumption. At minimum, add a warning log when the returned page is full.


⚠️ Low — bumpXml return type Promise<boolean> is now effectively Promise<true>

File: automation/utils/src/bump-version.ts line 52
Note: The old false return paths (file missing, empty content) were removed — the function now either succeeds and returns true or throws. The Promise<boolean> signature implies callers need to branch on the value, but no caller does (the false case is handled by hasPackageXml guards upstream). Consider changing the return type to Promise<void> to make the contract clear.


⚠️ Low — verifyAssetDigest silently skips the hash check when asset.digest is absent

File: automation/utils/src/oss-clearance.ts line 23
Note: asset.digest?.replace(...) yields undefined when the field is absent; the if (expectedDigest && ...) guard then short-circuits, so the function returns the local hash without verifying it. The name verifyAssetDigest implies a guarantee. This is probably intentional ("best-effort"), but add a short comment or a console.warn so it's clear when the check was skipped, and the SKILL.md doc for Phase 4 accurately sets user expectations.


Positives

  • bumpMajor was silently bumping minor instead of major (this.minor + 1this.major + 1). Caught and fixed here — a real correctness bug for any widget hitting a breaking change.
  • getReleaseByTag draft fallback is well-designed and the comment accurately explains the GitHub API constraint (drafts have no tag, so releases/tags/{tag} 404s for them).
  • bumpPackageJson now reads package.json back after pnpm version and throws on mismatch — a robust guard against silent failures that the old spawnSync call swallowed.
  • All CLI helpers follow a consistent main().catch(error => { console.error(...); process.exit(1) }) pattern — clean and predictable for scripted use.
  • isReleasable correctly handles null, undefined, and -1 (appNumber ?? -1) > 0) with a clear explanatory comment.
  • The SKILL.md "Common Mistakes" section is specific and actionable — the rui-* helper contract violations, the 409 misdiagnosis, and the asset-gate bypass are exactly the kind of past incidents worth encoding.


### Phase 3 — Version bump + release branch (autonomous)

Bump to the `<version>` confirmed in Phase 2. The helper only accepts an explicit `x.y.z` version — it has no bump-type shorthand:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The helper only accepts an explicit x.y.z version — it has no bump-type shorthand:

Looks redundant, if there is no other possibilities why mentioning it at all.

pnpm exec rui-bump-version <npm-package-name> <version>
```

Prints `{"previousVersion", "version", "xmlBumped", "bumpedPackages", "changedPaths"}`. `xmlBumped: false` is expected for modules (no `package.xml`) — not an error.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks like xmlBumped has no real use.

```
If it's a `409` on `POST .../packages/<appNumber>/versions`:
1. Check whether an **earlier run for this exact tag already succeeded**: `gh run list --workflow="Publishes a package to marketplace" --json databaseId,status,conclusion,createdAt,headBranch` filtered to this tag. If one did, the 409 means **the version is already published** — report that, don't escalate, retry, or teardown.
2. If no prior success: check for two runs created seconds apart for the same tag (double-trigger). Otherwise it's a genuine stuck server-side state, same as the last incident — not caused by our script.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

the last incident

what is the last incident?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants