Skip to content

ci(release): post to Slack when a released host needs an upload by hand - #7

Merged
imoital merged 21 commits into
mainfrom
ci/upload-reminder
Nov 12, 2026
Merged

imoital merged 21 commits into
mainfrom
ci/upload-reminder

Conversation

@imoital

@imoital imoital commented Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Some hosts take a release only as an upload done by hand, for example a marketplace that reviews every version (Cursor Marketplace, the OpenAI portal). Nothing told anyone a release was waiting, so now each host says whether it needs one and the release posts a reminder to #proj-integrations.

  • upload: in every host's vars.yaml. It's required: either false (installs read this repo or its mirror), or to: (where) and url: (an https:// link to the upload page). Copilot is false. npm run new-host writes a TODO(new-host) for it.

  • npm run validate fails if upload: is missing, or isn't false or a valid to:/url:.

  • .github/workflows/upload-reminder.yml, called by release.yml for each released host like the mirror job, or run by hand from Actions (a dry run unless unticked):

    • checks that the tag is that host's release;
    • posts through a Slack incoming webhook in the SLACK_WEBHOOK_INTEGRATIONS secret of the release environment;
    • always writes the message to the job summary.

    The message tags @ZenGrow and reads: ":package: cursor-v0.2.3 is released and needs an upload to Cursor Marketplace." It's followed by links to dist/cursor at the tag, the upload page and the GitHub release.

  • CONTRIBUTING.md: an "Uploads by hand" section, and upload: in what a new host has to decide.

The webhook and its secret aren't set up yet. Without them, a release with upload: set fails this job (the release itself is already done) and leaves the reminder in the job summary, so a missed reminder can't go unnoticed. No host on main sets upload: yet, so set the secret before the first one merges.

Not in this PR

  • Each host PR sets its own upload: when it's rebased onto main.
  • OpenClaw (ClawHub trusted publishing) and Activepieces (npm trusted publishing) could later publish automatically. They're follow-ups.

How to check it

  • npm run validate passes. With upload: removed or url: not https://, it fails and names the problem.
  • actionlint is clean on all workflows.
  • The jq that builds the message was run locally on a sample Cursor release.
  • After merge: run Upload reminder with host=copilot and tag=copilot-v0.1.1. It should be a no-op, since Copilot is upload: false.

@imoital
imoital marked this pull request as ready for review November 9, 2026 09:17
@imoital
imoital requested a review from a team as a code owner November 9, 2026 09:17
@imoital
imoital requested a review from tedi-z November 9, 2026 09:17
tedi-z
tedi-z previously approved these changes Nov 9, 2026
platforms/<host>/scripts/ is now reserved like skills/: render never copies it
into dist/. npm run validate runs platforms/<host>/scripts/validate.mjs on
dist/<host> when it exists, and npm run package -- <host> runs its package.sh.
shared/text/<name>.md holds one fact in plain text. A skill inlines it with
{{< name}}; code uses {{text:name}}, a quoted string literal. using-zenrows
and extract-structured-data now take AUTH004, AUTH014, AUTH006 and REQS007's
page_not_recognised from there; every plugin renders byte-identically.
Validate fails on a snippet with markdown, more than one line, or no user.

kind: code in vars.yaml makes a host whose output isn't a plugin (code for
another project, or a marketplace listing): it ships only its own files, with
{{...}} filled in .ts/.js too, no skills, LICENSE, assets or plugin.json, keeps
its README out of dist, needs no release-please entry yet, and may keep a
scripts/check.sh.
Per-host scripts (validate.mjs, package.sh, npm run package) are only used by
the OpenAI plugin, and check.sh and the AUTH/REQS007 snippets only by the
Activepieces piece: they stay with those hosts. What's left is what any code
host needs: kind: code, and shared/text with {{< name}} and {{text:name}}.
Comments and CONTRIBUTING describe any code host, a piece or a listing.
tedi-z
tedi-z previously approved these changes Nov 10, 2026
Comment thread scripts/validate.mjs Outdated
// Every host says whether its releases are uploaded somewhere by hand, so the
// release workflow knows whether to post a reminder.
const upload = values.upload;
if (upload === undefined) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I trial-merged this branch with build/render-host-kinds (#9). They merge textually clean, but this rule then applies to code hosts:

❌ piece: vars.yaml has no upload: (false, or to: and url:; see CONTRIBUTING.md)

A kind: code host with no release-please entry never gets a tag and never appears in detect’s packages, so upload-reminder can never fire for it. Validate still demands an answer, and would accept an upload: {to, url} that is structrally unhonourable. #9 says it merges first, so this lands here. Worth deciding explicitly: exempt code hosts, exempt only unreleased ones, or accept that they must all write upload: false.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Decided by release rather than by kind: a host with a release-please entry must say upload:, and one without can leave it out or write false. Setting to:/url: on a host that never releases fails with "has no release, so an upload reminder can never fire". While I was there I also made validate reject a link Slack would cut short (a space, <, > or |). Fixed in c455731, with npm test cases. #7 now has #9 merged in, so it's tested against code hosts directly.

Comment thread .github/workflows/upload-reminder.yml Outdated
HOST: ${{ inputs.host }}
TAG: ${{ inputs.tag }}
# workflow_call has no dry_run input, so a release always posts.
DRY_RUN: ${{ inputs.dry_run == true }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

non-blocker
This diverges from mirror.yml for no gain. mirror.yml declares dry_run in its workflow_call inputs with default: false and writes DRY_RUN: ${{ inputs.dry_run }}. Here the input is omitted and the expression leans on null == true coercing to false, which is why line 46 needs a comment to be readable.

Both behave correctly, I confirmed the semantics but two sibling reusable workflows now answer the same question two ways. Suggest matching mirror.yml.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Matched mirror.yml: dry_run is declared on workflow_call with default: false, and the job uses DRY_RUN: ${{ inputs.dry_run }}, so the comment is gone. Fixed in a94ab8c. I also worded the reminder's notices like mirror.yml's (ec5224d).

Fail the render on any {{…}} left in a rendered text file, and on a skills/ folder in a code host. Validate requires a code host README without {{…}}, matches {{< name}} the way the render does, and only treats backticks, *, links and headings as markdown in a snippet.
…s and vars.yaml

Other tools' {{…}} (JSX, Make, n8n) ships as written. Snippets are trimmed and can't contain {{…}}, and a malformed vars.yaml or kind names the file.
@imoital
imoital changed the base branch from main to build/render-host-kinds November 11, 2026 09:27
tedi-z
tedi-z previously approved these changes Nov 11, 2026
Base automatically changed from build/render-host-kinds to main November 11, 2026 14:58
@imoital
imoital dismissed tedi-z’s stale review November 11, 2026 14:58

The base branch was changed.

# Conflicts:
#	scripts/lib.mjs
#	scripts/test.mjs
@imoital
imoital requested a review from tedi-z November 11, 2026 15:00
@imoital
imoital merged commit 7ac9ae2 into main Nov 12, 2026
3 checks passed
@imoital
imoital deleted the ci/upload-reminder branch November 12, 2026 11:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants