extension_ci: Bump update action and fix cache issues (#51716)

Finn Evers created

This PR bumps the update action again. It also fixes a bug where a cache
issue could occur during the extension auto bump and adds update
auto-merge for PRs from staff-members in zed-industries/extensions.

Release Notes:

- N/A

Change summary

.github/workflows/extension_bump.yml                | 61 ++++++++++
tooling/xtask/src/tasks/workflows/extension_bump.rs | 85 +++++++++++++-
2 files changed, 136 insertions(+), 10 deletions(-)

Detailed changes

.github/workflows/extension_bump.yml 🔗

@@ -105,7 +105,7 @@ jobs:
             --no-configured-files "$BUMP_TYPE" "${BUMP_FILES[@]}"
 
         if [[ -f "Cargo.toml" ]]; then
-            cargo update --workspace
+            cargo +stable update --workspace
         fi
 
         NEW_VERSION="$(sed -n 's/^version = \"\(.*\)\"/\1/p' < extension.toml | tr -d '[:space:]')"
@@ -229,14 +229,69 @@ jobs:
         EXTENSION_ID="$(sed -n 's/id = \"\(.*\)\"/\1/p' < extension.toml)"
 
         echo "extension_id=${EXTENSION_ID}" >> "$GITHUB_OUTPUT"
-    - name: extension_bump::release_action
-      uses: zed-extensions/update-action@1ef53b23be40fe2549be0baffaa98e9f51838fef
+    - id: extension-update
+      name: extension_bump::release_action
+      uses: zed-extensions/update-action@72da482880c2f32ec8aa6e0a0427ab92d52ae32d
       with:
         extension-name: ${{ steps.get-extension-id.outputs.extension_id }}
         push-to: zed-industries/extensions
         tag: ${{ needs.create_version_label.outputs.tag }}
       env:
         COMMITTER_TOKEN: ${{ steps.generate-token.outputs.token }}
+    - name: extension_bump::enable_automerge_if_staff
+      uses: actions/github-script@v7
+      with:
+        github-token: ${{ steps.generate-token.outputs.token }}
+        script: |
+          const prNumber = process.env.PR_NUMBER;
+          if (!prNumber) {
+              console.log('No pull request number set, skipping automerge.');
+              return;
+          }
+
+          const author = process.env.GITHUB_ACTOR;
+          let isStaff = false;
+          try {
+              const response = await github.rest.teams.getMembershipForUserInOrg({
+                  org: 'zed-industries',
+                  team_slug: 'staff',
+                  username: author
+              });
+              isStaff = response.data.state === 'active';
+          } catch (error) {
+              if (error.status !== 404) {
+                  throw error;
+              }
+          }
+
+          if (!isStaff) {
+              console.log(`Actor ${author} is not a staff member, skipping automerge.`);
+              return;
+          }
+
+
+          // Get the GraphQL node ID
+          const { data: pr } = await github.rest.pulls.get({
+              owner: 'zed-industries',
+              repo: 'extensions',
+              pull_number: parseInt(prNumber)
+          });
+
+          await github.graphql(`
+              mutation($pullRequestId: ID!) {
+                  enablePullRequestAutoMerge(input: { pullRequestId: $pullRequestId, mergeMethod: SQUASH }) {
+                      pullRequest {
+                          autoMergeRequest {
+                              enabledAt
+                          }
+                      }
+                  }
+              }
+          `, { pullRequestId: pr.node_id });
+
+          console.log(`Automerge enabled for PR #${prNumber} in zed-industries/extensions`);
+      env:
+        PR_NUMBER: ${{ steps.extension-update.outputs.pull-request-number }}
     defaults:
       run:
         shell: bash -euxo pipefail {0}

tooling/xtask/src/tasks/workflows/extension_bump.rs 🔗

@@ -316,7 +316,7 @@ fn bump_version(
             --no-configured-files "$BUMP_TYPE" "${{BUMP_FILES[@]}}"
 
         if [[ -f "Cargo.toml" ]]; then
-            cargo update --workspace
+            cargo +stable update --workspace
         fi
 
         NEW_VERSION="$({VERSION_CHECK})"
@@ -395,6 +395,7 @@ fn trigger_release(
         Some(extension_registry),
     );
     let (get_extension_id, extension_id) = get_extension_id();
+    let (release_action, pull_request_number) = release_action(extension_id, tag, &generated_token);
 
     let job = dependant_job(dependencies)
         .defaults(extension_job_defaults())
@@ -403,7 +404,11 @@ fn trigger_release(
         .add_step(generate_token)
         .add_step(checkout_repo())
         .add_step(get_extension_id)
-        .add_step(release_action(extension_id, tag, generated_token));
+        .add_step(release_action)
+        .add_step(enable_automerge_if_staff(
+            pull_request_number,
+            generated_token,
+        ));
 
     named::job(job)
 }
@@ -425,17 +430,83 @@ fn get_extension_id() -> (Step<Run>, StepOutput) {
 fn release_action(
     extension_id: StepOutput,
     tag: JobOutput,
-    generated_token: StepOutput,
-) -> Step<Use> {
-    named::uses(
+    generated_token: &StepOutput,
+) -> (Step<Use>, StepOutput) {
+    let step = named::uses(
         "zed-extensions",
         "update-action",
-        "1ef53b23be40fe2549be0baffaa98e9f51838fef",
+        "72da482880c2f32ec8aa6e0a0427ab92d52ae32d",
     )
+    .id("extension-update")
     .add_with(("extension-name", extension_id.to_string()))
     .add_with(("push-to", "zed-industries/extensions"))
     .add_with(("tag", tag.to_string()))
-    .add_env(("COMMITTER_TOKEN", generated_token.to_string()))
+    .add_env(("COMMITTER_TOKEN", generated_token.to_string()));
+
+    let pull_request_number = StepOutput::new(&step, "pull-request-number");
+
+    (step, pull_request_number)
+}
+
+fn enable_automerge_if_staff(
+    pull_request_number: StepOutput,
+    generated_token: StepOutput,
+) -> Step<Use> {
+    named::uses("actions", "github-script", "v7")
+        .add_with(("github-token", generated_token.to_string()))
+        .add_with((
+            "script",
+            indoc! {r#"
+                const prNumber = process.env.PR_NUMBER;
+                if (!prNumber) {
+                    console.log('No pull request number set, skipping automerge.');
+                    return;
+                }
+
+                const author = process.env.GITHUB_ACTOR;
+                let isStaff = false;
+                try {
+                    const response = await github.rest.teams.getMembershipForUserInOrg({
+                        org: 'zed-industries',
+                        team_slug: 'staff',
+                        username: author
+                    });
+                    isStaff = response.data.state === 'active';
+                } catch (error) {
+                    if (error.status !== 404) {
+                        throw error;
+                    }
+                }
+
+                if (!isStaff) {
+                    console.log(`Actor ${author} is not a staff member, skipping automerge.`);
+                    return;
+                }
+
+
+                // Get the GraphQL node ID
+                const { data: pr } = await github.rest.pulls.get({
+                    owner: 'zed-industries',
+                    repo: 'extensions',
+                    pull_number: parseInt(prNumber)
+                });
+
+                await github.graphql(`
+                    mutation($pullRequestId: ID!) {
+                        enablePullRequestAutoMerge(input: { pullRequestId: $pullRequestId, mergeMethod: SQUASH }) {
+                            pullRequest {
+                                autoMergeRequest {
+                                    enabledAt
+                                }
+                            }
+                        }
+                    }
+                `, { pullRequestId: pr.node_id });
+
+                console.log(`Automerge enabled for PR #${prNumber} in zed-industries/extensions`);
+            "#},
+        ))
+        .add_env(("PR_NUMBER", pull_request_number.to_string()))
 }
 
 fn extension_workflow_secrets() -> (WorkflowSecret, WorkflowSecret) {