gh-workflow release (#41502)
Closes #ISSUE Rewrite our release pipeline to be generated by `gh-workflow` Release Notes: - N/A *or* Added/Fixed/Improved ...
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
use gh_workflow::{Event, Expression, Push, Run, Step, Use, Workflow};
|
||||
|
||||
use crate::tasks::workflows::{
|
||||
run_bundling, run_tests, runners,
|
||||
steps::{self, NamedJob, dependant_job, named, release_job},
|
||||
vars,
|
||||
};
|
||||
|
||||
pub(crate) fn release() -> Workflow {
|
||||
let macos_tests = run_tests::run_platform_tests(runners::Platform::Mac);
|
||||
let linux_tests = run_tests::run_platform_tests(runners::Platform::Linux);
|
||||
let windows_tests = run_tests::run_platform_tests(runners::Platform::Windows);
|
||||
let check_scripts = run_tests::check_scripts();
|
||||
|
||||
let create_draft_release = create_draft_release();
|
||||
|
||||
let bundle = ReleaseBundleJobs {
|
||||
linux_arm64: bundle_linux_arm64(&[&linux_tests, &check_scripts]),
|
||||
linux_x86_64: bundle_linux_x86_64(&[&linux_tests, &check_scripts]),
|
||||
mac_arm64: bundle_mac_arm64(&[&macos_tests, &check_scripts]),
|
||||
mac_x86_64: bundle_mac_x86_64(&[&macos_tests, &check_scripts]),
|
||||
windows_arm64: bundle_windows_arm64(&[&windows_tests, &check_scripts]),
|
||||
windows_x86_64: bundle_windows_x86_64(&[&windows_tests, &check_scripts]),
|
||||
};
|
||||
|
||||
let upload_release_assets = upload_release_assets(&[&create_draft_release], &bundle);
|
||||
|
||||
let auto_release_preview = auto_release_preview(&[&upload_release_assets]);
|
||||
|
||||
named::workflow()
|
||||
.on(Event::default().push(Push::default().tags(vec!["v*".to_string()])))
|
||||
.concurrency(vars::one_workflow_per_non_main_branch())
|
||||
.add_job(macos_tests.name, macos_tests.job)
|
||||
.add_job(linux_tests.name, linux_tests.job)
|
||||
.add_job(windows_tests.name, windows_tests.job)
|
||||
.add_job(check_scripts.name, check_scripts.job)
|
||||
.add_job(create_draft_release.name, create_draft_release.job)
|
||||
.add_job(bundle.linux_arm64.name, bundle.linux_arm64.job)
|
||||
.add_job(bundle.linux_x86_64.name, bundle.linux_x86_64.job)
|
||||
.add_job(bundle.mac_arm64.name, bundle.mac_arm64.job)
|
||||
.add_job(bundle.mac_x86_64.name, bundle.mac_x86_64.job)
|
||||
.add_job(bundle.windows_arm64.name, bundle.windows_arm64.job)
|
||||
.add_job(bundle.windows_x86_64.name, bundle.windows_x86_64.job)
|
||||
.add_job(upload_release_assets.name, upload_release_assets.job)
|
||||
.add_job(auto_release_preview.name, auto_release_preview.job)
|
||||
}
|
||||
|
||||
fn auto_release_preview(deps: &[&NamedJob; 1]) -> NamedJob {
|
||||
named::job(
|
||||
dependant_job(deps)
|
||||
.runs_on(runners::LINUX_SMALL)
|
||||
.cond(Expression::new(indoc::indoc!(
|
||||
r#"
|
||||
false
|
||||
&& startsWith(github.ref, 'refs/tags/v')
|
||||
&& endsWith(github.ref, '-pre') && !endsWith(github.ref, '.0-pre')
|
||||
"# // todo(ci-release) enable
|
||||
)))
|
||||
.add_step(
|
||||
steps::script(
|
||||
r#"gh release edit "$GITHUB_REF_NAME" --repo=zed-industries/zed --draft=false"#,
|
||||
)
|
||||
.add_env(("GITHUB_TOKEN", "${{ secrets.GITHUB_TOKEN }}")),
|
||||
)
|
||||
.add_step(create_sentry_release()),
|
||||
)
|
||||
}
|
||||
|
||||
fn create_sentry_release() -> Step<Use> {
|
||||
named::uses(
|
||||
"getsentry",
|
||||
"action-release",
|
||||
"526942b68292201ac6bbb99b9a0747d4abee354c", // v3
|
||||
)
|
||||
.add_env(("SENTRY_ORG", "zed-dev"))
|
||||
.add_env(("SENTRY_PROJECT", "zed"))
|
||||
.add_env(("SENTRY_AUTH_TOKEN", "${{ secrets.SENTRY_AUTH_TOKEN }}"))
|
||||
.add_with(("environment", "production"))
|
||||
}
|
||||
|
||||
struct ReleaseBundleJobs {
|
||||
linux_arm64: NamedJob,
|
||||
linux_x86_64: NamedJob,
|
||||
mac_arm64: NamedJob,
|
||||
mac_x86_64: NamedJob,
|
||||
windows_arm64: NamedJob,
|
||||
windows_x86_64: NamedJob,
|
||||
}
|
||||
|
||||
fn upload_release_assets(deps: &[&NamedJob], bundle_jobs: &ReleaseBundleJobs) -> NamedJob {
|
||||
fn download_workflow_artifacts() -> Step<Use> {
|
||||
named::uses(
|
||||
"actions",
|
||||
"download-artifact",
|
||||
"018cc2cf5baa6db3ef3c5f8a56943fffe632ef53", // v6.0.0
|
||||
)
|
||||
.add_with(("path", "./artifacts/"))
|
||||
}
|
||||
|
||||
fn prep_release_artifacts(bundle: &ReleaseBundleJobs) -> Step<Run> {
|
||||
let assets = [
|
||||
(&bundle.mac_x86_64.name, "zed", "Zed-x86_64.dmg"),
|
||||
(&bundle.mac_arm64.name, "zed", "Zed-aarch64.dmg"),
|
||||
(&bundle.windows_x86_64.name, "zed", "Zed-x86_64.exe"),
|
||||
(&bundle.windows_arm64.name, "zed", "Zed-aarch64.exe"),
|
||||
(&bundle.linux_arm64.name, "zed", "zed-linux-aarch64.tar.gz"),
|
||||
(&bundle.linux_x86_64.name, "zed", "zed-linux-x86_64.tar.gz"),
|
||||
(
|
||||
&bundle.linux_x86_64.name,
|
||||
"remote-server",
|
||||
"zed-remote-server-linux-x86_64.gz",
|
||||
),
|
||||
(
|
||||
&bundle.linux_arm64.name,
|
||||
"remote-server",
|
||||
"zed-remote-server-linux-aarch64.gz",
|
||||
),
|
||||
(
|
||||
&bundle.mac_x86_64.name,
|
||||
"remote-server",
|
||||
"zed-remote-server-macos-x86_64.gz",
|
||||
),
|
||||
(
|
||||
&bundle.mac_arm64.name,
|
||||
"remote-server",
|
||||
"zed-remote-server-macos-aarch64.gz",
|
||||
),
|
||||
];
|
||||
|
||||
let mut script_lines = vec!["mkdir -p release-artifacts/\n".to_string()];
|
||||
for (job_name, artifact_kind, release_artifact_name) in assets {
|
||||
let artifact_path =
|
||||
["${{ needs.", job_name, ".outputs.", artifact_kind, " }}"].join("");
|
||||
let mv_command = format!(
|
||||
"mv ./artifacts/{artifact_path}/* release-artifacts/{release_artifact_name}"
|
||||
);
|
||||
script_lines.push(mv_command)
|
||||
}
|
||||
|
||||
named::bash(&script_lines.join("\n"))
|
||||
}
|
||||
|
||||
let mut deps = deps.to_vec();
|
||||
deps.extend([
|
||||
&bundle_jobs.linux_arm64,
|
||||
&bundle_jobs.linux_x86_64,
|
||||
&bundle_jobs.mac_arm64,
|
||||
&bundle_jobs.mac_x86_64,
|
||||
&bundle_jobs.windows_arm64,
|
||||
&bundle_jobs.windows_x86_64,
|
||||
]);
|
||||
|
||||
named::job(
|
||||
dependant_job(&deps)
|
||||
.runs_on(runners::LINUX_MEDIUM)
|
||||
.add_step(download_workflow_artifacts())
|
||||
.add_step(steps::script("ls -lR ./artifacts"))
|
||||
.add_step(prep_release_artifacts(bundle_jobs))
|
||||
.add_step(
|
||||
steps::script("gh release upload \"$GITHUB_REF_NAME\" --repo=zed-industries/zed release-artifacts/*")
|
||||
.add_env(("GITHUB_TOKEN", "${{ secrets.GITHUB_TOKEN }}")),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn create_draft_release() -> NamedJob {
|
||||
named::job(
|
||||
release_job(&[])
|
||||
.runs_on(runners::LINUX_SMALL)
|
||||
// We need to fetch more than one commit so that `script/draft-release-notes`
|
||||
// is able to diff between the current and previous tag.
|
||||
//
|
||||
// 25 was chosen arbitrarily.
|
||||
.add_step(
|
||||
steps::checkout_repo()
|
||||
.add_with(("fetch-depth", 25))
|
||||
.add_with(("clean", false))
|
||||
.add_with(("ref", "${{ github.ref }}")),
|
||||
)
|
||||
.add_step(steps::script("script/determine-release-channel")) // export RELEASE_CHANNEL and RELEASE_VERSION
|
||||
.add_step(steps::script("mkdir -p target/"))
|
||||
.add_step(steps::script(r#"script/draft-release-notes "$RELEASE_VERSION" "$RELEASE_CHANNEL" > target/release-notes.md || true"#))
|
||||
.add_step(steps::script("script/create-draft-release target/release-notes.md")),
|
||||
)
|
||||
}
|
||||
|
||||
fn bundle_mac_x86_64(deps: &[&NamedJob]) -> NamedJob {
|
||||
named::job(run_bundling::bundle_mac_job(runners::Arch::X86_64, deps))
|
||||
}
|
||||
fn bundle_mac_arm64(deps: &[&NamedJob]) -> NamedJob {
|
||||
named::job(run_bundling::bundle_mac_job(runners::Arch::ARM64, deps))
|
||||
}
|
||||
fn bundle_linux_x86_64(deps: &[&NamedJob]) -> NamedJob {
|
||||
named::job(run_bundling::bundle_linux_job(runners::Arch::X86_64, deps))
|
||||
}
|
||||
fn bundle_linux_arm64(deps: &[&NamedJob]) -> NamedJob {
|
||||
named::job(run_bundling::bundle_linux_job(runners::Arch::ARM64, deps))
|
||||
}
|
||||
fn bundle_windows_x86_64(deps: &[&NamedJob]) -> NamedJob {
|
||||
named::job(run_bundling::bundle_windows_job(
|
||||
runners::Arch::X86_64,
|
||||
deps,
|
||||
))
|
||||
}
|
||||
fn bundle_windows_arm64(deps: &[&NamedJob]) -> NamedJob {
|
||||
named::job(run_bundling::bundle_windows_job(runners::Arch::ARM64, deps))
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
use crate::tasks::workflows::{
|
||||
steps::{FluentBuilder, named},
|
||||
steps::{FluentBuilder, NamedJob, dependant_job, named},
|
||||
vars::{mac_bundle_envs, windows_bundle_envs},
|
||||
};
|
||||
|
||||
use super::{runners, steps, vars};
|
||||
use gh_workflow::*;
|
||||
use indexmap::IndexMap;
|
||||
|
||||
pub fn run_bundling() -> Workflow {
|
||||
named::workflow()
|
||||
@@ -22,32 +23,47 @@ pub fn run_bundling() -> Workflow {
|
||||
.add_env(("RUST_BACKTRACE", "1"))
|
||||
.add_env(("ZED_CLIENT_CHECKSUM_SEED", vars::ZED_CLIENT_CHECKSUM_SEED))
|
||||
.add_env(("ZED_MINIDUMP_ENDPOINT", vars::ZED_SENTRY_MINIDUMP_ENDPOINT))
|
||||
.add_job("bundle_mac_x86_64", bundle_mac_job(runners::Arch::X86_64))
|
||||
.add_job("bundle_mac_arm64", bundle_mac_job(runners::Arch::ARM64))
|
||||
.add_job("bundle_linux_x86_64", bundle_linux(runners::Arch::X86_64))
|
||||
.add_job("bundle_linux_arm64", bundle_linux(runners::Arch::ARM64))
|
||||
.add_job(
|
||||
"bundle_mac_x86_64",
|
||||
bundle_mac_job(runners::Arch::X86_64, &[]),
|
||||
)
|
||||
.add_job(
|
||||
"bundle_mac_arm64",
|
||||
bundle_mac_job(runners::Arch::ARM64, &[]),
|
||||
)
|
||||
.add_job(
|
||||
"bundle_linux_x86_64",
|
||||
bundle_linux_job(runners::Arch::X86_64, &[]),
|
||||
)
|
||||
.add_job(
|
||||
"bundle_linux_arm64",
|
||||
bundle_linux_job(runners::Arch::ARM64, &[]),
|
||||
)
|
||||
.add_job(
|
||||
"bundle_windows_x86_64",
|
||||
bundle_windows_job(runners::Arch::X86_64),
|
||||
bundle_windows_job(runners::Arch::X86_64, &[]),
|
||||
)
|
||||
.add_job(
|
||||
"bundle_windows_arm64",
|
||||
bundle_windows_job(runners::Arch::ARM64),
|
||||
bundle_windows_job(runners::Arch::ARM64, &[]),
|
||||
)
|
||||
}
|
||||
|
||||
fn bundle_job() -> Job {
|
||||
Job::default()
|
||||
.cond(Expression::new(
|
||||
fn bundle_job(deps: &[&NamedJob]) -> Job {
|
||||
dependant_job(deps)
|
||||
.when(deps.len() == 0, |job|
|
||||
job.cond(Expression::new(
|
||||
"(github.event.action == 'labeled' && github.event.label.name == 'run-bundling') ||
|
||||
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'run-bundling'))",
|
||||
))
|
||||
)))
|
||||
.timeout_minutes(60u32)
|
||||
}
|
||||
|
||||
fn bundle_mac_job(arch: runners::Arch) -> Job {
|
||||
pub(crate) fn bundle_mac_job(arch: runners::Arch, deps: &[&NamedJob]) -> Job {
|
||||
use vars::GITHUB_SHA;
|
||||
bundle_job()
|
||||
let artifact_name = format!("Zed_{GITHUB_SHA}-{arch}.dmg");
|
||||
let remote_server_artifact_name = format!("zed-remote-server-{GITHUB_SHA}-macos-{arch}.gz");
|
||||
bundle_job(deps)
|
||||
.runs_on(runners::MAC_DEFAULT)
|
||||
.envs(mac_bundle_envs())
|
||||
.add_step(steps::checkout_repo())
|
||||
@@ -56,27 +72,35 @@ fn bundle_mac_job(arch: runners::Arch) -> Job {
|
||||
.add_step(steps::clear_target_dir_if_large(runners::Platform::Mac))
|
||||
.add_step(bundle_mac(arch))
|
||||
.add_step(steps::upload_artifact(
|
||||
&format!("Zed_{GITHUB_SHA}-{arch}.dmg"),
|
||||
&artifact_name,
|
||||
&format!("target/{arch}-apple-darwin/release/Zed.dmg"),
|
||||
))
|
||||
.add_step(steps::upload_artifact(
|
||||
&format!("zed-remote-server-{GITHUB_SHA}-macos-{arch}.gz"),
|
||||
&remote_server_artifact_name,
|
||||
&format!("target/zed-remote-server-macos-{arch}.gz"),
|
||||
))
|
||||
.outputs(
|
||||
[
|
||||
("zed".to_string(), artifact_name),
|
||||
("remote-server".to_string(), remote_server_artifact_name),
|
||||
]
|
||||
.into_iter()
|
||||
.collect::<IndexMap<_, _>>(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn bundle_mac(arch: runners::Arch) -> Step<Run> {
|
||||
named::bash(&format!("./script/bundle-mac {arch}-apple-darwin"))
|
||||
}
|
||||
|
||||
fn bundle_linux(arch: runners::Arch) -> Job {
|
||||
pub(crate) fn bundle_linux_job(arch: runners::Arch, deps: &[&NamedJob]) -> Job {
|
||||
let artifact_name = format!("zed-{}-{}.tar.gz", vars::GITHUB_SHA, arch.triple());
|
||||
let remote_server_artifact_name = format!(
|
||||
"zed-remote-server-{}-{}.tar.gz",
|
||||
vars::GITHUB_SHA,
|
||||
arch.triple()
|
||||
);
|
||||
bundle_job()
|
||||
bundle_job(deps)
|
||||
.runs_on(arch.linux_bundler())
|
||||
.add_step(steps::checkout_repo())
|
||||
.add_step(steps::setup_sentry())
|
||||
@@ -88,22 +112,36 @@ fn bundle_linux(arch: runners::Arch) -> Job {
|
||||
))
|
||||
.add_step(steps::upload_artifact(
|
||||
&remote_server_artifact_name,
|
||||
"target/release/zed-remote-server-*.tar.gz",
|
||||
"target/zed-remote-server-*.gz",
|
||||
))
|
||||
.outputs(
|
||||
[
|
||||
("zed".to_string(), artifact_name),
|
||||
("remote-server".to_string(), remote_server_artifact_name),
|
||||
]
|
||||
.into_iter()
|
||||
.collect::<IndexMap<_, _>>(),
|
||||
)
|
||||
}
|
||||
|
||||
fn bundle_windows_job(arch: runners::Arch) -> Job {
|
||||
pub(crate) fn bundle_windows_job(arch: runners::Arch, deps: &[&NamedJob]) -> Job {
|
||||
use vars::GITHUB_SHA;
|
||||
bundle_job()
|
||||
let artifact_name = format!("Zed_{GITHUB_SHA}-{arch}.exe");
|
||||
bundle_job(deps)
|
||||
.runs_on(runners::WINDOWS_DEFAULT)
|
||||
.envs(windows_bundle_envs())
|
||||
.add_step(steps::checkout_repo())
|
||||
.add_step(steps::setup_sentry())
|
||||
.add_step(bundle_windows(arch))
|
||||
.add_step(steps::upload_artifact(
|
||||
&format!("Zed_{GITHUB_SHA}-{arch}.exe"),
|
||||
&artifact_name,
|
||||
"${{ env.SETUP_PATH }}",
|
||||
))
|
||||
.outputs(
|
||||
[("zed".to_string(), artifact_name)]
|
||||
.into_iter()
|
||||
.collect::<IndexMap<_, _>>(),
|
||||
)
|
||||
}
|
||||
|
||||
fn bundle_windows(arch: runners::Arch) -> Step<Run> {
|
||||
|
||||
@@ -302,9 +302,6 @@ pub(crate) fn run_platform_tests(platform: Platform) -> NamedJob {
|
||||
NamedJob {
|
||||
name: format!("run_tests_{platform}"),
|
||||
job: release_job(&[])
|
||||
.cond(Expression::new(
|
||||
"github.repository_owner == 'zed-industries'",
|
||||
))
|
||||
.runs_on(runner)
|
||||
.add_step(steps::checkout_repo())
|
||||
.add_step(steps::setup_cargo_config(platform))
|
||||
@@ -436,7 +433,7 @@ fn check_docs() -> NamedJob {
|
||||
)
|
||||
}
|
||||
|
||||
fn check_scripts() -> NamedJob {
|
||||
pub(crate) fn check_scripts() -> NamedJob {
|
||||
fn download_actionlint() -> Step<Run> {
|
||||
named::bash(
|
||||
"bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)",
|
||||
|
||||
@@ -95,6 +95,7 @@ pub fn upload_artifact(name: &str, path: &str) -> Step<Use> {
|
||||
)
|
||||
.add_with(("name", name))
|
||||
.add_with(("path", path))
|
||||
.add_with(("if-no-files-found", "error"))
|
||||
}
|
||||
|
||||
pub fn clear_target_dir_if_large(platform: Platform) -> Step<Run> {
|
||||
@@ -156,11 +157,15 @@ pub(crate) struct NamedJob {
|
||||
// }
|
||||
|
||||
pub(crate) fn release_job(deps: &[&NamedJob]) -> Job {
|
||||
let job = Job::default()
|
||||
dependant_job(deps)
|
||||
.cond(Expression::new(
|
||||
"github.repository_owner == 'zed-industries'",
|
||||
))
|
||||
.timeout_minutes(60u32);
|
||||
.timeout_minutes(60u32)
|
||||
}
|
||||
|
||||
pub(crate) fn dependant_job(deps: &[&NamedJob]) -> Job {
|
||||
let job = Job::default();
|
||||
if deps.len() > 0 {
|
||||
job.needs(deps.iter().map(|j| j.name.clone()).collect::<Vec<_>>())
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::cell::RefCell;
|
||||
|
||||
use gh_workflow::{Env, Expression};
|
||||
use gh_workflow::{Concurrency, Env, Expression};
|
||||
|
||||
use crate::tasks::workflows::steps::NamedJob;
|
||||
|
||||
@@ -62,6 +62,12 @@ pub fn windows_bundle_envs() -> Env {
|
||||
.add("TIMESTAMP_SERVER", "http://timestamp.acs.microsoft.com")
|
||||
}
|
||||
|
||||
pub(crate) fn one_workflow_per_non_main_branch() -> Concurrency {
|
||||
Concurrency::default()
|
||||
.group("${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}")
|
||||
.cancel_in_progress(true)
|
||||
}
|
||||
|
||||
// Represents a pattern to check for changed files and corresponding output variable
|
||||
pub(crate) struct PathCondition {
|
||||
pub name: &'static str,
|
||||
|
||||
Reference in New Issue
Block a user