Add workflow to rollout changes to the extension organization (#45579)
This PR adds a workflow that we can utilize to rollout changes to the CI workflows for the `zed-extensions` organization. Release Notes: - N/A
This commit is contained in:
101
.github/workflows/extension_workflow_rollout.yml
vendored
Normal file
101
.github/workflows/extension_workflow_rollout.yml
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
# Generated from xtask::workflows::extension_workflow_rollout
|
||||
# Rebuild with `cargo xtask workflows`.
|
||||
name: extension_workflow_rollout
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
on:
|
||||
workflow_dispatch: {}
|
||||
jobs:
|
||||
fetch_extension_repos:
|
||||
runs-on: namespace-profile-2x4-ubuntu-2404
|
||||
steps:
|
||||
- id: list-repos
|
||||
name: extension_workflow_rollout::fetch_extension_repos::get_repositories
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const repos = await github.paginate(github.rest.repos.listForOrg, {
|
||||
org: 'zed-extensions',
|
||||
type: 'public',
|
||||
per_page: 100,
|
||||
});
|
||||
|
||||
const filteredRepos = repos
|
||||
.filter(repo => !repo.archived)
|
||||
.filter(repo => repo.name !== 'workflows' && repo.name !== 'material-icon-theme')
|
||||
.map(repo => repo.name);
|
||||
|
||||
console.log(`Found ${filteredRepos.length} extension repos`);
|
||||
return filteredRepos;
|
||||
result-encoding: json
|
||||
outputs:
|
||||
repos: ${{ steps.list-repos.outputs.result }}
|
||||
timeout-minutes: 5
|
||||
rollout_workflows_to_extension:
|
||||
needs:
|
||||
- fetch_extension_repos
|
||||
if: needs.fetch_extension_repos.outputs.repos != '[]'
|
||||
runs-on: namespace-profile-2x4-ubuntu-2404
|
||||
strategy:
|
||||
matrix:
|
||||
repo: ${{ fromJson(needs.fetch_extension_repos.outputs.repos) }}
|
||||
fail-fast: false
|
||||
max-parallel: 5
|
||||
steps:
|
||||
- id: get-app-token
|
||||
name: steps::authenticate_as_zippy
|
||||
uses: actions/create-github-app-token@bef1eaf1c0ac2b148ee2a0a74c65fbe6db0631f1
|
||||
with:
|
||||
app-id: ${{ secrets.ZED_ZIPPY_APP_ID }}
|
||||
private-key: ${{ secrets.ZED_ZIPPY_APP_PRIVATE_KEY }}
|
||||
- name: checkout_zed_repo
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
with:
|
||||
clean: false
|
||||
path: zed
|
||||
- name: steps::checkout_repo_with_token
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
with:
|
||||
clean: false
|
||||
token: ${{ steps.get-app-token.outputs.token }}
|
||||
repository: zed-extensions/${{ matrix.repo }}
|
||||
path: extension
|
||||
- name: extension_workflow_rollout::rollout_workflows_to_extension::copy_workflow_files
|
||||
run: |
|
||||
mkdir -p extension/.github/workflows
|
||||
cp zed/extensions/workflows/*.yml extension/.github/workflows/
|
||||
shell: bash -euxo pipefail {0}
|
||||
- id: short-sha
|
||||
name: extension_workflow_rollout::rollout_workflows_to_extension::get_short_sha
|
||||
run: |
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
|
||||
shell: bash -euxo pipefail {0}
|
||||
working-directory: zed
|
||||
- id: create-pr
|
||||
name: extension_workflow_rollout::rollout_workflows_to_extension::create_pull_request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
path: extension
|
||||
title: Update CI workflows to zed@${{ steps.short-sha.outputs.sha_short }}
|
||||
body: |
|
||||
This PR updates the CI workflow files from the main Zed repository
|
||||
based on the commit zed-industries/zed@${{ github.sha }}
|
||||
commit-message: Update CI workflows to zed@${{ steps.short-sha.outputs.sha_short }}
|
||||
branch: update-workflows
|
||||
committer: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
|
||||
author: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
|
||||
base: main
|
||||
delete-branch: true
|
||||
token: ${{ steps.get-app-token.outputs.token }}
|
||||
sign-commits: true
|
||||
- name: extension_workflow_rollout::rollout_workflows_to_extension::enable_auto_merge
|
||||
run: |
|
||||
PR_NUMBER="${{ steps.create-pr.outputs.pull-request-number }}"
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
cd extension
|
||||
gh pr merge "$PR_NUMBER" --auto --squash
|
||||
fi
|
||||
shell: bash -euxo pipefail {0}
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.get-app-token.outputs.token }}
|
||||
timeout-minutes: 10
|
||||
@@ -12,6 +12,7 @@ mod danger;
|
||||
mod extension_bump;
|
||||
mod extension_release;
|
||||
mod extension_tests;
|
||||
mod extension_workflow_rollout;
|
||||
mod extensions;
|
||||
mod nix_build;
|
||||
mod release_nightly;
|
||||
@@ -121,6 +122,7 @@ pub fn run_workflows(_: GenerateWorkflowArgs) -> Result<()> {
|
||||
WorkflowFile::zed(extension_tests::extension_tests),
|
||||
WorkflowFile::zed(extension_bump::extension_bump),
|
||||
WorkflowFile::zed(extension_release::extension_release),
|
||||
WorkflowFile::zed(extension_workflow_rollout::extension_workflow_rollout),
|
||||
/* workflows used for CI/CD in extension repositories */
|
||||
WorkflowFile::extension(extensions::run_tests::run_tests),
|
||||
WorkflowFile::extension(extensions::bump_version::bump_version),
|
||||
|
||||
174
tooling/xtask/src/tasks/workflows/extension_workflow_rollout.rs
Normal file
174
tooling/xtask/src/tasks/workflows/extension_workflow_rollout.rs
Normal file
@@ -0,0 +1,174 @@
|
||||
use gh_workflow::{Event, Expression, Job, Run, Step, Strategy, Use, Workflow, WorkflowDispatch};
|
||||
use indoc::indoc;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::tasks::workflows::{
|
||||
runners,
|
||||
steps::{self, NamedJob, named},
|
||||
vars::StepOutput,
|
||||
};
|
||||
|
||||
const EXCLUDED_REPOS: &[&str] = &["workflows", "material-icon-theme"];
|
||||
|
||||
pub(crate) fn extension_workflow_rollout() -> Workflow {
|
||||
let fetch_repos = fetch_extension_repos();
|
||||
let rollout_workflows = rollout_workflows_to_extension(&fetch_repos);
|
||||
|
||||
named::workflow()
|
||||
.on(Event::default().workflow_dispatch(WorkflowDispatch::default()))
|
||||
.add_env(("CARGO_TERM_COLOR", "always"))
|
||||
.add_job(fetch_repos.name, fetch_repos.job)
|
||||
.add_job(rollout_workflows.name, rollout_workflows.job)
|
||||
}
|
||||
|
||||
fn fetch_extension_repos() -> NamedJob {
|
||||
fn get_repositories() -> (Step<Use>, StepOutput) {
|
||||
let exclusion_filter = EXCLUDED_REPOS
|
||||
.iter()
|
||||
.map(|repo| format!("repo.name !== '{}'", repo))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" && ");
|
||||
|
||||
let step = named::uses("actions", "github-script", "v7")
|
||||
.id("list-repos")
|
||||
.add_with((
|
||||
"script",
|
||||
format!(
|
||||
indoc! {r#"
|
||||
const repos = await github.paginate(github.rest.repos.listForOrg, {{
|
||||
org: 'zed-extensions',
|
||||
type: 'public',
|
||||
per_page: 100,
|
||||
}});
|
||||
|
||||
const filteredRepos = repos
|
||||
.filter(repo => !repo.archived)
|
||||
.filter(repo => {})
|
||||
.map(repo => repo.name);
|
||||
|
||||
console.log(`Found ${{filteredRepos.length}} extension repos`);
|
||||
return filteredRepos;
|
||||
"#},
|
||||
exclusion_filter
|
||||
),
|
||||
))
|
||||
.add_with(("result-encoding", "json"));
|
||||
|
||||
let filtered_repos = StepOutput::new(&step, "result");
|
||||
|
||||
(step, filtered_repos)
|
||||
}
|
||||
|
||||
let (get_org_repositories, list_repos_output) = get_repositories();
|
||||
|
||||
let job = Job::default()
|
||||
.runs_on(runners::LINUX_SMALL)
|
||||
.timeout_minutes(5u32)
|
||||
.outputs([("repos".to_owned(), list_repos_output.to_string())])
|
||||
.add_step(get_org_repositories);
|
||||
|
||||
named::job(job)
|
||||
}
|
||||
|
||||
fn rollout_workflows_to_extension(fetch_repos_job: &NamedJob) -> NamedJob {
|
||||
fn checkout_zed_repo() -> Step<Use> {
|
||||
steps::checkout_repo()
|
||||
.name("checkout_zed_repo")
|
||||
.add_with(("path", "zed"))
|
||||
}
|
||||
|
||||
fn checkout_extension_repo(token: &StepOutput) -> Step<Use> {
|
||||
steps::checkout_repo_with_token(token)
|
||||
.add_with(("repository", "zed-extensions/${{ matrix.repo }}"))
|
||||
.add_with(("path", "extension"))
|
||||
}
|
||||
|
||||
fn copy_workflow_files() -> Step<Run> {
|
||||
named::bash(indoc! {r#"
|
||||
mkdir -p extension/.github/workflows
|
||||
cp zed/extensions/workflows/*.yml extension/.github/workflows/
|
||||
"#})
|
||||
}
|
||||
|
||||
fn get_short_sha() -> (Step<Run>, StepOutput) {
|
||||
let step = named::bash(indoc! {r#"
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
|
||||
"#})
|
||||
.id("short-sha")
|
||||
.working_directory("zed");
|
||||
|
||||
let step_output = StepOutput::new(&step, "sha_short");
|
||||
|
||||
(step, step_output)
|
||||
}
|
||||
|
||||
fn create_pull_request(token: &StepOutput, short_sha: StepOutput) -> Step<Use> {
|
||||
let title = format!("Update CI workflows to zed@{}", short_sha);
|
||||
|
||||
named::uses("peter-evans", "create-pull-request", "v7")
|
||||
.add_with(("path", "extension"))
|
||||
.add_with(("title", title.clone()))
|
||||
.add_with((
|
||||
"body",
|
||||
indoc! {r#"
|
||||
This PR updates the CI workflow files from the main Zed repository
|
||||
based on the commit zed-industries/zed@${{ github.sha }}
|
||||
"#},
|
||||
))
|
||||
.add_with(("commit-message", title))
|
||||
.add_with(("branch", "update-workflows"))
|
||||
.add_with((
|
||||
"committer",
|
||||
"zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>",
|
||||
))
|
||||
.add_with((
|
||||
"author",
|
||||
"zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>",
|
||||
))
|
||||
.add_with(("base", "main"))
|
||||
.add_with(("delete-branch", true))
|
||||
.add_with(("token", token.to_string()))
|
||||
.add_with(("sign-commits", true))
|
||||
.id("create-pr")
|
||||
}
|
||||
|
||||
fn enable_auto_merge(token: &StepOutput) -> Step<gh_workflow::Run> {
|
||||
named::bash(indoc! {r#"
|
||||
PR_NUMBER="${{ steps.create-pr.outputs.pull-request-number }}"
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
cd extension
|
||||
gh pr merge "$PR_NUMBER" --auto --squash
|
||||
fi
|
||||
"#})
|
||||
.add_env(("GH_TOKEN", token.to_string()))
|
||||
}
|
||||
|
||||
let (authenticate, token) = steps::authenticate_as_zippy();
|
||||
let (calculate_short_sha, short_sha) = get_short_sha();
|
||||
|
||||
let job = Job::default()
|
||||
.needs([fetch_repos_job.name.clone()])
|
||||
.cond(Expression::new(format!(
|
||||
"needs.{}.outputs.repos != '[]'",
|
||||
fetch_repos_job.name
|
||||
)))
|
||||
.runs_on(runners::LINUX_SMALL)
|
||||
.timeout_minutes(10u32)
|
||||
.strategy(
|
||||
Strategy::default()
|
||||
.fail_fast(false)
|
||||
.max_parallel(5u32)
|
||||
.matrix(json!({
|
||||
"repo": format!("${{{{ fromJson(needs.{}.outputs.repos) }}}}", fetch_repos_job.name)
|
||||
})),
|
||||
)
|
||||
.add_step(authenticate)
|
||||
.add_step(checkout_zed_repo())
|
||||
.add_step(checkout_extension_repo(&token))
|
||||
.add_step(copy_workflow_files())
|
||||
.add_step(calculate_short_sha)
|
||||
.add_step(create_pull_request(&token, short_sha))
|
||||
.add_step(enable_auto_merge(&token));
|
||||
|
||||
named::job(job)
|
||||
}
|
||||
Reference in New Issue
Block a user