ci: Verify commits and releases created with Zed Zippy (#54264)

Finn Evers created

This changes our approach for creating Zed version bumps with the Zed
Zippy identity:

With these changes, the Zippy version bumps as well as the tag creations
will be verified as per
https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification#signature-verification-for-bots.
This adds an extra layer of security for version bumps and release
triggers done by the Zippy identity.

Eventually, we can move code more around for this so it happens in the
bot itself, but for now, I think its a good and solid interim solution
to have this here.

Release Notes:

- N/A

Change summary

.github/workflows/bump_patch_version.yml                | 34 +++-
tooling/xtask/src/tasks/workflows/bump_patch_version.rs | 76 ++++++++--
2 files changed, 83 insertions(+), 27 deletions(-)

Detailed changes

.github/workflows/bump_patch_version.yml 🔗

@@ -25,7 +25,8 @@ jobs:
         clean: false
         ref: ${{ inputs.branch }}
         token: ${{ steps.generate-token.outputs.token }}
-    - name: bump_patch_version::run_bump_patch_version::bump_patch_version
+    - id: bump-version
+      name: bump_patch_version::run_bump_patch_version::bump_version
       run: |
         channel="$(cat crates/zed/RELEASE_CHANNEL)"
 
@@ -42,16 +43,27 @@ jobs:
             ;;
         esac
         which cargo-set-version > /dev/null || cargo install cargo-edit -f --no-default-features --features "set-version"
-        output="$(cargo set-version -p zed --bump patch 2>&1 | sed 's/.* //')"
-        git commit -am "Bump to $output for @$GITHUB_ACTOR"
-        git tag "v${output}${tag_suffix}"
-        git push origin HEAD "v${output}${tag_suffix}"
-      env:
-        GIT_COMMITTER_NAME: Zed Zippy
-        GIT_COMMITTER_EMAIL: 234243425+zed-zippy[bot]@users.noreply.github.com
-        GIT_AUTHOR_NAME: Zed Zippy
-        GIT_AUTHOR_EMAIL: 234243425+zed-zippy[bot]@users.noreply.github.com
-        GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
+        version="$(cargo set-version -p zed --bump patch 2>&1 | sed 's/.* //')"
+        echo "version=$version" >> "$GITHUB_OUTPUT"
+        echo "tag_suffix=$tag_suffix" >> "$GITHUB_OUTPUT"
+    - id: commit
+      name: bump_patch_version::run_bump_patch_version::commit_changes
+      uses: IAreKyleW00t/verified-bot-commit@126a6a11889ab05bcff72ec2403c326cd249b84c
+      with:
+        message: Bump to ${{ steps.bump-version.outputs.version }} for @${{ github.actor }}
+        files: '**'
+        token: ${{ steps.generate-token.outputs.token }}
+    - name: bump_patch_version::run_bump_patch_version::create_version_tag
+      uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b
+      with:
+        script: |
+          github.rest.git.createRef({
+              owner: context.repo.owner,
+              repo: context.repo.repo,
+              ref: 'refs/tags/v${{ steps.bump-version.outputs.version }}${{ steps.bump-version.outputs.tag_suffix }}',
+              sha: '${{ steps.commit.outputs.commit }}'
+          })
+        github-token: ${{ steps.generate-token.outputs.token }}
 concurrency:
   group: ${{ github.workflow }}-${{ inputs.branch }}
   cancel-in-progress: true

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

@@ -28,7 +28,7 @@ fn run_bump_patch_version(branch: &WorkflowInput) -> steps::NamedJob {
             .with_ref(branch.to_string())
     }
 
-    fn bump_patch_version(token: &StepOutput) -> Step<Run> {
+    fn bump_version() -> Step<Run> {
         named::bash(indoc::indoc! {r#"
             channel="$(cat crates/zed/RELEASE_CHANNEL)"
 
@@ -45,25 +45,62 @@ fn run_bump_patch_version(branch: &WorkflowInput) -> steps::NamedJob {
                 ;;
             esac
             which cargo-set-version > /dev/null || cargo install cargo-edit -f --no-default-features --features "set-version"
-            output="$(cargo set-version -p zed --bump patch 2>&1 | sed 's/.* //')"
-            git commit -am "Bump to $output for @$GITHUB_ACTOR"
-            git tag "v${output}${tag_suffix}"
-            git push origin HEAD "v${output}${tag_suffix}"
+            version="$(cargo set-version -p zed --bump patch 2>&1 | sed 's/.* //')"
+            echo "version=$version" >> "$GITHUB_OUTPUT"
+            echo "tag_suffix=$tag_suffix" >> "$GITHUB_OUTPUT"
         "#})
-        .add_env(("GIT_COMMITTER_NAME", "Zed Zippy"))
-        .add_env((
-            "GIT_COMMITTER_EMAIL",
-            "234243425+zed-zippy[bot]@users.noreply.github.com",
-        ))
-        .add_env(("GIT_AUTHOR_NAME", "Zed Zippy"))
-        .add_env((
-            "GIT_AUTHOR_EMAIL",
-            "234243425+zed-zippy[bot]@users.noreply.github.com",
+        .id("bump-version")
+    }
+
+    fn commit_changes(version: &StepOutput, token: &StepOutput) -> Step<Use> {
+        named::uses(
+            "IAreKyleW00t",
+            "verified-bot-commit",
+            "126a6a11889ab05bcff72ec2403c326cd249b84c", // v2.3.0
+        )
+        .id("commit")
+        .add_with((
+            "message",
+            format!("Bump to {version} for @${{{{ github.actor }}}}"),
         ))
-        .add_env(("GITHUB_TOKEN", token))
+        .add_with(("files", "**"))
+        .add_with(("token", token.to_string()))
+    }
+
+    fn create_version_tag(
+        version: &StepOutput,
+        tag_suffix: &StepOutput,
+        commit_sha: &StepOutput,
+        token: &StepOutput,
+    ) -> Step<Use> {
+        named::uses(
+            "actions",
+            "github-script",
+            "f28e40c7f34bde8b3046d885e986cb6290c5673b", // v7
+        )
+        .with(
+            Input::default()
+                .add(
+                    "script",
+                    indoc::formatdoc! {r#"
+                        github.rest.git.createRef({{
+                            owner: context.repo.owner,
+                            repo: context.repo.repo,
+                            ref: 'refs/tags/v{version}{tag_suffix}',
+                            sha: '{commit_sha}'
+                        }})
+                    "#},
+                )
+                .add("github-token", token.to_string()),
+        )
     }
 
     let (authenticate, token) = steps::authenticate_as_zippy().into();
+    let bump_version_step = bump_version();
+    let version = StepOutput::new(&bump_version_step, "version");
+    let tag_suffix = StepOutput::new(&bump_version_step, "tag_suffix");
+    let commit_step = commit_changes(&version, &token);
+    let commit_sha = StepOutput::new_unchecked(&commit_step, "commit");
 
     named::job(
         Job::default()
@@ -73,6 +110,13 @@ fn run_bump_patch_version(branch: &WorkflowInput) -> steps::NamedJob {
             .runs_on(runners::LINUX_XL)
             .add_step(authenticate)
             .add_step(checkout_branch(branch, &token))
-            .add_step(bump_patch_version(&token)),
+            .add_step(bump_version_step)
+            .add_step(commit_step)
+            .add_step(create_version_tag(
+                &version,
+                &tag_suffix,
+                &commit_sha,
+                &token,
+            )),
     )
 }