Cut new release candidate
SkillCommunicationUse when the user asks to cut, trigger, or start a release candidate for a release branch. Validates the branch against configured channel prefixes, dispatches the release workflow, receives the run URL, and posts a status notification. Don''t use for full releases, hotfixes, or non-release-candidat
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Cut new release candidate skill
What this skill tells your AI
The instructions your AI receives, as published by outlinedriven/outline-driven-development in .devin/skills/cut-new-release-candidate/SKILL.md and read by ahel’s review.
Contract
| Field | Bound contract |
|---|---|
| Trigger | User asks to cut, trigger, or start a release candidate for a release branch. |
| Authority | Remote: dispatches the release workflow on the named branch and posts one status notification; requires explicit human invocation. Preview the target and consequence before each remote mutation; mutate only the one workflow dispatch on the branch the user named and the one status notification. |
| Side effect | Runs the configured release workflow on the release branch, obtains its run URL, and posts one status notification. Nothing else changes. |
| Done | The workflow dispatch exits zero, the run query returns a non-null run URL, and the status notification is posted. |
Inputs
Required from the user:
- The release branch name. Strip a leading
origin/before validating. - Optionally, a notification destination (channel, thread, or recipient). Ask before posting if no destination was supplied.
The operator environment must supply these values before any step:
INTERNAL_REPO: theowner/repocontaining the release branches and workflow.REPO_DIR: the absolute path to its local checkout.RC_WORKFLOW_NAME: the release-candidate workflow name. Default:Cut New Release Candidate.RELEASE_CHANNELS: space-separated channel names. Default:preview stable.RELEASE_BRANCH_PREFIX: per-channel branch prefix template, with{channel}replaced by each channel name. Default:{channel}_release/.NOTIFICATION_TOKEN: a token for the notification service with write scope. Read it only from the environment; never hardcode or commit it.NOTIFICATION_ENDPOINT: the API endpoint for posting the status notification.
If INTERNAL_REPO or NOTIFICATION_TOKEN is unset, stop and ask before running. Required tools: git, an authenticated gh, jq, and curl. Run all git and gh operations inside the release repo.
Procedure
-
Validate the branch at the trust boundary: set the requested branch, strip the
origin/prefix, and reject any branch that does not start with a configured channel prefix:BRANCH_NAME="<release_branch>" case "$BRANCH_NAME" in origin/*) BRANCH_NAME="${BRANCH_NAME#origin/}";; esac is_release=0 for ch in $RELEASE_CHANNELS; do prefix=$(printf '%s' "$RELEASE_BRANCH_PREFIX" | sed "s|{channel}|$ch|") case "$BRANCH_NAME" in "$prefix"*) is_release=1; break;; esac done [ "$is_release" = 1 ] || { echo "Not a release branch: $BRANCH_NAME"; exit 1; }Done when: the branch passes the channel-prefix check or the run stops with
Not a release branch. -
Preview the mutation: state
INTERNAL_REPO,$RC_WORKFLOW_NAME,$BRANCH_NAME, and the consequence, a release-candidate build starts on that branch and one status notification is posted. Proceed only on the user's explicit invocation. Done when: the mutation preview is stated and the user explicitly invokes the run. -
Enter the repo context:
cd "$REPO_DIR". IfREPO_DIRis unset or the path does not exist, ask the user for the local path to the release repo checkout andcdthere; stop if none is given. Done when: the working directory is inside the release repo checkout. -
Confirm the branch exists on origin before dispatching:
git fetch origin git ls-remote --exit-code --heads origin "$BRANCH_NAME" >/dev/nullDone when: the branch is confirmed to exist on origin.
-
Dispatch the workflow by name on the branch ref. Record the UTC dispatch timestamp immediately before dispatching; step 6 uses it to tell this dispatch's run from the previous one:
DISPATCH_TS=$(date -u +%Y-%m-%dT%H:%M:%SZ) gh workflow run "$RC_WORKFLOW_NAME" --repo "$INTERNAL_REPO" --ref "$BRANCH_NAME"Done when: the workflow dispatch exits zero and the dispatch timestamp is recorded.
-
Fetch this dispatch's run and share its
url,status, andconclusion; do not watch or wait for completion. A run list taken right after dispatch can still show the previous run, so poll until the newest run'screatedAtis at or after the dispatch timestamp (ISO-8601 UTC strings compare lexicographically), up to ten tries ten seconds apart:RUN_JSON="" for i in $(seq 1 10); do RUN_JSON=$(gh run list \ --repo "$INTERNAL_REPO" \ --workflow "$RC_WORKFLOW_NAME" \ --branch "$BRANCH_NAME" \ --limit 1 \ --json url,status,conclusion,createdAt \ --jq '.[0] // empty') CREATED=$(jq -r '.createdAt // empty' <<<"$RUN_JSON") if [ -n "$CREATED" ] && [ ! "$CREATED" \< "$DISPATCH_TS" ]; then break fi RUN_JSON="" sleep 10 done RUN_URL=$(jq -r '.url // empty' <<<"$RUN_JSON")Guards:
// emptykeeps an empty run list from printing the literalnull, which would otherwise pass-nand compare greater than any timestamp; the! ... \<comparison accepts a run created in the same second as the dispatch. A run whosecreatedAtpredates the dispatch timestamp is the previous run, not this one. After the loop, verifyRUN_URLis non-empty and notnullbefore posting anything: an empty ornullURL means this dispatch's run never appeared, which is the "Dispatched but no run URL" failure below, never a notification. Done when: the URL,status, andconclusionfor this dispatch's run are fetched and shared. -
Post the status notification carrying the branch name and run URL. Use the destination the user named. If the user gave no destination, stop and ask for one. Send the notification through the configured endpoint:
if [ -z "$RUN_URL" ] || [ "$RUN_URL" = "null" ]; then printf 'Blocked: no run URL for workflow %s on branch %s after dispatch at %s\n' \ "$RC_WORKFLOW_NAME" "$BRANCH_NAME" "$DISPATCH_TS" >&2 exit 1 fi JSON=$(jq -n --arg destination "$DESTINATION" --arg wf "$RC_WORKFLOW_NAME" --arg br "$BRANCH_NAME" --arg url "$RUN_URL" '{destination: $destination, text: ("Triggered " + $wf + " for " + $br + ".\nRun: " + $url)}') curl -s -X POST "$NOTIFICATION_ENDPOINT" \ -H "Authorization: Bearer $NOTIFICATION_TOKEN" \ -H "Content-type: application/json; charset=utf-8" \ -d "$JSON"Require a success response from the notification API. Done when: the notification post returns success.
Failure and recovery
- Non-release branch: the prefix check in step 1 exits, stop before any remote call, report
Not a release branch: $BRANCH_NAME, and ask for a release branch. Nothing was mutated. - Missing repo context:
REPO_DIRis unset or missing and the user supplies no checkout path, stop; nothing was mutated. - Branch absent on origin:
git ls-remote --exit-codeexits non-zero, do not dispatch; report the branch was not found onorigin, ask the user to confirm the exact branch name, and re-run step 4. ghauthentication failure: the dispatch or run query fails with an auth error, direct the user togh auth statusandgh auth login, and retry the failed step after they authenticate.- Dispatched but no run URL: the run query returns nothing or a null
url, never re-dispatch, because a second dispatch cuts a duplicate release candidate; report the workflow name, branch, and missing URL, and classify blocked for manual inspection. - Notification post fails: the dispatch and run URL still stand; report the partial result, fix the destination or
NOTIFICATION_TOKEN, and repost. Done is not claimed until the post succeeds.
Report partial results exactly: name which of dispatch, run URL, and notification post landed. Never swallow an error or claim done while any of the three is missing.
Output
A report naming the branch, the workflow name, the run URL, the queried status and conclusion at fetch time (completion is not awaited), the notification destination posted, and the exact message text. Terminal classification: done only when the dispatch exited zero, the run URL is non-null, and the notification response was success; otherwise blocked with the failing step and the partial state.
Signals
- GitHub stars
- 52
- Forks
- 9
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
cut-new-release-candidate- Source
- github.com/outlinedriven/outline-driven-development