Enforce adding a message to extension CLI bumps (#58786)

This slightly reworks the extension CLI bump workflow - instead of
triggering on label push, it now triggers on workflow dispatch with a
message enforced to be added there.

This primarily allows us to add a message to these bumps to better
communicate what changes with that version of the CLI. Furthermore, we
can soon restrict the label to be only created by that workflow, which
has the advantage that it can only be based off of main. Also, it has
the nice side-effect that we actually only ever update the label if
everything worked properly.

Release Notes:

- N/A
This commit is contained in:
Finn Evers 2026-06-11 01:51:59 +02:00 committed by GitHub
parent 620ceaaaca
commit 511d197477
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 142 additions and 35 deletions

View file

@ -5,12 +5,15 @@ env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: '0'
on:
push:
tags:
- extension-cli
workflow_dispatch:
inputs:
message:
description: Describe why the extension CLI is being bumped and/or what changes are included.
required: true
type: string
jobs:
publish_job:
if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions')
if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions') && github.ref == 'refs/heads/main'
runs-on: namespace-profile-16x32-ubuntu-2204
steps:
- name: steps::checkout_repo
@ -31,10 +34,29 @@ jobs:
env:
DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
- id: generate-token
name: steps::authenticate_as_zippy
uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859
with:
app-id: ${{ secrets.ZED_ZIPPY_APP_ID }}
private-key: ${{ secrets.ZED_ZIPPY_APP_PRIVATE_KEY }}
permission-contents: write
- name: steps::update_tag
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b
with:
script: |
github.rest.git.updateRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: 'tags/extension-cli',
sha: context.sha,
force: true
})
github-token: ${{ steps.generate-token.outputs.token }}
update_sha_in_zed:
needs:
- publish_job
if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions')
if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions') && github.ref == 'refs/heads/main'
runs-on: namespace-profile-8x16-ubuntu-2204
steps:
- id: generate-token
@ -69,6 +91,8 @@ jobs:
body: |
This PR bumps the extension CLI version used in the extension workflows to `${{ github.sha }}`.
${{ inputs.message }}
Release Notes:
- N/A
@ -84,7 +108,7 @@ jobs:
update_sha_in_extensions:
needs:
- publish_job
if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions')
if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions') && github.ref == 'refs/heads/main'
runs-on: namespace-profile-2x4-ubuntu-2404
steps:
- id: generate-token
@ -114,6 +138,8 @@ jobs:
title: Bump extension CLI version to `${{ steps.short-sha.outputs.sha_short }}`
body: |
This PR bumps the extension CLI version to https://github.com/zed-industries/zed/commit/${{ github.sha }}.
${{ inputs.message }}
commit-message: Bump extension CLI version to `${{ steps.short-sha.outputs.sha_short }}`
branch: update-extension-cli-sha
committer: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>

View file

