extension_ci: Add initial support for extensions in a subdirectory (#51173)

This wil help with releases for extensions living this repository, which
will become more relevant once agent provider extensions are back on the
table.

Release Notes:

- N/A
This commit is contained in:
Finn Evers 2026-03-13 13:40:45 +01:00 committed by GitHub
parent 46f16c7502
commit 7d566e0600
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 278 additions and 90 deletions

View file

@ -17,6 +17,10 @@ on:
description: force-bump
required: true
type: boolean
working-directory:
description: working-directory
type: string
default: .
secrets:
app-id:
description: The app ID used to create the PR
@ -42,8 +46,6 @@ jobs:
if [[ "$GITHUB_EVENT_NAME" == "pull_request" ]]; then
PR_FORK_POINT="$(git merge-base origin/main HEAD)"
git checkout "$PR_FORK_POINT"
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
@ -59,6 +61,10 @@ jobs:
version_changed: ${{ steps.compare-versions-check.outputs.version_changed }}
current_version: ${{ steps.compare-versions-check.outputs.current_version }}
timeout-minutes: 1
defaults:
run:
shell: bash -euxo pipefail {0}
working-directory: ${{ inputs.working-directory }}
bump_extension_version:
needs:
- check_version_changed
@ -98,18 +104,35 @@ jobs:
fi
NEW_VERSION="$(sed -n 's/^version = \"\(.*\)\"/\1/p' < extension.toml | tr -d '[:space:]')"
EXTENSION_ID="$(sed -n 's/^id = "\(.*\)"/\1/p' < extension.toml | head -1 | tr -d '[:space:]')"
EXTENSION_NAME="$(sed -n 's/^name = "\(.*\)"/\1/p' < extension.toml | head -1 | tr -d '[:space:]')"
if [[ "$WORKING_DIR" == "." || -z "$WORKING_DIR" ]]; then
{
echo "title=Bump version to ${NEW_VERSION}";
echo "body=This PR bumps the version of this extension to v${NEW_VERSION}";
echo "branch_name=zed-zippy-autobump";
} >> "$GITHUB_OUTPUT"
else
{
echo "title=${EXTENSION_ID}: Bump to v${NEW_VERSION}";
echo "body=This PR bumps the version of the ${EXTENSION_NAME} extension to v${NEW_VERSION}";
echo "branch_name=zed-zippy-${EXTENSION_ID}-autobump";
} >> "$GITHUB_OUTPUT"
fi
echo "new_version=${NEW_VERSION}" >> "$GITHUB_OUTPUT"
env:
OLD_VERSION: ${{ needs.check_version_changed.outputs.current_version }}
BUMP_TYPE: ${{ inputs.bump-type }}
WORKING_DIR: ${{ inputs.working-directory }}
- name: extension_bump::create_pull_request
uses: peter-evans/create-pull-request@v7
with:
title: Bump version to ${{ steps.bump-version.outputs.new_version }}
body: This PR bumps the version of this extension to v${{ steps.bump-version.outputs.new_version }}
commit-message: Bump version to v${{ steps.bump-version.outputs.new_version }}
branch: zed-zippy-autobump
title: ${{ steps.bump-version.outputs.title }}
body: ${{ steps.bump-version.outputs.body }}
commit-message: ${{ steps.bump-version.outputs.title }}
branch: ${{ steps.bump-version.outputs.branch_name }}
committer: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>
base: main
delete-branch: true
@ -117,6 +140,10 @@ jobs:
sign-commits: true
assignees: ${{ github.actor }}
timeout-minutes: 3
defaults:
run:
shell: bash -euxo pipefail {0}
working-directory: ${{ inputs.working-directory }}
create_version_label:
needs:
- check_version_changed
@ -145,6 +172,10 @@ jobs:
})
github-token: ${{ steps.generate-token.outputs.token }}
timeout-minutes: 1
defaults:
run:
shell: bash -euxo pipefail {0}
working-directory: ${{ inputs.working-directory }}
trigger_release:
needs:
- check_version_changed
@ -178,6 +209,10 @@ jobs:
tag: v${{ needs.check_version_changed.outputs.current_version }}
env:
COMMITTER_TOKEN: ${{ steps.generate-token.outputs.token }}
defaults:
run:
shell: bash -euxo pipefail {0}
working-directory: ${{ inputs.working-directory }}
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}
cancel-in-progress: true

