Add more workflows for extension repositories (#43924)
This PR adds workflows to be used for CD in extension reposiories in the `zed-extensions` organization and updates some of the existing ones with minor improvemts. Release Notes: - N/A
This commit is contained in:
@@ -1,14 +1,17 @@
|
||||
use anyhow::{Context, Result};
|
||||
use clap::Parser;
|
||||
use gh_workflow::Workflow;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
mod after_release;
|
||||
mod cherry_pick;
|
||||
mod compare_perf;
|
||||
mod danger;
|
||||
mod extension_bump;
|
||||
mod extension_release;
|
||||
mod extension_tests;
|
||||
mod extensions;
|
||||
mod nix_build;
|
||||
mod release_nightly;
|
||||
mod run_bundling;
|
||||
@@ -23,44 +26,112 @@ mod vars;
|
||||
#[derive(Parser)]
|
||||
pub struct GenerateWorkflowArgs {}
|
||||
|
||||
struct WorkflowFile {
|
||||
source: fn() -> Workflow,
|
||||
r#type: WorkflowType,
|
||||
}
|
||||
|
||||
impl WorkflowFile {
|
||||
fn zed(f: fn() -> Workflow) -> WorkflowFile {
|
||||
WorkflowFile {
|
||||
source: f,
|
||||
r#type: WorkflowType::Zed,
|
||||
}
|
||||
}
|
||||
fn extension(f: fn() -> Workflow) -> WorkflowFile {
|
||||
WorkflowFile {
|
||||
source: f,
|
||||
r#type: WorkflowType::Extensions,
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_file(&self) -> Result<()> {
|
||||
let workflow = (self.source)();
|
||||
let workflow_folder = self.r#type.folder_path();
|
||||
let workflow_name = workflow
|
||||
.name
|
||||
.as_ref()
|
||||
.expect("Workflow must have a name at this point");
|
||||
let filename = format!(
|
||||
"{}.yml",
|
||||
workflow_name.rsplit("::").next().unwrap_or(workflow_name)
|
||||
);
|
||||
|
||||
let workflow_path = workflow_folder.join(filename);
|
||||
|
||||
let content = workflow
|
||||
.to_string()
|
||||
.map_err(|e| anyhow::anyhow!("{:?}: {:?}", workflow_path, e))?;
|
||||
|
||||
let disclaimer = self.r#type.disclaimer(workflow_name);
|
||||
|
||||
let content = [disclaimer, content].join("\n");
|
||||
fs::write(&workflow_path, content).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
enum WorkflowType {
|
||||
Zed,
|
||||
Extensions,
|
||||
}
|
||||
|
||||
impl WorkflowType {
|
||||
fn disclaimer(&self, workflow_name: &str) -> String {
|
||||
format!(
|
||||
concat!(
|
||||
"# Generated from xtask::workflows::{}{}\n",
|
||||
"# Rebuild with `cargo xtask workflows`.",
|
||||
),
|
||||
matches!(self, WorkflowType::Extensions)
|
||||
.then_some(" within the Zed repository.")
|
||||
.unwrap_or_default(),
|
||||
workflow_name
|
||||
)
|
||||
}
|
||||
|
||||
fn folder_path(&self) -> PathBuf {
|
||||
match self {
|
||||
WorkflowType::Zed => PathBuf::from(".github/workflows"),
|
||||
WorkflowType::Extensions => PathBuf::from("extensions/workflows"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_workflows(_: GenerateWorkflowArgs) -> Result<()> {
|
||||
if !Path::new("crates/zed/").is_dir() {
|
||||
anyhow::bail!("xtask workflows must be ran from the project root");
|
||||
}
|
||||
let dir = Path::new(".github/workflows");
|
||||
let workflow_dir = Path::new(".github/workflows");
|
||||
let extension_workflow_dir = Path::new("extensions/workflows");
|
||||
|
||||
let workflows = vec![
|
||||
("danger.yml", danger::danger()),
|
||||
("run_bundling.yml", run_bundling::run_bundling()),
|
||||
("release_nightly.yml", release_nightly::release_nightly()),
|
||||
("run_tests.yml", run_tests::run_tests()),
|
||||
("release.yml", release::release()),
|
||||
("cherry_pick.yml", cherry_pick::cherry_pick()),
|
||||
("compare_perf.yml", compare_perf::compare_perf()),
|
||||
("run_unit_evals.yml", run_agent_evals::run_unit_evals()),
|
||||
(
|
||||
"run_cron_unit_evals.yml",
|
||||
run_agent_evals::run_cron_unit_evals(),
|
||||
),
|
||||
("run_agent_evals.yml", run_agent_evals::run_agent_evals()),
|
||||
("after_release.yml", after_release::after_release()),
|
||||
("extension_tests.yml", extension_tests::extension_tests()),
|
||||
("extension_bump.yml", extension_bump::extension_bump()),
|
||||
let workflows = [
|
||||
WorkflowFile::zed(danger::danger),
|
||||
WorkflowFile::zed(run_bundling::run_bundling),
|
||||
WorkflowFile::zed(release_nightly::release_nightly),
|
||||
WorkflowFile::zed(run_tests::run_tests),
|
||||
WorkflowFile::zed(release::release),
|
||||
WorkflowFile::zed(cherry_pick::cherry_pick),
|
||||
WorkflowFile::zed(compare_perf::compare_perf),
|
||||
WorkflowFile::zed(run_agent_evals::run_unit_evals),
|
||||
WorkflowFile::zed(run_agent_evals::run_cron_unit_evals),
|
||||
WorkflowFile::zed(run_agent_evals::run_agent_evals),
|
||||
WorkflowFile::zed(after_release::after_release),
|
||||
WorkflowFile::zed(extension_tests::extension_tests),
|
||||
WorkflowFile::zed(extension_bump::extension_bump),
|
||||
WorkflowFile::zed(extension_release::extension_release),
|
||||
/* workflows used for CI/CD in extension repositories */
|
||||
WorkflowFile::extension(extensions::run_tests::run_tests),
|
||||
WorkflowFile::extension(extensions::bump_version::bump_version),
|
||||
WorkflowFile::extension(extensions::release_version::release_version),
|
||||
];
|
||||
fs::create_dir_all(dir)
|
||||
.with_context(|| format!("Failed to create directory: {}", dir.display()))?;
|
||||
|
||||
for (filename, workflow) in workflows {
|
||||
let content = workflow
|
||||
.to_string()
|
||||
.map_err(|e| anyhow::anyhow!("{}: {:?}", filename, e))?;
|
||||
let content = format!(
|
||||
"# Generated from xtask::workflows::{}\n# Rebuild with `cargo xtask workflows`.\n{}",
|
||||
workflow.name.unwrap(),
|
||||
content
|
||||
);
|
||||
let file_path = dir.join(filename);
|
||||
fs::write(&file_path, content)?;
|
||||
for directory in [&workflow_dir, &extension_workflow_dir] {
|
||||
fs::create_dir_all(directory)
|
||||
.with_context(|| format!("Failed to create directory: {}", directory.display()))?;
|
||||
}
|
||||
|
||||
for workflow_file in workflows {
|
||||
workflow_file.generate_file()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -2,6 +2,7 @@ use gh_workflow::*;
|
||||
use indoc::indoc;
|
||||
|
||||
use crate::tasks::workflows::{
|
||||
extension_release::extension_workflow_secrets,
|
||||
extension_tests::{self},
|
||||
runners,
|
||||
steps::{self, CommonJobConditions, DEFAULT_REPOSITORY_OWNER_GUARD, NamedJob, named},
|
||||
@@ -25,10 +26,11 @@ const VERSION_CHECK: &str = r#"sed -n 's/version = \"\(.*\)\"/\1/p' < extension.
|
||||
// This is used by various extensions repos in the zed-extensions org to bump extension versions.
|
||||
pub(crate) fn extension_bump() -> Workflow {
|
||||
let bump_type = WorkflowInput::string("bump-type", Some("patch".to_owned()));
|
||||
// TODO: Ideally, this would have a default of `false`, but this is currently not
|
||||
// supported in gh-workflows
|
||||
let force_bump = WorkflowInput::bool("force-bump", None);
|
||||
|
||||
let app_id = WorkflowSecret::new("app-id", "The app ID used to create the PR");
|
||||
let app_secret =
|
||||
WorkflowSecret::new("app-secret", "The app secret for the corresponding app ID");
|
||||
let (app_id, app_secret) = extension_workflow_secrets();
|
||||
|
||||
let test_extension = extension_tests::check_extension();
|
||||
let (check_bump_needed, needs_bump, current_version) = check_bump_needed();
|
||||
@@ -38,8 +40,15 @@ pub(crate) fn extension_bump() -> Workflow {
|
||||
|
||||
let dependencies = [&test_extension, &check_bump_needed];
|
||||
|
||||
let bump_version =
|
||||
bump_extension_version(&dependencies, &bump_type, &needs_bump, &app_id, &app_secret);
|
||||
let bump_version = bump_extension_version(
|
||||
&dependencies,
|
||||
¤t_version,
|
||||
&bump_type,
|
||||
&needs_bump,
|
||||
&force_bump,
|
||||
&app_id,
|
||||
&app_secret,
|
||||
);
|
||||
let create_label = create_version_label(
|
||||
&dependencies,
|
||||
&needs_bump,
|
||||
@@ -53,6 +62,7 @@ pub(crate) fn extension_bump() -> Workflow {
|
||||
Event::default().workflow_call(
|
||||
WorkflowCall::default()
|
||||
.add_input(bump_type.name, bump_type.call_input())
|
||||
.add_input(force_bump.name, force_bump.call_input())
|
||||
.secrets([
|
||||
(app_id.name.to_owned(), app_id.secret_configuration()),
|
||||
(
|
||||
@@ -90,7 +100,7 @@ fn check_bump_needed() -> (NamedJob, StepOutput, StepOutput) {
|
||||
])
|
||||
.runs_on(runners::LINUX_SMALL)
|
||||
.timeout_minutes(1u32)
|
||||
.add_step(steps::checkout_repo().add_with(("fetch-depth", 10)))
|
||||
.add_step(steps::checkout_repo().add_with(("fetch-depth", 0)))
|
||||
.add_step(compare_versions);
|
||||
|
||||
(named::job(job), version_changed, current_version)
|
||||
@@ -106,7 +116,7 @@ fn create_version_label(
|
||||
let (generate_token, generated_token) = generate_token(app_id, app_secret);
|
||||
let job = steps::dependant_job(dependencies)
|
||||
.cond(Expression::new(format!(
|
||||
"{DEFAULT_REPOSITORY_OWNER_GUARD} && {} == 'false'",
|
||||
"{DEFAULT_REPOSITORY_OWNER_GUARD} && github.event_name == 'push' && github.ref == 'refs/heads/main' && {} == 'false'",
|
||||
needs_bump.expr(),
|
||||
)))
|
||||
.runs_on(runners::LINUX_LARGE)
|
||||
@@ -143,14 +153,21 @@ fn create_version_tag(current_version: &JobOutput, generated_token: StepOutput)
|
||||
fn compare_versions() -> (Step<Run>, StepOutput, StepOutput) {
|
||||
let check_needs_bump = named::bash(format!(
|
||||
indoc! {
|
||||
r#"
|
||||
r#"
|
||||
CURRENT_VERSION="$({})"
|
||||
PR_PARENT_SHA="${{{{ github.event.pull_request.head.sha }}}}"
|
||||
|
||||
git checkout "$(git log -1 --format=%H)"~1
|
||||
if [[ -n "$PR_PARENT_SHA" ]]; then
|
||||
git checkout "$PR_PARENT_SHA"
|
||||
elif BRANCH_PARENT_SHA="$(git merge-base origin/main origin/zed-zippy-autobump)"; then
|
||||
git checkout "$BRANCH_PARENT_SHA"
|
||||
else
|
||||
git checkout "$(git log -1 --format=%H)"~1
|
||||
fi
|
||||
|
||||
PREV_COMMIT_VERSION="$({})"
|
||||
PARENT_COMMIT_VERSION="$({})"
|
||||
|
||||
[[ "$CURRENT_VERSION" == "$PREV_COMMIT_VERSION" ]] && \
|
||||
[[ "$CURRENT_VERSION" == "$PARENT_COMMIT_VERSION" ]] && \
|
||||
echo "needs_bump=true" >> "$GITHUB_OUTPUT" || \
|
||||
echo "needs_bump=false" >> "$GITHUB_OUTPUT"
|
||||
|
||||
@@ -169,17 +186,20 @@ fn compare_versions() -> (Step<Run>, StepOutput, StepOutput) {
|
||||
|
||||
fn bump_extension_version(
|
||||
dependencies: &[&NamedJob],
|
||||
current_version: &JobOutput,
|
||||
bump_type: &WorkflowInput,
|
||||
needs_bump: &JobOutput,
|
||||
force_bump: &WorkflowInput,
|
||||
app_id: &WorkflowSecret,
|
||||
app_secret: &WorkflowSecret,
|
||||
) -> NamedJob {
|
||||
let (generate_token, generated_token) = generate_token(app_id, app_secret);
|
||||
let (bump_version, old_version, new_version) = bump_version(bump_type);
|
||||
let (bump_version, new_version) = bump_version(current_version, bump_type);
|
||||
|
||||
let job = steps::dependant_job(dependencies)
|
||||
.cond(Expression::new(format!(
|
||||
"{DEFAULT_REPOSITORY_OWNER_GUARD} && {} == 'true'",
|
||||
"{DEFAULT_REPOSITORY_OWNER_GUARD} &&\n({} == 'true' || {} == 'true')",
|
||||
force_bump.expr(),
|
||||
needs_bump.expr(),
|
||||
)))
|
||||
.runs_on(runners::LINUX_LARGE)
|
||||
@@ -188,16 +208,15 @@ fn bump_extension_version(
|
||||
.add_step(steps::checkout_repo())
|
||||
.add_step(install_bump_2_version())
|
||||
.add_step(bump_version)
|
||||
.add_step(create_pull_request(
|
||||
old_version,
|
||||
new_version,
|
||||
generated_token,
|
||||
));
|
||||
.add_step(create_pull_request(new_version, generated_token));
|
||||
|
||||
named::job(job)
|
||||
}
|
||||
|
||||
fn generate_token(app_id: &WorkflowSecret, app_secret: &WorkflowSecret) -> (Step<Use>, StepOutput) {
|
||||
pub(crate) fn generate_token(
|
||||
app_id: &WorkflowSecret,
|
||||
app_secret: &WorkflowSecret,
|
||||
) -> (Step<Use>, StepOutput) {
|
||||
let step = named::uses("actions", "create-github-app-token", "v2")
|
||||
.id("generate-token")
|
||||
.add_with(
|
||||
@@ -215,10 +234,10 @@ fn install_bump_2_version() -> Step<Run> {
|
||||
named::run(runners::Platform::Linux, "pip install bump2version")
|
||||
}
|
||||
|
||||
fn bump_version(bump_type: &WorkflowInput) -> (Step<Run>, StepOutput, StepOutput) {
|
||||
fn bump_version(current_version: &JobOutput, bump_type: &WorkflowInput) -> (Step<Run>, StepOutput) {
|
||||
let step = named::bash(format!(
|
||||
indoc! {r#"
|
||||
OLD_VERSION="$({})"
|
||||
OLD_VERSION="{}"
|
||||
|
||||
cat <<EOF > .bumpversion.cfg
|
||||
{}
|
||||
@@ -230,24 +249,18 @@ fn bump_version(bump_type: &WorkflowInput) -> (Step<Run>, StepOutput, StepOutput
|
||||
|
||||
rm .bumpversion.cfg
|
||||
|
||||
echo "old_version=${{OLD_VERSION}}" >> "$GITHUB_OUTPUT"
|
||||
echo "new_version=${{NEW_VERSION}}" >> "$GITHUB_OUTPUT"
|
||||
"#
|
||||
},
|
||||
VERSION_CHECK, BUMPVERSION_CONFIG, bump_type, VERSION_CHECK
|
||||
current_version, BUMPVERSION_CONFIG, bump_type, VERSION_CHECK
|
||||
))
|
||||
.id("bump-version");
|
||||
|
||||
let old_version = StepOutput::new(&step, "old_version");
|
||||
let new_version = StepOutput::new(&step, "new_version");
|
||||
(step, old_version, new_version)
|
||||
(step, new_version)
|
||||
}
|
||||
|
||||
fn create_pull_request(
|
||||
old_version: StepOutput,
|
||||
new_version: StepOutput,
|
||||
generated_token: StepOutput,
|
||||
) -> Step<Use> {
|
||||
fn create_pull_request(new_version: StepOutput, generated_token: StepOutput) -> Step<Use> {
|
||||
let formatted_version = format!("v{}", new_version);
|
||||
|
||||
named::uses("peter-evans", "create-pull-request", "v7").with(
|
||||
@@ -264,7 +277,7 @@ fn create_pull_request(
|
||||
"commit-message",
|
||||
format!("Bump version to {}", formatted_version),
|
||||
)
|
||||
.add("branch", format!("bump-from-{}", old_version))
|
||||
.add("branch", "zed-zippy-autobump")
|
||||
.add(
|
||||
"committer",
|
||||
"zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>",
|
||||
|
||||
70
tooling/xtask/src/tasks/workflows/extension_release.rs
Normal file
70
tooling/xtask/src/tasks/workflows/extension_release.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
use gh_workflow::{Event, Job, Run, Step, Use, Workflow, WorkflowCall};
|
||||
use indoc::indoc;
|
||||
|
||||
use crate::tasks::workflows::{
|
||||
extension_bump::generate_token,
|
||||
runners,
|
||||
steps::{CommonJobConditions, NamedJob, checkout_repo, named},
|
||||
vars::{StepOutput, WorkflowSecret},
|
||||
};
|
||||
|
||||
pub(crate) fn extension_release() -> Workflow {
|
||||
let (app_id, app_secret) = extension_workflow_secrets();
|
||||
|
||||
let create_release = create_release(&app_id, &app_secret);
|
||||
named::workflow()
|
||||
.on(
|
||||
Event::default().workflow_call(WorkflowCall::default().secrets([
|
||||
(app_id.name.to_owned(), app_id.secret_configuration()),
|
||||
(
|
||||
app_secret.name.to_owned(),
|
||||
app_secret.secret_configuration(),
|
||||
),
|
||||
])),
|
||||
)
|
||||
.add_job(create_release.name, create_release.job)
|
||||
}
|
||||
|
||||
fn create_release(app_id: &WorkflowSecret, app_secret: &WorkflowSecret) -> NamedJob {
|
||||
let (generate_token, generated_token) = generate_token(&app_id, &app_secret);
|
||||
let (get_extension_id, extension_id) = get_extension_id();
|
||||
|
||||
let job = Job::default()
|
||||
.with_repository_owner_guard()
|
||||
.runs_on(runners::LINUX_LARGE)
|
||||
.add_step(generate_token)
|
||||
.add_step(checkout_repo())
|
||||
.add_step(get_extension_id)
|
||||
.add_step(release_action(extension_id, generated_token));
|
||||
|
||||
named::job(job)
|
||||
}
|
||||
|
||||
fn get_extension_id() -> (Step<Run>, StepOutput) {
|
||||
let step = named::bash(indoc! {
|
||||
r#"
|
||||
EXTENSION_ID="$(sed -n 's/id = \"\(.*\)\"/\1/p' < extension.toml)"
|
||||
|
||||
echo "extension_id=${EXTENSION_ID}" >> "$GITHUB_OUTPUT"
|
||||
"#})
|
||||
.id("get-extension-id");
|
||||
|
||||
let extension_id = StepOutput::new(&step, "extension_id");
|
||||
|
||||
(step, extension_id)
|
||||
}
|
||||
|
||||
fn release_action(extension_id: StepOutput, generated_token: StepOutput) -> Step<Use> {
|
||||
named::uses("huacnlee", "zed-extension-action", "v2")
|
||||
.add_with(("extension-name", extension_id.to_string()))
|
||||
.add_with(("push-to", "zed-industries/extensions"))
|
||||
.add_env(("COMMITTER_TOKEN", generated_token.to_string()))
|
||||
}
|
||||
|
||||
pub(crate) fn extension_workflow_secrets() -> (WorkflowSecret, WorkflowSecret) {
|
||||
let app_id = WorkflowSecret::new("app-id", "The app ID used to create the PR");
|
||||
let app_secret =
|
||||
WorkflowSecret::new("app-secret", "The app secret for the corresponding app ID");
|
||||
|
||||
(app_id, app_secret)
|
||||
}
|
||||
99
tooling/xtask/src/tasks/workflows/extensions/bump_version.rs
Normal file
99
tooling/xtask/src/tasks/workflows/extensions/bump_version.rs
Normal file
@@ -0,0 +1,99 @@
|
||||
use gh_workflow::{
|
||||
Event, Expression, Input, Job, PullRequest, PullRequestType, Push, Run, Step, UsesJob, Workflow,
|
||||
};
|
||||
use indexmap::IndexMap;
|
||||
use indoc::indoc;
|
||||
|
||||
use crate::tasks::workflows::{
|
||||
runners,
|
||||
steps::{NamedJob, named},
|
||||
vars::{self, JobOutput, StepOutput},
|
||||
};
|
||||
|
||||
pub(crate) fn bump_version() -> Workflow {
|
||||
let (determine_bump_type, bump_type) = determine_bump_type();
|
||||
let bump_type = bump_type.as_job_output(&determine_bump_type);
|
||||
|
||||
let call_bump_version = call_bump_version(&determine_bump_type, bump_type);
|
||||
|
||||
named::workflow()
|
||||
.on(Event::default()
|
||||
.push(Push::default().add_branch("main"))
|
||||
.pull_request(PullRequest::default().add_type(PullRequestType::Labeled)))
|
||||
.add_job(determine_bump_type.name, determine_bump_type.job)
|
||||
.add_job(call_bump_version.name, call_bump_version.job)
|
||||
}
|
||||
|
||||
pub(crate) fn call_bump_version(
|
||||
depending_job: &NamedJob,
|
||||
bump_type: JobOutput,
|
||||
) -> NamedJob<UsesJob> {
|
||||
let job = Job::default()
|
||||
.cond(Expression::new(format!(
|
||||
indoc! {
|
||||
"(github.event.action == 'labeled' && {} != 'patch') ||
|
||||
github.event_name == 'push'"
|
||||
},
|
||||
bump_type.expr()
|
||||
)))
|
||||
.uses(
|
||||
"zed-industries",
|
||||
"zed",
|
||||
".github/workflows/extension_bump.yml",
|
||||
"main",
|
||||
)
|
||||
.add_need(depending_job.name.clone())
|
||||
.with(
|
||||
Input::default()
|
||||
.add("bump-type", bump_type.to_string())
|
||||
.add("force-bump", true),
|
||||
)
|
||||
.secrets(IndexMap::from([
|
||||
("app-id".to_owned(), vars::ZED_ZIPPY_APP_ID.to_owned()),
|
||||
(
|
||||
"app-secret".to_owned(),
|
||||
vars::ZED_ZIPPY_APP_PRIVATE_KEY.to_owned(),
|
||||
),
|
||||
]));
|
||||
|
||||
named::job(job)
|
||||
}
|
||||
|
||||
fn determine_bump_type() -> (NamedJob, StepOutput) {
|
||||
let (get_bump_type, output) = get_bump_type();
|
||||
let job = Job::default()
|
||||
.runs_on(runners::LINUX_DEFAULT)
|
||||
.add_step(get_bump_type)
|
||||
.outputs([(output.name.to_owned(), output.to_string())]);
|
||||
(named::job(job), output)
|
||||
}
|
||||
|
||||
fn get_bump_type() -> (Step<Run>, StepOutput) {
|
||||
let step = named::bash(
|
||||
indoc! {r#"
|
||||
if [ "$HAS_MAJOR_LABEL" = "true" ]; then
|
||||
bump_type="major"
|
||||
elif [ "$HAS_MINOR_LABEL" = "true" ]; then
|
||||
bump_type="minor"
|
||||
else
|
||||
bump_type="patch"
|
||||
fi
|
||||
echo "bump_type=$bump_type" >> $GITHUB_OUTPUT
|
||||
"#},
|
||||
)
|
||||
.add_env(("HAS_MAJOR_LABEL",
|
||||
indoc!{
|
||||
"${{ (github.event.action == 'labeled' && github.event.label.name == 'major') ||
|
||||
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'major')) }}"
|
||||
}))
|
||||
.add_env(("HAS_MINOR_LABEL",
|
||||
indoc!{
|
||||
"${{ (github.event.action == 'labeled' && github.event.label.name == 'minor') ||
|
||||
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'minor')) }}"
|
||||
}))
|
||||
.id("get-bump-type");
|
||||
|
||||
let step_output = StepOutput::new(&step, "bump_type");
|
||||
|
||||
(step, step_output)
|
||||
}
|
||||
24
tooling/xtask/src/tasks/workflows/extensions/mod.rs
Normal file
24
tooling/xtask/src/tasks/workflows/extensions/mod.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use gh_workflow::{Job, UsesJob};
|
||||
use indexmap::IndexMap;
|
||||
|
||||
use crate::tasks::workflows::vars;
|
||||
|
||||
pub(crate) mod bump_version;
|
||||
pub(crate) mod release_version;
|
||||
pub(crate) mod run_tests;
|
||||
|
||||
pub(crate) trait WithAppSecrets: Sized {
|
||||
fn with_app_secrets(self) -> Self;
|
||||
}
|
||||
|
||||
impl WithAppSecrets for Job<UsesJob> {
|
||||
fn with_app_secrets(self) -> Self {
|
||||
self.secrets(IndexMap::from([
|
||||
("app-id".to_owned(), vars::ZED_ZIPPY_APP_ID.to_owned()),
|
||||
(
|
||||
"app-secret".to_owned(),
|
||||
vars::ZED_ZIPPY_APP_PRIVATE_KEY.to_owned(),
|
||||
),
|
||||
]))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
use gh_workflow::{Event, Job, Push, UsesJob, Workflow};
|
||||
|
||||
use crate::tasks::workflows::{
|
||||
extensions::WithAppSecrets,
|
||||
steps::{NamedJob, named},
|
||||
};
|
||||
|
||||
pub(crate) fn release_version() -> Workflow {
|
||||
let create_release = call_release_version();
|
||||
named::workflow()
|
||||
.on(Event::default().push(Push::default().add_tag("v**")))
|
||||
.add_job(create_release.name, create_release.job)
|
||||
}
|
||||
|
||||
pub(crate) fn call_release_version() -> NamedJob<UsesJob> {
|
||||
let job = Job::default()
|
||||
.uses(
|
||||
"zed-industries",
|
||||
"zed",
|
||||
".github/workflows/extension_release.yml",
|
||||
"main",
|
||||
)
|
||||
.with_app_secrets();
|
||||
|
||||
named::job(job)
|
||||
}
|
||||
25
tooling/xtask/src/tasks/workflows/extensions/run_tests.rs
Normal file
25
tooling/xtask/src/tasks/workflows/extensions/run_tests.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use gh_workflow::{Event, Job, PullRequest, UsesJob, Workflow};
|
||||
|
||||
use crate::tasks::workflows::{
|
||||
steps::{NamedJob, named},
|
||||
vars::one_workflow_per_non_main_branch,
|
||||
};
|
||||
|
||||
pub(crate) fn run_tests() -> Workflow {
|
||||
let call_extension_tests = call_extension_tests();
|
||||
named::workflow()
|
||||
.on(Event::default().pull_request(PullRequest::default().add_branch("**")))
|
||||
.concurrency(one_workflow_per_non_main_branch())
|
||||
.add_job(call_extension_tests.name, call_extension_tests.job)
|
||||
}
|
||||
|
||||
pub(crate) fn call_extension_tests() -> NamedJob<UsesJob> {
|
||||
let job = Job::default().uses(
|
||||
"zed-industries",
|
||||
"zed",
|
||||
".github/workflows/extension_tests.yml",
|
||||
"main",
|
||||
);
|
||||
|
||||
named::job(job)
|
||||
}
|
||||
@@ -9,6 +9,7 @@ use crate::tasks::workflows::{
|
||||
|
||||
use super::{runners, steps};
|
||||
use gh_workflow::*;
|
||||
use indoc::indoc;
|
||||
|
||||
pub fn run_bundling() -> Workflow {
|
||||
let bundle = ReleaseBundleJobs {
|
||||
@@ -42,10 +43,11 @@ pub fn run_bundling() -> Workflow {
|
||||
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'))",
|
||||
)))
|
||||
job.cond(Expression::new(
|
||||
indoc! {
|
||||
r#"(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)
|
||||
}
|
||||
|
||||
|
||||
@@ -128,9 +128,9 @@ pub fn script(name: &str) -> Step<Run> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NamedJob {
|
||||
pub struct NamedJob<J: JobType = RunJob> {
|
||||
pub name: String,
|
||||
pub job: Job,
|
||||
pub job: Job<J>,
|
||||
}
|
||||
|
||||
// impl NamedJob {
|
||||
@@ -282,15 +282,19 @@ pub mod named {
|
||||
Workflow::default().name(
|
||||
named::function_name(1)
|
||||
.split("::")
|
||||
.next()
|
||||
.unwrap()
|
||||
.to_owned(),
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
.rev()
|
||||
.skip(1)
|
||||
.rev()
|
||||
.collect::<Vec<_>>()
|
||||
.join("::"),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a Job with the same name as the enclosing function.
|
||||
/// (note job names may not contain `::`)
|
||||
pub fn job(job: Job) -> NamedJob {
|
||||
pub fn job<J: JobType>(job: Job<J>) -> NamedJob<J> {
|
||||
NamedJob {
|
||||
name: function_name(1).split("::").last().unwrap().to_owned(),
|
||||
job,
|
||||
|
||||
@@ -219,6 +219,14 @@ impl WorkflowInput {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bool(name: &'static str, default: Option<bool>) -> Self {
|
||||
Self {
|
||||
input_type: "boolean",
|
||||
name,
|
||||
default: default.as_ref().map(ToString::to_string),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn input(&self) -> WorkflowDispatchInput {
|
||||
WorkflowDispatchInput {
|
||||
description: self.name.to_owned(),
|
||||
@@ -236,11 +244,15 @@ impl WorkflowInput {
|
||||
default: self.default.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn expr(&self) -> String {
|
||||
format!("inputs.{}", self.name)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for WorkflowInput {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "${{{{ inputs.{} }}}}", self.name)
|
||||
write!(f, "${{{{ {} }}}}", self.expr())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user