Repository: axodotdev/cargo-dist
Pull request #443 (2023-09-20 23:52:02)

docs: document new CI features
This begins a new section in the documentation with the new features from CI++, including PR release builds and custom publish jobs.

I felt that there's enough detail here it's worth a new section in the docs, in particular as we start extending it with new features and CI backends other than GitHub.

Although these are tagged with the appropriate version, we should still avoid merging this until closer to feature availability.


Patch:
diff --git a/.github/workflows/append-release.yml b/.github/workflows/append-release.yml
index 4682091f..185d8338 100644
--- a/.github/workflows/append-release.yml
+++ b/.github/workflows/append-release.yml
@@ -49,7 +49,7 @@ jobs:
     if: ${{ needs.should-run.outputs.val == 'run' }}
     steps:
       # Setup
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           ref: ${{ github.event.workflow_run.head_branch }}
           fetch-depth: 0
diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml
index d5d84204..adbfa2cb 100644
--- a/.github/workflows/publish-release.yml
+++ b/.github/workflows/publish-release.yml
@@ -32,7 +32,7 @@ jobs:
     needs: download-tag
     steps:
       - name: Checkout sources
-        uses: actions/checkout@v4
+        uses: actions/checkout@v3
         with:
           ref: ${{needs.download-tag.outputs.tag}}
           fetch-depth: 0
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index b73eb25d..b12d5256 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -7,6 +7,7 @@
   - [A Simple Application](./simple-guide.md)
   - [More Complex Workspaces](./workspace-guide.md)
   - [Using cargo-release](./cargo-release-guide.md)
+- [Customizing CI](./customizing-ci.md)
 - [Reference](./reference.md)
   - [Concepts](./concepts.md)
   - [Config](./config.md)