View file

@ -9,7 +9,12 @@ env:
RUSTUP_TOOLCHAIN: stable
CARGO_BUILD_TARGET: wasm32-wasip2
on:
workflow_call: {}
workflow_call:
inputs:
working-directory:
description: working-directory
type: string
default: .
jobs:
orchestrate:
if: (github.repository_owner == 'zed-industries' || github.repository_owner == 'zed-extensions')
@ -34,6 +39,14 @@ jobs:
fi
CHANGED_FILES="$(git diff --name-only "$COMPARE_REV" "$GITHUB_SHA")"
# When running from a subdirectory, git diff returns repo-root-relative paths.
# Filter to only files within the current working directory and strip the prefix.
REPO_SUBDIR="$(git rev-parse --show-prefix)"
REPO_SUBDIR="${REPO_SUBDIR%/}"
if [ -n "$REPO_SUBDIR" ]; then
CHANGED_FILES="$(echo "$CHANGED_FILES" | grep "^${REPO_SUBDIR}/" | sed "s|^${REPO_SUBDIR}/||" || true)"
fi
check_pattern() {
local output_name="$1"
local pattern="$2"
@ -49,6 +62,10 @@ jobs:
outputs:
check_rust: ${{ steps.filter.outputs.check_rust }}
check_extension: ${{ steps.filter.outputs.check_extension }}
defaults:
run:
shell: bash -euxo pipefail {0}
working-directory: ${{ inputs.working-directory }}
check_rust:
needs:
- orchestrate
@ -66,17 +83,31 @@ jobs:
path: ~/.rustup
- name: extension_tests::install_rust_target
run: rustup target add wasm32-wasip2
- name: steps::cargo_fmt
run: cargo fmt --all -- --check
- id: get-package-name
name: extension_tests::get_package_name
run: |
PACKAGE_NAME="$(sed -n 's/^name = "\(.*\)"/\1/p' < Cargo.toml | head -1 | tr -d '[:space:]')"
echo "package_name=${PACKAGE_NAME}" >> "$GITHUB_OUTPUT"
- name: extension_tests::cargo_fmt_package
run: cargo fmt -p "$PACKAGE_NAME" -- --check
env:
PACKAGE_NAME: ${{ steps.get-package-name.outputs.package_name }}
- name: extension_tests::run_clippy
run: cargo clippy --release --all-features -- --deny warnings
run: cargo clippy -p "$PACKAGE_NAME" --release --all-features -- --deny warnings
env:
PACKAGE_NAME: ${{ steps.get-package-name.outputs.package_name }}
- name: steps::cargo_install_nextest
uses: taiki-e/install-action@nextest
- name: steps::cargo_nextest
run: 'cargo nextest run --workspace --no-fail-fast --no-tests=warn --target "$(rustc -vV | sed -n ''s|host: ||p'')"'
- name: extension_tests::run_nextest
run: 'cargo nextest run -p "$PACKAGE_NAME" --no-fail-fast --no-tests=warn --target "$(rustc -vV | sed -n ''s|host: ||p'')"'
env:
PACKAGE_NAME: ${{ steps.get-package-name.outputs.package_name }}
NEXTEST_NO_TESTS: warn
timeout-minutes: 6
defaults:
run:
shell: bash -euxo pipefail {0}
working-directory: ${{ inputs.working-directory }}
check_extension:
needs:
- orchestrate
@ -97,8 +128,8 @@ jobs:
- name: extension_tests::download_zed_extension_cli
if: steps.cache-zed-extension-cli.outputs.cache-hit != 'true'
run: |
wget --quiet "https://zed-extension-cli.nyc3.digitaloceanspaces.com/$ZED_EXTENSION_CLI_SHA/x86_64-unknown-linux-gnu/zed-extension"
chmod +x zed-extension
wget --quiet "https://zed-extension-cli.nyc3.digitaloceanspaces.com/$ZED_EXTENSION_CLI_SHA/x86_64-unknown-linux-gnu/zed-extension" -O "$GITHUB_WORKSPACE/zed-extension"
chmod +x "$GITHUB_WORKSPACE/zed-extension"
- name: steps::cache_rust_dependencies_namespace
uses: namespacelabs/nscloud-cache-action@v1
with:
@ -108,7 +139,7 @@ jobs:
run: |
mkdir -p /tmp/ext-scratch
mkdir -p /tmp/ext-output
./zed-extension --source-dir . --scratch-dir /tmp/ext-scratch --output-dir /tmp/ext-output
"$GITHUB_WORKSPACE/zed-extension" --source-dir . --scratch-dir /tmp/ext-scratch --output-dir /tmp/ext-output
- name: run_tests::fetch_ts_query_ls
uses: dsaltares/fetch-gh-release-asset@aa37ae5c44d3c9820bc12fe675e8670ecd93bd1c
with:
@ -117,8 +148,8 @@ jobs:
file: ts_query_ls-x86_64-unknown-linux-gnu.tar.gz
- name: run_tests::run_ts_query_ls
run: |-
tar -xf ts_query_ls-x86_64-unknown-linux-gnu.tar.gz
./ts_query_ls format --check . || {
tar -xf "$GITHUB_WORKSPACE/ts_query_ls-x86_64-unknown-linux-gnu.tar.gz" -C "$GITHUB_WORKSPACE"
"$GITHUB_WORKSPACE/ts_query_ls" format --check . || {
echo "Found unformatted queries, please format them with ts_query_ls."
echo "For easy use, install the Tree-sitter query extension:"
echo "zed://extension/tree-sitter-query"
@ -132,8 +163,6 @@ jobs:
if [[ "$GITHUB_EVENT_NAME" == "pull_request" ]]; then
PR_FORK_POINT="$(git merge-base origin/main HEAD)"
git checkout "$PR_FORK_POINT"
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
@ -156,6 +185,10 @@ jobs:
VERSION_CHANGED: ${{ steps.compare-versions-check.outputs.version_changed }}
PR_USER_LOGIN: ${{ github.event.pull_request.user.login }}
timeout-minutes: 6
defaults:
run:
shell: bash -euxo pipefail {0}
working-directory: ${{ inputs.working-directory }}
tests_pass:
needs:
- orchestrate
@ -183,6 +216,10 @@ jobs:
RESULT_ORCHESTRATE: ${{ needs.orchestrate.result }}
RESULT_CHECK_RUST: ${{ needs.check_rust.result }}
RESULT_CHECK_EXTENSION: ${{ needs.check_extension.result }}
defaults:
run:
shell: bash -euxo pipefail {0}
working-directory: ${{ inputs.working-directory }}
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}
cancel-in-progress: true

View file

@ -147,8 +147,8 @@ jobs:
file: ts_query_ls-x86_64-unknown-linux-gnu.tar.gz
- name: run_tests::run_ts_query_ls
run: |-
tar -xf ts_query_ls-x86_64-unknown-linux-gnu.tar.gz
./ts_query_ls format --check . || {
tar -xf "$GITHUB_WORKSPACE/ts_query_ls-x86_64-unknown-linux-gnu.tar.gz" -C "$GITHUB_WORKSPACE"
"$GITHUB_WORKSPACE/ts_query_ls" format --check . || {
echo "Found unformatted queries, please format them with ts_query_ls."
echo "For easy use, install the Tree-sitter query extension:"
echo "zed://extension/tree-sitter-query"

View file

@ -5,8 +5,8 @@ use crate::tasks::workflows::{
extension_tests::{self},
runners,
steps::{
self, CommonJobConditions, DEFAULT_REPOSITORY_OWNER_GUARD, FluentBuilder, NamedJob,
checkout_repo, dependant_job, named,
self, BASH_SHELL, CommonJobConditions, DEFAULT_REPOSITORY_OWNER_GUARD, FluentBuilder,
NamedJob, checkout_repo, dependant_job, named,
},
vars::{
JobOutput, StepOutput, WorkflowInput, WorkflowSecret, one_workflow_per_non_main_branch,
@ -22,6 +22,7 @@ pub(crate) fn extension_bump() -> Workflow {
// 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 working_directory = WorkflowInput::string("working-directory", Some(".".to_owned()));
let (app_id, app_secret) = extension_workflow_secrets();
let (check_version_changed, version_changed, current_version) = check_version_changed();
@ -59,6 +60,7 @@ pub(crate) fn extension_bump() -> Workflow {
WorkflowCall::default()
.add_input(bump_type.name, bump_type.call_input())
.add_input(force_bump.name, force_bump.call_input())
.add_input(working_directory.name, working_directory.call_input())
.secrets([
(app_id.name.to_owned(), app_id.secret_configuration()),
(
@ -82,10 +84,19 @@ pub(crate) fn extension_bump() -> Workflow {
.add_job(trigger_release.name, trigger_release.job)
}
fn extension_job_defaults() -> Defaults {
Defaults::default().run(
RunDefaults::default()
.shell(BASH_SHELL)
.working_directory("${{ inputs.working-directory }}"),
)
}
fn check_version_changed() -> (NamedJob, StepOutput, StepOutput) {
let (compare_versions, version_changed, current_version) = compare_versions();
let job = Job::default()
.defaults(extension_job_defaults())
.with_repository_owner_guard()
.outputs([
(version_changed.name.to_owned(), version_changed.to_string()),
@ -112,6 +123,7 @@ fn create_version_label(
let (generate_token, generated_token) =
generate_token(&app_id.to_string(), &app_secret.to_string(), None);
let job = steps::dependant_job(dependencies)
.defaults(extension_job_defaults())
.cond(Expression::new(format!(
"{DEFAULT_REPOSITORY_OWNER_GUARD} && github.event_name == 'push' && \
github.ref == 'refs/heads/main' && {version_changed} == 'true'",
@ -153,8 +165,6 @@ pub(crate) fn compare_versions() -> (Step<Run>, StepOutput, StepOutput) {
if [[ "$GITHUB_EVENT_NAME" == "pull_request" ]]; then
PR_FORK_POINT="$(git merge-base origin/main HEAD)"
git checkout "$PR_FORK_POINT"
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
@ -187,9 +197,11 @@ fn bump_extension_version(
) -> NamedJob {
let (generate_token, generated_token) =
generate_token(&app_id.to_string(), &app_secret.to_string(), None);
let (bump_version, new_version) = bump_version(current_version, bump_type);
let (bump_version, _new_version, title, body, branch_name) =
bump_version(current_version, bump_type);
let job = steps::dependant_job(dependencies)
.defaults(extension_job_defaults())
.cond(Expression::new(format!(
"{DEFAULT_REPOSITORY_OWNER_GUARD} &&\n({force_bump} == true || {version_changed} == 'false')",
force_bump = force_bump_output.expr(),
@ -201,7 +213,12 @@ fn bump_extension_version(
.add_step(steps::checkout_repo())
.add_step(install_bump_2_version())
.add_step(bump_version)
.add_step(create_pull_request(new_version, generated_token));
.add_step(create_pull_request(
title,
body,
generated_token,
branch_name,
));
named::job(job)
}
@ -256,7 +273,10 @@ fn install_bump_2_version() -> Step<Run> {
)
}
fn bump_version(current_version: &JobOutput, bump_type: &WorkflowInput) -> (Step<Run>, StepOutput) {
fn bump_version(
current_version: &JobOutput,
bump_type: &WorkflowInput,
) -> (Step<Run>, StepOutput, StepOutput, StepOutput, StepOutput) {
let step = named::bash(formatdoc! {r#"
BUMP_FILES=("extension.toml")
if [[ -f "Cargo.toml" ]]; then
@ -274,33 +294,50 @@ fn bump_version(current_version: &JobOutput, bump_type: &WorkflowInput) -> (Step
fi
NEW_VERSION="$({VERSION_CHECK})"
EXTENSION_ID="$(sed -n 's/^id = "\(.*\)"/\1/p' < extension.toml | head -1 | tr -d '[:space:]')"
EXTENSION_NAME="$(sed -n 's/^name = "\(.*\)"/\1/p' < extension.toml | head -1 | tr -d '[:space:]')"
if [[ "$WORKING_DIR" == "." || -z "$WORKING_DIR" ]]; then
{{
echo "title=Bump version to ${{NEW_VERSION}}";
echo "body=This PR bumps the version of this extension to v${{NEW_VERSION}}";
echo "branch_name=zed-zippy-autobump";
}} >> "$GITHUB_OUTPUT"
else
{{
echo "title=${{EXTENSION_ID}}: Bump to v${{NEW_VERSION}}";
echo "body=This PR bumps the version of the ${{EXTENSION_NAME}} extension to v${{NEW_VERSION}}";
echo "branch_name=zed-zippy-${{EXTENSION_ID}}-autobump";
}} >> "$GITHUB_OUTPUT"
fi
echo "new_version=${{NEW_VERSION}}" >> "$GITHUB_OUTPUT"
"#
})
.id("bump-version")
.add_env(("OLD_VERSION", current_version.to_string()))
.add_env(("BUMP_TYPE", bump_type.to_string()));
.add_env(("BUMP_TYPE", bump_type.to_string()))
.add_env(("WORKING_DIR", "${{ inputs.working-directory }}"));
let new_version = StepOutput::new(&step, "new_version");
(step, new_version)
let title = StepOutput::new(&step, "title");
let body = StepOutput::new(&step, "body");
let branch_name = StepOutput::new(&step, "branch_name");
(step, new_version, title, body, branch_name)
}
fn create_pull_request(new_version: StepOutput, generated_token: StepOutput) -> Step<Use> {
let formatted_version = format!("v{new_version}");
fn create_pull_request(
title: StepOutput,
body: StepOutput,
generated_token: StepOutput,
branch_name: StepOutput,
) -> Step<Use> {
named::uses("peter-evans", "create-pull-request", "v7").with(
Input::default()
.add("title", format!("Bump version to {new_version}"))
.add(
"body",
format!("This PR bumps the version of this extension to {formatted_version}",),
)
.add(
"commit-message",
format!("Bump version to {formatted_version}"),
)
.add("branch", "zed-zippy-autobump")
.add("title", title.to_string())
.add("body", body.to_string())
.add("commit-message", title.to_string())
.add("branch", branch_name.to_string())
.add(
"committer",
"zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com>",
@ -328,6 +365,7 @@ fn trigger_release(
let (get_extension_id, extension_id) = get_extension_id();
let job = dependant_job(dependencies)
.defaults(extension_job_defaults())
.with_repository_owner_guard()
.runs_on(runners::LINUX_SMALL)
.add_step(generate_token)

View file

@ -3,15 +3,13 @@ use indoc::indoc;
use crate::tasks::workflows::{
extension_bump::compare_versions,
run_tests::{
fetch_ts_query_ls, orchestrate_without_package_filter, run_ts_query_ls, tests_pass,
},
run_tests::{fetch_ts_query_ls, orchestrate_for_extension, run_ts_query_ls, tests_pass},
runners,
steps::{
self, CommonJobConditions, FluentBuilder, NamedJob, cache_rust_dependencies_namespace,
named,
self, BASH_SHELL, CommonJobConditions, FluentBuilder, NamedJob,
cache_rust_dependencies_namespace, named,
},
vars::{PathCondition, StepOutput, one_workflow_per_non_main_branch},
vars::{PathCondition, StepOutput, WorkflowInput, one_workflow_per_non_main_branch},
};
pub(crate) const ZED_EXTENSION_CLI_SHA: &str = "03d8e9aee95ea6117d75a48bcac2e19241f6e667";
@ -25,8 +23,10 @@ pub(crate) fn extension_tests() -> Workflow {
let should_check_extension =
PathCondition::new("check_extension", r"^(extension\.toml|.*\.scm)$");
let orchestrate =
orchestrate_without_package_filter(&[&should_check_rust, &should_check_extension]);
let orchestrate = with_extension_defaults(orchestrate_for_extension(&[
&should_check_rust,
&should_check_extension,
]));
let jobs = [
orchestrate,
@ -34,10 +34,17 @@ pub(crate) fn extension_tests() -> Workflow {
should_check_extension.guard(check_extension()),
];
let tests_pass = tests_pass(&jobs);
let tests_pass = with_extension_defaults(tests_pass(&jobs));
let working_directory = WorkflowInput::string("working-directory", Some(".".to_owned()));
named::workflow()
.add_event(Event::default().workflow_call(WorkflowCall::default()))
.add_event(
Event::default().workflow_call(
WorkflowCall::default()
.add_input(working_directory.name, working_directory.call_input()),
),
)
.concurrency(one_workflow_per_non_main_branch())
.add_env(("CARGO_TERM_COLOR", "always"))
.add_env(("RUST_BACKTRACE", 1))
@ -58,27 +65,66 @@ fn install_rust_target() -> Step<Run> {
named::bash(format!("rustup target add {EXTENSION_RUST_TARGET}",))
}
fn run_clippy() -> Step<Run> {
named::bash("cargo clippy --release --all-features -- --deny warnings")
fn get_package_name() -> (Step<Run>, StepOutput) {
let step = named::bash(indoc! {r#"
PACKAGE_NAME="$(sed -n 's/^name = "\(.*\)"/\1/p' < Cargo.toml | head -1 | tr -d '[:space:]')"
echo "package_name=${PACKAGE_NAME}" >> "$GITHUB_OUTPUT"
"#})
.id("get-package-name");
let output = StepOutput::new(&step, "package_name");
(step, output)
}
fn cargo_fmt_package(package_name: &StepOutput) -> Step<Run> {
named::bash(r#"cargo fmt -p "$PACKAGE_NAME" -- --check"#)
.add_env(("PACKAGE_NAME", package_name.to_string()))
}
fn run_clippy(package_name: &StepOutput) -> Step<Run> {
named::bash(r#"cargo clippy -p "$PACKAGE_NAME" --release --all-features -- --deny warnings"#)
.add_env(("PACKAGE_NAME", package_name.to_string()))
}
fn run_nextest(package_name: &StepOutput) -> Step<Run> {
named::bash(
r#"cargo nextest run -p "$PACKAGE_NAME" --no-fail-fast --no-tests=warn --target "$(rustc -vV | sed -n 's|host: ||p')""#,
)
.add_env(("PACKAGE_NAME", package_name.to_string()))
.add_env(("NEXTEST_NO_TESTS", "warn"))
}
fn extension_job_defaults() -> Defaults {
Defaults::default().run(
RunDefaults::default()
.shell(BASH_SHELL)
.working_directory("${{ inputs.working-directory }}"),
)
}
fn with_extension_defaults(named_job: NamedJob) -> NamedJob {
NamedJob {
name: named_job.name,
job: named_job.job.defaults(extension_job_defaults()),
}
}
fn check_rust() -> NamedJob {
let (get_package, package_name) = get_package_name();
let job = Job::default()
.defaults(extension_job_defaults())
.with_repository_owner_guard()
.runs_on(runners::LINUX_LARGE_RAM)
.timeout_minutes(6u32)
.add_step(steps::checkout_repo())
.add_step(steps::cache_rust_dependencies_namespace())
.add_step(install_rust_target())
.add_step(steps::cargo_fmt())
.add_step(run_clippy())
.add_step(get_package)
.add_step(cargo_fmt_package(&package_name))
.add_step(run_clippy(&package_name))
.add_step(steps::cargo_install_nextest())
.add_step(
steps::cargo_nextest(runners::Platform::Linux)
// Set the target to the current platform again
.with_target("$(rustc -vV | sed -n 's|host: ||p')")
.add_env(("NEXTEST_NO_TESTS", "warn")),
);
.add_step(run_nextest(&package_name));
named::job(job)
}
@ -88,6 +134,7 @@ pub(crate) fn check_extension() -> NamedJob {
let (check_version_job, version_changed, _) = compare_versions();
let job = Job::default()
.defaults(extension_job_defaults())
.with_repository_owner_guard()
.runs_on(runners::LINUX_LARGE_RAM)
.timeout_minutes(6u32)
@ -124,8 +171,8 @@ pub fn download_zed_extension_cli(cache_hit: StepOutput) -> Step<Run> {
named::bash(
indoc! {
r#"
wget --quiet "https://zed-extension-cli.nyc3.digitaloceanspaces.com/$ZED_EXTENSION_CLI_SHA/x86_64-unknown-linux-gnu/zed-extension"
chmod +x zed-extension
wget --quiet "https://zed-extension-cli.nyc3.digitaloceanspaces.com/$ZED_EXTENSION_CLI_SHA/x86_64-unknown-linux-gnu/zed-extension" -O "$GITHUB_WORKSPACE/zed-extension"
chmod +x "$GITHUB_WORKSPACE/zed-extension"
"#,
}
).if_condition(Expression::new(format!("{} != 'true'", cache_hit.expr())))
@ -136,7 +183,7 @@ pub fn check() -> Step<Run> {
r#"
mkdir -p /tmp/ext-scratch
mkdir -p /tmp/ext-output
./zed-extension --source-dir . --scratch-dir /tmp/ext-scratch --output-dir /tmp/ext-output
"$GITHUB_WORKSPACE/zed-extension" --source-dir . --scratch-dir /tmp/ext-scratch --output-dir /tmp/ext-output
"#
})
}

View file

@ -127,8 +127,9 @@ fn fetch_extension_repos(filter_repos_input: &WorkflowInput) -> (NamedJob, JobOu
.id("calc-changes")
.add_env(("PREV_COMMIT", prev_commit.to_string()));
let removed_ci = StepOutput::new(&step, "removed_ci");
let removed_shared = StepOutput::new(&step, "removed_shared");
// These are created in the for-loop above and thus do exist
let removed_ci = StepOutput::new_unchecked(&step, "removed_ci");
let removed_shared = StepOutput::new_unchecked(&step, "removed_shared");
(step, removed_ci, removed_shared)
}

View file

@ -97,14 +97,18 @@ pub(crate) fn run_tests() -> Workflow {
// Generates a bash script that checks changed files against regex patterns
// and sets GitHub output variables accordingly
pub fn orchestrate(rules: &[&PathCondition]) -> NamedJob {
orchestrate_impl(rules, true)
orchestrate_impl(rules, true, false)
}
pub fn orchestrate_without_package_filter(rules: &[&PathCondition]) -> NamedJob {
orchestrate_impl(rules, false)
pub fn orchestrate_for_extension(rules: &[&PathCondition]) -> NamedJob {
orchestrate_impl(rules, false, true)
}
fn orchestrate_impl(rules: &[&PathCondition], include_package_filter: bool) -> NamedJob {
fn orchestrate_impl(
rules: &[&PathCondition],
include_package_filter: bool,
filter_by_working_directory: bool,
) -> NamedJob {
let name = "orchestrate".to_owned();
let step_name = "filter".to_owned();
let mut script = String::new();
@ -121,6 +125,22 @@ fn orchestrate_impl(rules: &[&PathCondition], include_package_filter: bool) -> N
fi
CHANGED_FILES="$(git diff --name-only "$COMPARE_REV" "$GITHUB_SHA")"
"#});
if filter_by_working_directory {
script.push_str(indoc::indoc! {r#"
# When running from a subdirectory, git diff returns repo-root-relative paths.
# Filter to only files within the current working directory and strip the prefix.
REPO_SUBDIR="$(git rev-parse --show-prefix)"
REPO_SUBDIR="${REPO_SUBDIR%/}"
if [ -n "$REPO_SUBDIR" ]; then
CHANGED_FILES="$(echo "$CHANGED_FILES" | grep "^${REPO_SUBDIR}/" | sed "s|^${REPO_SUBDIR}/||" || true)"
fi
"#});
}
script.push_str(indoc::indoc! {r#"
check_pattern() {
local output_name="$1"
local pattern="$2"
@ -298,8 +318,8 @@ pub(crate) fn fetch_ts_query_ls() -> Step<Use> {
pub(crate) fn run_ts_query_ls() -> Step<Run> {
named::bash(formatdoc!(
r#"tar -xf {TS_QUERY_LS_FILE}
./ts_query_ls format --check . || {{
r#"tar -xf "$GITHUB_WORKSPACE/{TS_QUERY_LS_FILE}" -C "$GITHUB_WORKSPACE"
"$GITHUB_WORKSPACE/ts_query_ls" format --check . || {{
echo "Found unformatted queries, please format them with ts_query_ls."
echo "For easy use, install the Tree-sitter query extension:"
echo "zed://extension/tree-sitter-query"

View file

@ -10,7 +10,7 @@ pub(crate) fn use_clang(job: Job) -> Job {
const SCCACHE_R2_BUCKET: &str = "sccache-zed";
const BASH_SHELL: &str = "bash -euxo pipefail {0}";
pub(crate) const BASH_SHELL: &str = "bash -euxo pipefail {0}";
// https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idstepsshell
pub const PWSH_SHELL: &str = "pwsh";
@ -24,13 +24,6 @@ pub(crate) fn cargo_nextest(platform: Platform) -> Nextest {
}
impl Nextest {
pub(crate) fn with_target(mut self, target: &str) -> Step<Run> {
if let Some(nextest_command) = self.0.value.run.as_mut() {
nextest_command.push_str(&format!(r#" --target "{target}""#));
}
self.into()
}
#[allow(dead_code)]
pub(crate) fn with_filter_expr(mut self, filter_expr: &str) -> Self {
if let Some(nextest_command) = self.0.value.run.as_mut() {

View file

@ -156,14 +156,31 @@ pub(crate) struct StepOutput {
impl StepOutput {
pub fn new<T>(step: &Step<T>, name: &'static str) -> Self {
Self {
name,
step_id: step
.value
.id
.clone()
.expect("Steps that produce outputs must have an ID"),
}
let step_id = step
.value
.id
.clone()
.expect("Steps that produce outputs must have an ID");
assert!(
step.value
.run
.as_ref()
.is_none_or(|run_command| run_command.contains(name)),
"Step Output name {name} must occur at least once in run command with ID {step_id}!"
);
Self { name, step_id }
}
pub fn new_unchecked<T>(step: &Step<T>, name: &'static str) -> Self {
let step_id = step
.value
.id
.clone()
.expect("Steps that produce outputs must have an ID");
Self { name, step_id }
}
pub fn expr(&self) -> String {