299 lines · 10.7 KB · Rust
RawDownload
use gh_workflow::*; use crate::tasks::workflows::{    runners,    steps::{self, CommonPermissionSets, named},    vars::{self, StepOutput, WorkflowInput},}; pub fn bump_zed_version() -> Workflow {    let target = WorkflowInput::string("target", Some("all".to_string()))        .description("Which channels to bump: all, main, preview, or stable");     let (versions_job, outputs) = resolve_versions();     let bump_main_job = bump_main(&target, &versions_job, &outputs);    let preview_job = create_preview_branch(&target, &versions_job, &outputs);    let stable_job = promote_to_stable(&target, &versions_job, &outputs);     named::workflow()        .with_minimal_permissions()        .on(Event::default()            .workflow_dispatch(WorkflowDispatch::default().add_input(target.name, target.input())))        .add_job(versions_job.name, versions_job.job)        .add_job(bump_main_job.name, bump_main_job.job)        .add_job(preview_job.name, preview_job.job)        .add_job(stable_job.name, stable_job.job)} struct ResolvedOutputs {    next_version: vars::JobOutput,    pr_branch: vars::JobOutput,    preview_branch: vars::JobOutput,    preview_tag: vars::JobOutput,    stable_branch: vars::JobOutput,} fn resolve_versions() -> (steps::NamedJob, ResolvedOutputs) {    fn extract_versions() -> Step<Run> {        named::bash(indoc::indoc! {r#"            version=$(script/get-crate-version zed)            major=$(echo "$version" | cut -d. -f1)            minor=$(echo "$version" | cut -d. -f2)             channel=$(cat crates/zed/RELEASE_CHANNEL)            if [[ "$channel" != "dev" && "$channel" != "nightly" ]]; then                echo "::error::release channel on main should be dev or nightly, found: $channel"                exit 1            fi             # Next main version after bump            next_version="${major}.$((minor + 1)).0"            next_major=$(echo "$next_version" | cut -d. -f1)            next_minor=$(echo "$next_version" | cut -d. -f2)            pr_branch="bump-zed-to-v${next_major}.${next_minor}.0"             # New preview branch from current main            preview_branch="v${major}.${minor}.x"            preview_tag="v${version}-pre"             # Current preview to promote to stable — derive branch from released preview version            released_preview=$(script/get-released-version preview)            if [[ -z "$released_preview" ]]; then                echo "::error::could not determine released preview version"                exit 1            fi            stable_major=$(echo "$released_preview" | cut -d. -f1)            stable_minor=$(echo "$released_preview" | cut -d. -f2)            stable_branch="v${stable_major}.${stable_minor}.x"             # Final validation            for var in next_version pr_branch preview_branch preview_tag stable_branch; do                if [[ -z "${!var}" ]]; then                    echo "::error::failed to compute $var"                    exit 1                fi            done             {                echo "next_version=$next_version"                echo "pr_branch=$pr_branch"                echo "preview_branch=$preview_branch"                echo "preview_tag=$preview_tag"                echo "stable_branch=$stable_branch"            } >> "$GITHUB_OUTPUT"             echo "Resolved: next=$next_version preview=$preview_branch($preview_tag) stable=$stable_branch pr=$pr_branch"        "#})        .id("versions")    }     let (authenticate, token) = steps::authenticate_as_zippy()        .for_repository(steps::RepositoryTarget::current())        .with_permissions([(steps::TokenPermissions::Contents, Level::Read)])        .into();    let versions_step = extract_versions();    let next_version = StepOutput::new(&versions_step, "next_version");    let pr_branch = StepOutput::new(&versions_step, "pr_branch");    let preview_branch = StepOutput::new(&versions_step, "preview_branch");    let preview_tag = StepOutput::new(&versions_step, "preview_tag");    let stable_branch = StepOutput::new(&versions_step, "stable_branch");     let job = named::job(        Job::default()            .cond(Expression::new(                "github.repository_owner == 'zed-industries'",            ))            .runs_on(runners::LINUX_XL)            .add_step(authenticate)            .add_step(steps::checkout_repo().with_token(&token).with_ref("main"))            .add_step(versions_step)            .outputs([                (next_version.name.to_owned(), next_version.to_string()),                (pr_branch.name.to_owned(), pr_branch.to_string()),                (preview_branch.name.to_owned(), preview_branch.to_string()),                (preview_tag.name.to_owned(), preview_tag.to_string()),                (stable_branch.name.to_owned(), stable_branch.to_string()),            ]),    );     let outputs = ResolvedOutputs {        next_version: next_version.as_job_output(&job),        pr_branch: pr_branch.as_job_output(&job),        preview_branch: preview_branch.as_job_output(&job),        preview_tag: preview_tag.as_job_output(&job),        stable_branch: stable_branch.as_job_output(&job),    };     (job, outputs)} fn bump_main(    target: &WorkflowInput,    versions_job: &steps::NamedJob,    outputs: &ResolvedOutputs,) -> steps::NamedJob {    fn bump_version() -> Step<Run> {        named::bash("cargo set-version -p zed --bump minor")    }     let (authenticate, token) = steps::authenticate_as_zippy()        .for_repository(steps::RepositoryTarget::current())        .with_permissions([            (steps::TokenPermissions::Contents, Level::Write),            (steps::TokenPermissions::PullRequests, Level::Write),        ])        .into();     named::job(        Job::default()            .cond(Expression::new(format!(                "{} == 'all' || {} == 'main'",                target.expr(),                target.expr(),            )))            .permissions(                Permissions::default()                    .contents(Level::Write)                    .pull_requests(Level::Write),            )            .needs(vec![versions_job.name.clone()])            .runs_on(runners::LINUX_DEFAULT)            .add_step(authenticate)            .add_step(steps::checkout_repo().with_token(&token).with_ref("main"))            .add_step(steps::install_cargo_edit())            .add_step(bump_version())            .add_step(steps::CreatePrStep::new(                format!("Bump Zed to v{}", outputs.next_version),                &outputs.pr_branch,                &token,            )),    )} fn create_preview_branch(    target: &WorkflowInput,    versions_job: &steps::NamedJob,    outputs: &ResolvedOutputs,) -> steps::NamedJob {    fn promote_to_preview() -> Step<Run> {        named::bash("echo -n preview > crates/zed/RELEASE_CHANNEL")    }     fn get_main_sha() -> Step<Run> {        named::bash("echo \"main_sha=$(git rev-parse HEAD)\" >> \"$GITHUB_OUTPUT\"").id("main-sha")    }     let (authenticate, token) = steps::authenticate_as_zippy()        .for_repository(steps::RepositoryTarget::current())        .with_permissions([            (steps::TokenPermissions::Contents, Level::Write),            (steps::TokenPermissions::Workflows, Level::Write),        ])        .into();     let main_sha_step = get_main_sha();    let main_sha = StepOutput::new(&main_sha_step, "main_sha");     let commit_step: Step<Use> = steps::BotCommitStep::new(        format!(            "{} preview for @${{{{ github.actor }}}}",            outputs.preview_branch        ),        &outputs.preview_branch,        &token,    )    .with_files("crates/zed/RELEASE_CHANNEL")    .into();    let commit_sha = StepOutput::new_unchecked(&commit_step, "commit");     named::job(        Job::default()            .cond(Expression::new(format!(                "{} == 'all' || {} == 'preview'",                target.expr(),                target.expr(),            )))            .permissions(Permissions::default().contents(Level::Write))            .needs(vec![versions_job.name.clone()])            .runs_on(runners::LINUX_DEFAULT)            .add_step(authenticate)            .add_step(steps::checkout_repo().with_token(&token).with_ref("main"))            .add_step(main_sha_step)            .add_step(promote_to_preview())            .add_step(steps::create_ref(                steps::GitRef::branch(&outputs.preview_branch),                &main_sha,                &token,            ))            .add_step(commit_step)            .add_step(steps::create_ref(                steps::GitRef::tag(&outputs.preview_tag),                &commit_sha,                &token,            )),    )} fn promote_to_stable(    target: &WorkflowInput,    versions_job: &steps::NamedJob,    outputs: &ResolvedOutputs,) -> steps::NamedJob {    let (authenticate, token) = steps::authenticate_as_zippy()        .for_repository(steps::RepositoryTarget::current())        .with_permissions([            (steps::TokenPermissions::Contents, Level::Write),            (steps::TokenPermissions::Workflows, Level::Write),        ])        .into();     let read_version_step = named::bash(indoc::indoc! {r#"            stable_version=$(script/get-crate-version zed)            {                echo "stable_tag=v${stable_version}"            } >> "$GITHUB_OUTPUT"        "#})    .id("stable-info");    let stable_tag = StepOutput::new(&read_version_step, "stable_tag");     let write_channel = named::bash("echo -n stable > crates/zed/RELEASE_CHANNEL");     let commit_step: Step<Use> = steps::BotCommitStep::new(        format!(            "{} stable for @${{{{ github.actor }}}}",            outputs.stable_branch        ),        &outputs.stable_branch,        &token,    )    .with_files("crates/zed/RELEASE_CHANNEL")    .into();    let commit_sha = StepOutput::new_unchecked(&commit_step, "commit");     named::job(        Job::default()            .cond(Expression::new(format!(                "{} == 'all' || {} == 'stable'",                target.expr(),                target.expr(),            )))            .permissions(Permissions::default().contents(Level::Write))            .needs(vec![versions_job.name.clone()])            .runs_on(runners::LINUX_DEFAULT)            .add_step(authenticate)            .add_step(                steps::checkout_repo()                    .with_token(&token)                    .with_ref(outputs.stable_branch.to_string()),            )            .add_step(read_version_step)            .add_step(write_channel)            .add_step(commit_step)            .add_step(steps::create_ref(                steps::GitRef::tag(&stable_tag),                &commit_sha,                &token,            )),    )}