diff --git a/book/src/customizing-ci.md b/book/src/customizing-ci.md
new file mode 100644
index 00000000..e9a22baa
--- /dev/null
+++ b/book/src/customizing-ci.md
@@ -0,0 +1,63 @@
+# Customizing CI
+
+Out of the box, cargo-dist's CI configuration is designed to cover the majority of usecases. We provide some tools to customize how it works for your project.
+
+## Build and upload artifacts on every pull request
+
+> since 0.3.0
+
+By default, cargo-dist will run the plan step on every pull request but won't perform a full release build. If these builds are turned on, the resulting pull request artifacts won't be uploaded to a release but will be available as a download from within the CI job. To enable this, select the "upload" option from the "check your release process in pull requests" question in `cargo-dist-init` or set the `pr-run-mode` key to `"upload"` in `Cargo.toml`'s cargo-dist config. For example:
+
+```toml
+pr-run-mode = "upload"
+```
+
+## Custom jobs
+
+> since 0.3.0
+
+cargo-dist's CI can be configured to call additional jobs on top of the ones it has builtin. Currently, we support adding extra jobs to the publish step; in the future, we'll allow extending all of the lifecycle steps of the CI workflow. To add one, you need to follow two steps:
+
+1. Define the new job as a reusable workflow using the standard method defined by your CI system. For GitHub actions, see the documentation on [reusable workflows](https://docs.github.com/en/actions/using-workflows/reusing-workflows#creating-a-reusable-workflow).
+2. Add the name of your new workflow file to the `publish-jobs` array in your `Cargo.toml`'s cargo-dist config, prefixed with a `./`. For example, if your job name is `.github/workflows/my-publish.yml`, you would write it like this:
+
+```toml
+publish-jobs = ["./my-publish"]
+```
+
+Here's an example reusable workflow written using GitHub Actions. It won't do any real publishing, just echo text to the CI output. First, create a file named `.github/workflows/publish-greeter.yml` with these contents:
+
+```yaml
+name: Greeter
+
+on:
+  # Defining workflow_call means that this workflow can be called from
+  # your main workflow job
+  workflow_call:
+    # cargo-dist exposes the plan from the plan step, as a JSON string,
+    # to your job if it needs it
+    inputs:
+      plan:
+        required: true
+        type: string
+
+jobs:
+  greeter:
+    runs-on: ubuntu-latest
+    # This is optional; it exposes the plan to your job as an environment variable
+    env:
+      PLAN: ${{ inputs.plan }}
+    steps:
+      - name: Step 1
+        run: |
+          echo "Hello!"
+          echo "Plan is: ${PLAN}"
+```
+
+Then, add the following to your `publish-jobs` array:
+
+```toml
+publish-jobs = ["./publish-greeter"]
+```
+
+Running `cargo-dist init` for your tool will update your GitHub Actions configuration to make use of the new reusable workflow during the publish step.
diff --git a/cargo-dist/src/init.rs b/cargo-dist/src/init.rs
index 923c544b..fca5ebeb 100644
--- a/cargo-dist/src/init.rs
+++ b/cargo-dist/src/init.rs
@@ -1,5 +1,7 @@
+use std::ops::Not;
+
+use axoproject::errors::AxoprojectError;
 use axoproject::WorkspaceInfo;
-use axoproject::{errors::AxoprojectError, platforms::triple_to_display_name};
 use camino::Utf8PathBuf;
 use cargo_dist_schema::PrRunMode;
 use semver::Version;
@@ -50,9 +52,16 @@ pub fn do_init(cfg: &Config, args: &InitArgs) -> Result<()> {
     let check = console::style("✔".to_string()).for_stderr().green();
 
     // Init things
-    let did_add_profile = init_dist_profile(cfg, &mut workspace_toml)?;
+    eprintln!("first let's setup your cargo build profile...");
+    eprintln!();
+    if init_dist_profile(cfg, &mut workspace_toml)? {
+        eprintln!("{check} added [profile.dist] to your root Cargo.toml");
+    } else {
+        eprintln!("{check} [profile.dist] already exists");
+    }
+    eprintln!();
 
-    eprintln!("let's setup your cargo-dist config...");
+    eprintln!("next let's setup your cargo-dist config...");
     eprintln!();
 
     let multi_meta = if let Some(json_path) = &args.with_json_config {
@@ -74,14 +83,10 @@ pub fn do_init(cfg: &Config, args: &InitArgs) -> Result<()> {
         apply_dist_to_metadata(metadata, meta);
     }
 
-    eprintln!();
-
     // Save the workspace toml (potentially an effective no-op if we made no edits)
     config::save_cargo_toml(&workspace.manifest_path, workspace_toml)?;
-    if did_add_profile {
-        eprintln!("{check} added [profile.dist] to your root Cargo.toml");
-    }
     eprintln!("{check} added [workspace.metadata.dist] to your root Cargo.toml");
+    eprintln!();
 
     // Now that we've done the stuff that's definitely part of the root Cargo.toml,
     // Optionally apply updates to packages
@@ -96,36 +101,35 @@ pub fn do_init(cfg: &Config, args: &InitArgs) -> Result<()> {
             let metadata = config::get_toml_metadata(&mut package_toml, false);
 
             // Apply [package.metadata.dist]
-            let mut writing_metadata = false;
             if let Some(meta) = meta {
                 apply_dist_to_metadata(metadata, meta);
-                writing_metadata = true;
-            }
-
-            // Save the result
-            config::save_cargo_toml(&package.manifest_path, package_toml)?;
-            if writing_metadata {
                 eprintln!(
                     "{check} added [package.metadata.dist] to {}'s Cargo.toml",
                     package.name
                 );
             }
+
+            // Save the result
+            eprintln!();
+            config::save_cargo_toml(&package.manifest_path, package_toml)?;
         }
     }
 
     eprintln!("{check} cargo-dist is setup!");
     eprintln!();
 
-    // regenerate anything that needs to be
-    if !args.no_generate_ci {
-        eprintln!("running 'cargo dist generate' to apply any changes");
-        eprintln!();
+    // If there's CI stuff, regenerate it
+    if let Some(ci) = multi_meta.workspace.as_ref().and_then(|w| w.ci.as_ref()) {
+        if !ci.is_empty() && !args.no_generate_ci {
+            eprintln!("running 'cargo dist generate-ci' to apply any changes to your CI scripts");
+            eprintln!();
 
-        let ci_args = GenerateArgs {
-            check: false,
-            modes: vec![],
-        };
-        do_generate(cfg, &ci_args)?;
+            let ci_args = GenerateArgs {
+                check: false,
+                modes: vec![],
+            };
+            do_generate(cfg, &ci_args)?;
+        }
     }
     Ok(())
 }
@@ -201,7 +205,7 @@ fn get_new_dist_metadata(
             ci: None,
             installers: None,
             tap: None,
-            targets: None,
+            targets: cfg.targets.is_empty().not().then(|| cfg.targets.clone()),
             dist: None,
             include: None,
             auto_includes: None,
@@ -297,69 +301,8 @@ fn get_new_dist_metadata(
         }
     }
 
-    {
-        // Start with builtin targets
-        let default_platforms = crate::default_desktop_targets();
-        let mut known = default_platforms.clone();
-        // If the config doesn't have targets at all, generate them
-        let config_vals = meta.targets.as_deref().unwrap_or(&default_platforms);
-        let cli_vals = cfg.targets.as_slice();
-        // Add anything custom they did to the list (this will do some reordering if they hand-edited)
-        for val in config_vals.iter().chain(cli_vals) {
-            if !known.contains(val) {
-                known.push(val.clone());
-            }
-        }
-
-        // Prettify/sort things
-        let desc = move |triple: &str| -> String {
-            let pretty = triple_to_display_name(triple).unwrap_or("[unknown]");
-            format!("{pretty} ({triple})")
-        };
-        known.sort_by_cached_key(|k| desc(k).to_uppercase());
-
-        let mut defaults = vec![];
-        let mut keys = vec![];
-        for item in &known {
-            // If this target is in their config, keep it
-            // If they passed it on the CLI, flip it on
-            let config_had_it = config_vals.contains(item);
-            let cli_had_it = cli_vals.contains(item);
-
-            let default = config_had_it || cli_had_it;
-            defaults.push(default);
-
-            keys.push(desc(item));
-        }
-
-        // Prompt the user
-        let prompt = r#"what platforms do you want to build for?
-    (select with arrow keys and space, submit with enter)"#;
-        let selected = if args.yes {
-            defaults
-                .iter()
-                .enumerate()
-                .filter_map(|(idx, enabled)| enabled.then_some(idx))
-                .collect()
-        } else {
-            let res = MultiSelect::with_theme(&theme)
-                .items(&keys)
-                .defaults(&defaults)
-                .with_prompt(prompt)
-                .interact()?;
-            eprintln!();
-            res
-        };
-
-        // Apply the results
-        meta.targets = Some(selected.into_iter().map(|i| known[i].clone()).collect());
-    }
-
     // Enable CI backends
-    // FIXME: when there is more than one option we maybe shouldn't hide this
-    // once the user has any one enabled, right now it's just annoying to always
-    // prompt for Github CI support.
-    if meta.ci.as_deref().unwrap_or_default().is_empty() {
+    {
         // FIXME: when there is more than one option this should be a proper
         // multiselect like the installer selector is! For now we do
         // most of the multi-select logic and then just give a prompt.
@@ -396,7 +339,10 @@ fn get_new_dist_metadata(
         }
 
         // Prompt the user
-        let prompt = r#"enable Github CI and Releases?"#;
+        let prompt = r#"enable Github CI integration?
+    this creates a CI action which automates creating a Github Release,
+    builds all your binaries/archives, and then uploads them to the Release
+    it also unlocks the ability to generate installers which fetch those artifacts"#;
         let default = defaults[github_key];
 
         let github_selected = if args.yes {
@@ -457,7 +403,7 @@ fn get_new_dist_metadata(
         }
     }
 
-    if has_github_ci && meta.pr_run_mode.is_none() {
+    if has_github_ci {
         let default_val = PrRunMode::default();
         let cur_val = meta.pr_run_mode.unwrap_or(default_val);
 
@@ -487,28 +433,25 @@ fn get_new_dist_metadata(
 
         let result = items[selection];
 
-        // Record that the user made a concrete decision so we don't prompt over and over
-        meta.pr_run_mode = Some(result);
+        // Don't add needlessly noisy config if it's just the default
+        meta.pr_run_mode = if result == default_val {
+            None
+        } else {
+            Some(result)
+        };
     }
 
     // Enable installer backends (if they have a CI backend that can provide URLs)
     // FIXME: "vendored" installers like msi could be enabled without any CI...
     let has_ci = meta.ci.as_ref().map(|ci| !ci.is_empty()).unwrap_or(false);
-    {
-        // If they have CI, then they can use fetching installers,
-        // otherwise they can only do vendored installers.
-        let known: &[InstallerStyle] = if has_ci {
-            &[
-                InstallerStyle::Shell,
-                InstallerStyle::Powershell,
-                InstallerStyle::Npm,
-                InstallerStyle::Homebrew,
-                InstallerStyle::Msi,
-            ]
-        } else {
-            eprintln!("{notice} no CI backends enabled, most installers have been hidden");
-            &[InstallerStyle::Msi]
-        };
+    if has_ci {
+        let known = &[
+            InstallerStyle::Shell,
+            InstallerStyle::Powershell,
+            InstallerStyle::Npm,
+            InstallerStyle::Homebrew,
+            InstallerStyle::Msi,
+        ];
         let mut defaults = vec![];
         let mut keys = vec![];
         for item in known {
@@ -536,7 +479,9 @@ fn get_new_dist_metadata(
         }
 
         // Prompt the user
-        let prompt = r#"what installers do you want to build?
+        let prompt = r#"enable generating installers?
+    installers streamline fetching your app's prebuilt artifacts
+    see the docs for details on each one
     (select with arrow keys and space, submit with enter)"#;
         let selected = if args.yes {
             defaults
@@ -556,6 +501,9 @@ fn get_new_dist_metadata(
 
         // Apply the results
         meta.installers = Some(selected.into_iter().map(|i| known[i]).collect());
+    } else {
+        eprintln!("{notice} no CI backends enabled, skipping installers");
+        eprintln!();
     }
 
     let mut publish_jobs = orig_meta.publish_jobs.clone().unwrap_or(vec![]);
diff --git a/cargo-dist/src/lib.rs b/cargo-dist/src/lib.rs
index 35f7a7b2..fa644490 100644
--- a/cargo-dist/src/lib.rs
+++ b/cargo-dist/src/lib.rs
@@ -753,18 +753,3 @@ fn generate_installer(dist: &DistGraph, style: &InstallerImpl) -> Result<()> {
     }
     Ok(())
 }
-
-/// Get the default list of targets
-pub fn default_desktop_targets() -> Vec<String> {
-    vec![
-        // Everyone can build x64!
-        axoproject::platforms::TARGET_X64_LINUX_GNU.to_owned(),
-        axoproject::platforms::TARGET_X64_WINDOWS.to_owned(),
-        axoproject::platforms::TARGET_X64_MAC.to_owned(),
-        // Apple is really easy to cross from Apple
-        axoproject::platforms::TARGET_ARM64_MAC.to_owned(),
-        // other cross-compiles not yet supported
-        // axoproject::platforms::TARGET_ARM64_LINUX_GNU.to_owned(),
-        // axoproject::platforms::TARGET_ARM64_WINDOWS.to_owned(),
-    ]
-}
diff --git a/cargo-dist/src/main.rs b/cargo-dist/src/main.rs
index 7c5f4baf..16aba48d 100644
--- a/cargo-dist/src/main.rs
+++ b/cargo-dist/src/main.rs
@@ -202,12 +202,18 @@ fn cmd_plan(cli: &Cli, _args: &PlanArgs) -> Result<(), miette::Report> {
 }
 
 fn cmd_init(cli: &Cli, args: &InitArgs) -> Result<(), miette::Report> {
+    // This command is more automagic, so provide default targets if none are chosen
+    let targets = if cli.target.is_empty() {
+        default_desktop_targets()
+    } else {
+        cli.target.clone()
+    };
     let config = cargo_dist::config::Config {
         needs_coherent_announcement_tag: false,
         artifact_mode: cargo_dist::config::ArtifactMode::All,
         no_local_paths: cli.no_local_paths,
         allow_all_dirty: cli.allow_dirty,
-        targets: cli.target.clone(),
+        targets,
         ci: cli.ci.iter().map(|ci| ci.to_lib()).collect(),
         installers: cli.installer.iter().map(|ins| ins.to_lib()).collect(),
         announcement_tag: cli.tag.clone(),
@@ -248,6 +254,20 @@ fn cmd_generate_ci(cli: &Cli, args: &GenerateCiArgs) -> Result<(), miette::Repor
     )
 }
 
+fn default_desktop_targets() -> Vec<String> {
+    vec![
+        // Everyone can build x64!
+        "x86_64-unknown-linux-gnu".to_owned(),
+        "x86_64-apple-darwin".to_owned(),
+        "x86_64-pc-windows-msvc".to_owned(),
+        // Apple is really easy to cross from Apple
+        "aarch64-apple-darwin".to_owned(),
+        // other cross-compiles not yet supported
+        // "aarch64-gnu-unknown-linux".to_owned(),
+        // "aarch64-pc-windows-msvc".to_owned(),
+    ]
+}
+
 fn cmd_help_md(_args: &Cli, _sub_args: &HelpMarkdownArgs) -> Result<(), miette::Report> {
     let mut out = Term::stdout();
     print_help_markdown(&mut out).into_diagnostic()
diff --git a/cargo-dist/templates/ci/github_ci.yml.j2 b/cargo-dist/templates/ci/github_ci.yml.j2
index 0384fb98..ae1cb0b4 100644
--- a/cargo-dist/templates/ci/github_ci.yml.j2
+++ b/cargo-dist/templates/ci/github_ci.yml.j2
@@ -62,7 +62,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       {{%- if rust_version %}}
@@ -105,7 +105,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       {{%- if rust_version %}}
@@ -145,7 +145,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       {{%- if rust_version %}}
@@ -264,7 +264,7 @@ jobs:
       GITHUB_EMAIL: "admin+bot@axo.dev"
     if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           repository: {{{ tap }}}
           token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
@@ -297,7 +297,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: "Download artifacts"


Test patch:
diff --git a/cargo-dist/tests/snapshots/akaikatana_basic.snap b/cargo-dist/tests/snapshots/akaikatana_basic.snap
index 3ef9e2a3..9475ef04 100644
--- a/cargo-dist/tests/snapshots/akaikatana_basic.snap
+++ b/cargo-dist/tests/snapshots/akaikatana_basic.snap
@@ -1325,7 +1325,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install Rust
@@ -1366,7 +1366,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install Rust
@@ -1402,7 +1402,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install Rust
@@ -1452,7 +1452,7 @@ jobs:
       GITHUB_EMAIL: "admin+bot@axo.dev"
     if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           repository: "mistydemeo/homebrew-formulae"
           token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
@@ -1483,7 +1483,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: "Download artifacts"
diff --git a/cargo-dist/tests/snapshots/akaikatana_repo_with_dot_git.snap b/cargo-dist/tests/snapshots/akaikatana_repo_with_dot_git.snap
index 3ef9e2a3..9475ef04 100644
--- a/cargo-dist/tests/snapshots/akaikatana_repo_with_dot_git.snap
+++ b/cargo-dist/tests/snapshots/akaikatana_repo_with_dot_git.snap
@@ -1325,7 +1325,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install Rust
@@ -1366,7 +1366,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install Rust
@@ -1402,7 +1402,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install Rust
@@ -1452,7 +1452,7 @@ jobs:
       GITHUB_EMAIL: "admin+bot@axo.dev"
     if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           repository: "mistydemeo/homebrew-formulae"
           token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
@@ -1483,7 +1483,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: "Download artifacts"
diff --git a/cargo-dist/tests/snapshots/axolotlsay_basic.snap b/cargo-dist/tests/snapshots/axolotlsay_basic.snap
index dc64667e..f4536723 100644
--- a/cargo-dist/tests/snapshots/axolotlsay_basic.snap
+++ b/cargo-dist/tests/snapshots/axolotlsay_basic.snap
@@ -2224,7 +2224,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install cargo-dist
@@ -2263,7 +2263,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - uses: swatinem/rust-cache@v2
@@ -2297,7 +2297,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install cargo-dist
@@ -2345,7 +2345,7 @@ jobs:
       GITHUB_EMAIL: "admin+bot@axo.dev"
     if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           repository: "axodotdev/homebrew-packages"
           token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
@@ -2376,7 +2376,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: "Download artifacts"
diff --git a/cargo-dist/tests/snapshots/axolotlsay_edit_existing.snap b/cargo-dist/tests/snapshots/axolotlsay_edit_existing.snap
index 4930a5c6..31647c49 100644
--- a/cargo-dist/tests/snapshots/axolotlsay_edit_existing.snap
+++ b/cargo-dist/tests/snapshots/axolotlsay_edit_existing.snap
@@ -2199,7 +2199,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install cargo-dist
@@ -2238,7 +2238,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - uses: swatinem/rust-cache@v2
@@ -2272,7 +2272,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install cargo-dist
@@ -2320,7 +2320,7 @@ jobs:
       GITHUB_EMAIL: "admin+bot@axo.dev"
     if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           repository: "axodotdev/homebrew-packages"
           token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
@@ -2351,7 +2351,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: "Download artifacts"
diff --git a/cargo-dist/tests/snapshots/axolotlsay_no_homebrew_publish.snap b/cargo-dist/tests/snapshots/axolotlsay_no_homebrew_publish.snap
index d72bbc9c..b5df6e90 100644
--- a/cargo-dist/tests/snapshots/axolotlsay_no_homebrew_publish.snap
+++ b/cargo-dist/tests/snapshots/axolotlsay_no_homebrew_publish.snap
@@ -2199,7 +2199,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install cargo-dist
@@ -2238,7 +2238,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - uses: swatinem/rust-cache@v2
@@ -2272,7 +2272,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install cargo-dist
@@ -2317,7 +2317,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: "Download artifacts"
diff --git a/cargo-dist/tests/snapshots/axolotlsay_ssldotcom_windows_sign.snap b/cargo-dist/tests/snapshots/axolotlsay_ssldotcom_windows_sign.snap
index b1ec1053..cfa6bd42 100644
--- a/cargo-dist/tests/snapshots/axolotlsay_ssldotcom_windows_sign.snap
+++ b/cargo-dist/tests/snapshots/axolotlsay_ssldotcom_windows_sign.snap
@@ -1317,7 +1317,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install cargo-dist
@@ -1356,7 +1356,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - uses: swatinem/rust-cache@v2
@@ -1390,7 +1390,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install cargo-dist
@@ -1490,7 +1490,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: "Download artifacts"
diff --git a/cargo-dist/tests/snapshots/axolotlsay_ssldotcom_windows_sign_prod.snap b/cargo-dist/tests/snapshots/axolotlsay_ssldotcom_windows_sign_prod.snap
index f6b97815..fc21ba4a 100644
--- a/cargo-dist/tests/snapshots/axolotlsay_ssldotcom_windows_sign_prod.snap
+++ b/cargo-dist/tests/snapshots/axolotlsay_ssldotcom_windows_sign_prod.snap
@@ -1317,7 +1317,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install cargo-dist
@@ -1356,7 +1356,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - uses: swatinem/rust-cache@v2
@@ -1390,7 +1390,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: Install cargo-dist
@@ -1490,7 +1490,7 @@ jobs:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v3
         with:
           submodules: recursive
       - name: "Download artifacts"