@ -1,7 +1,34 @@
#!/usr/bin/env bash
set -e
set -eu
git pull --ff-only origin main
git tag -f extension-cli
git push -f origin extension-cli
usage() {
echo "Usage: $0 <message>"
echo ""
echo "Triggers the publish_extension_cli workflow on main to build a new"
echo "extension CLI binary, bump the 'extension-cli' tag after a successful"
echo "build, and open PRs that update the SHA used by the zed and"
echo "zed-industries/extensions repositories."
echo ""
echo "Arguments:"
echo " message Describes why the extension CLI is being bumped /"
echo " what the changes include. Included in the PR bodies."
exit 1
}
if [[ $# -lt 1 || -z "${1:-}" ]]; then
echo "error: a message describing the bump is required" >&2
echo "" >&2
usage >&2
fi
which gh > /dev/null 2>&1 || {
echo "error: GitHub CLI (gh) is required but not installed." >&2
echo "Install it with: brew install gh" >&2
exit 1
}
gh workflow run publish_extension_cli.yml --ref main -f message="$1"
echo "Workflow triggered. Monitor progress at:"
echo " https://github.com/zed-industries/zed/actions/workflows/publish_extension_cli.yml"

View file

@ -1,19 +1,30 @@
use gh_workflow::*;
use indoc::indoc;
use indoc::{formatdoc, indoc};
use crate::tasks::workflows::{
runners,
steps::{self, CommonJobConditions, NamedJob, RepositoryTarget, generate_token, named},
vars::{self, StepOutput},
steps::{
self, DEFAULT_REPOSITORY_OWNER_GUARD, GitRef, NamedJob, RefSha, RepositoryTarget,
TokenPermissions, generate_token, named,
},
vars::{self, StepOutput, WorkflowInput},
};
const EXTENSION_CLI_TAG: &str = "extension-cli";
pub fn publish_extension_cli() -> Workflow {
let message = WorkflowInput::string("message", None).description(
"Describe why the extension CLI is being bumped and/or what changes are included.",
);
let publish = publish_job();
let update_sha_in_zed = update_sha_in_zed(&publish);
let update_sha_in_extensions = update_sha_in_extensions(&publish);
let update_sha_in_zed = update_sha_in_zed(&publish, &message);
let update_sha_in_extensions = update_sha_in_extensions(&publish, &message);
named::workflow()
.on(Event::default().push(Push::default().tags(vec!["extension-cli".to_string()])))
.on(Event::default().workflow_dispatch(
WorkflowDispatch::default().add_input(message.name, message.input()),
))
.add_env(("CARGO_TERM_COLOR", "always"))
.add_env(("CARGO_INCREMENTAL", 0))
.add_job(publish.name, publish.job)
@ -21,6 +32,16 @@ pub fn publish_extension_cli() -> Workflow {
.add_job(update_sha_in_extensions.name, update_sha_in_extensions.job)
}
// `workflow_dispatch` can be triggered from any branch where this workflow file
// exists, so we additionally guard the jobs to only run when dispatched from
// `main`. Jobs that depend on `publish_job` inherit this guard transitively
// because they are skipped when `publish_job` is skipped.
fn dispatched_from_main_guard() -> Expression {
Expression::new(format!(
"{DEFAULT_REPOSITORY_OWNER_GUARD} && github.ref == 'refs/heads/main'"
))
}
fn publish_job() -> NamedJob {
fn build_extension_cli() -> Step<Run> {
named::bash("cargo build --release --package extension_cli")
@ -38,19 +59,31 @@ fn publish_job() -> NamedJob {
))
}
let (authenticate, token) = steps::authenticate_as_zippy()
.for_repository(RepositoryTarget::current())
.with_permissions([(TokenPermissions::Contents, Level::Write)])
.into();
named::job(
Job::default()
.with_repository_owner_guard()
.cond(dispatched_from_main_guard())
.runs_on(runners::LINUX_DEFAULT)
.add_step(steps::checkout_repo())
.add_step(steps::cache_rust_dependencies_namespace())
.add_step(steps::setup_linux())
.add_step(build_extension_cli())
.add_step(upload_binary()),
.add_step(upload_binary())
.add_step(authenticate)
.add_step(steps::update_ref(
GitRef::tag(EXTENSION_CLI_TAG),
RefSha::Context,
&token,
true,
)),
)
}
fn update_sha_in_zed(publish_job: &NamedJob) -> NamedJob {
fn update_sha_in_zed(publish_job: &NamedJob, message: &WorkflowInput) -> NamedJob {
let (generate_token, generated_token) =
generate_token(vars::ZED_ZIPPY_APP_ID, vars::ZED_ZIPPY_APP_PRIVATE_KEY).into();
@ -69,7 +102,7 @@ fn update_sha_in_zed(publish_job: &NamedJob) -> NamedJob {
named::job(
Job::default()
.with_repository_owner_guard()
.cond(dispatched_from_main_guard())
.needs(vec![publish_job.name.clone()])
.runs_on(runners::LINUX_LARGE)
.add_step(generate_token)
@ -78,28 +111,40 @@ fn update_sha_in_zed(publish_job: &NamedJob) -> NamedJob {
.add_step(get_short_sha_step)
.add_step(replace_sha())
.add_step(regenerate_workflows())
.add_step(create_pull_request_zed(&generated_token, &short_sha)),
.add_step(create_pull_request_zed(
&generated_token,
&short_sha,
message,
)),
)
}
fn create_pull_request_zed(generated_token: &StepOutput, short_sha: &StepOutput) -> Step<Use> {
fn create_pull_request_zed(
generated_token: &StepOutput,
short_sha: &StepOutput,
message: &WorkflowInput,
) -> Step<Use> {
let title = format!(
"extension_ci: Bump extension CLI version to `{}`",
short_sha
);
let body = formatdoc! {r#"
This PR bumps the extension CLI version used in the extension workflows to `${{{{ github.sha }}}}`.
{message}
Release Notes:
- N/A
"#};
steps::CreatePrStep::new(title, "update-extension-cli-sha", generated_token)
.with_body(indoc::indoc! {r#"
This PR bumps the extension CLI version used in the extension workflows to `${{ github.sha }}`.
Release Notes:
- N/A
"#})
.with_body(body)
.into()
}
fn update_sha_in_extensions(publish_job: &NamedJob) -> NamedJob {
fn update_sha_in_extensions(publish_job: &NamedJob, message: &WorkflowInput) -> NamedJob {
let extensions_repo = RepositoryTarget::new("zed-industries", &["extensions"]);
let (generate_token, generated_token) =
generate_token(vars::ZED_ZIPPY_APP_ID, vars::ZED_ZIPPY_APP_PRIVATE_KEY)
@ -127,27 +172,36 @@ fn update_sha_in_extensions(publish_job: &NamedJob) -> NamedJob {
named::job(
Job::default()
.with_repository_owner_guard()
.cond(dispatched_from_main_guard())
.needs(vec![publish_job.name.clone()])
.runs_on(runners::LINUX_SMALL)
.add_step(generate_token)
.add_step(get_short_sha_step)
.add_step(checkout_extensions_repo(&generated_token))
.add_step(replace_sha())
.add_step(create_pull_request_extensions(&generated_token, &short_sha)),
.add_step(create_pull_request_extensions(
&generated_token,
&short_sha,
message,
)),
)
}
fn create_pull_request_extensions(
generated_token: &StepOutput,
short_sha: &StepOutput,
message: &WorkflowInput,
) -> Step<Use> {
let title = format!("Bump extension CLI version to `{}`", short_sha);
let body = formatdoc! {r#"
This PR bumps the extension CLI version to https://github.com/zed-industries/zed/commit/${{{{ github.sha }}}}.
{message}
"#};
steps::CreatePrStep::new(title, "update-extension-cli-sha", generated_token)
.with_body(indoc::indoc! {r#"
This PR bumps the extension CLI version to https://github.com/zed-industries/zed/commit/${{ github.sha }}.
"#})
.with_body(body)
.with_labels("allow-no-extension")
.into()
}