From 6e8ea78761dab1c46f30880b83a6ae0e6a9f1237 Mon Sep 17 00:00:00 2001
From: Miles Johnson <milesj@users.noreply.github.com>
Date: Tue, 25 Apr 2023 10:16:40 -0700
Subject: [PATCH] new: Add `inherit-toolchain` input. (#6)

---
 CHANGELOG.md |  7 ++++++-
 README.md    | 42 +++++++++++++++++++++++++++++++-----------
 action.yml   |  3 +++
 package.json |  2 +-
 src/rust.ts  | 14 +++++++++++---
 5 files changed, 52 insertions(+), 16 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0dbeb4f..c0aa7bb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
-# Unreleased
+# 0.5.0
+
+- Added `inherit-toolchain` input to inherit all settings from `rust-toolchain.toml`, and not just
+  `channel`.
+
+# 0.1.0
 
 - Initial release.
diff --git a/README.md b/README.md
index 86af5ee..6de9c93 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
 # Setup Rust and Cargo
 
-A GitHub action for setting up Rust and Cargo.
+A one-stop-shop GitHub action for setting up Rust and Cargo. Will automatically setup the Rust
+toolchain with `rustup`, cache the `~/.cargo/registry` and `/target/debug` directories, and install
+Cargo binaries (when applicable).
 
 ```yaml
 jobs:
@@ -27,15 +29,16 @@ channel = "1.68.0"
 
 > When loading a configuration file, only the `channel` field is used, while the other fields are
 > ignored. We chose this approach, as those other fields are typically for develop/release
-> workflows, but not for CI, which requires a minimal/granular setup.
+> workflows, but not for CI, which requires a minimal/granular setup. However, this can be
+> overwritten with the `inherit-toolchain` input.
 
-The toolchain/channel can also be explicitly configured with the `toolchain` input, which takes
+The toolchain/channel can also be explicitly configured with the `channel` input, which takes
 highest precedence.
 
 ```yaml
 - uses: moonrepo/setup-rust@v0
   with:
-    toolchain: '1.65.0'
+    channel: '1.65.0'
 ```
 
 ### Profile and components
@@ -93,15 +96,16 @@ The following optimizations and considerations are taken into account when cachi
     crate, a checkout will be performed on-demand.
   - The `/registry` directory is _cleaned_ before saving the cache. This includes removing `src`,
     `.cache`, and any other unnecessary files.
-- `/target/debug`
-  - Only the `debug` profile is cached, as this profile is typically used for formatting, linting,
+- `/target`
+  - Only the `/debug` profile is cached, as this profile is typically used for formatting, linting,
     and testing.
-  - The `/examples` and `/incremental` directories are not cached as they are not necessary for CI.
+  - The `/examples` and `/incremental` sub-directories are not cached as they are not necessary for
+    CI.
   - All dep-info (`*.d`) files are removed, as they're meant for build systems and signaling
     re-executions.
 
-The following sources are hashed for the generated cache key: `$GITHUB_JOB`, `Cargo.lock`, Rust
-version, Rust commit hash, and OS.
+> The following sources are hashed for the generated cache key: `$GITHUB_JOB`, `Cargo.lock`, Rust
+> version, Rust commit hash, and OS.
 
 ## Compared to
 
@@ -124,10 +128,26 @@ However, this action _does not_:
 
 ### `dtolnay/rust-toolchain`
 
-This action is very similar to `dtolnay/rust-toolchain`, which was a great implementation reference,
-but this action also supports the following features:
+Our action is very similar to theirs, which was a great implementation reference, but our action
+also supports the following features:
 
 - Extracts the toolchain/channel from `rust-toolchain.toml` and `rust-toolchain` configuration
   files.
 - Automatically caches.
 - Installs Cargo bins.
+
+### `Swatinem/rust-cache`
+
+Their action only caches for Rust/Cargo, it doesn't actually setup Rust/Cargo. Our action is meant
+to do _everything_, but it's not as configurable as the alternatives.
+
+Here are the key differences between the two:
+
+- Theirs caches the entire `~/.cargo` directory, while our action only caches `~/.cargo/registry`.
+  [View the reasoning above](#caching-in-ci).
+  - Our action also avoids an array of `~/.cargo/bin` issues that theirs currently has.
+- Theirs includes compiler specific environment variables in the cache key, while our action
+  currently does not.
+- Theirs supports a handful of inputs for controlling the cache key, while ours does not.
+- Theirs is a bit more smart in what it caches, while ours is a bit more brute force. We simply
+  cache specific directories as-is after cleaning.
diff --git a/action.yml b/action.yml
index 8a52c54..9efcb4a 100644
--- a/action.yml
+++ b/action.yml
@@ -17,6 +17,9 @@ inputs:
     description: 'Comma-separated list of additional targets to install.'
   profile:
     description: 'Profile to install. Defaults to "minimal".'
+  inherit-toolchain:
+    description: 'Inherit all toolchain settings from the rust-toolchain.toml file.'
+    default: false
 outputs:
   cache-key:
     description: 'The generated cache key used.'
diff --git a/package.json b/package.json
index 93a9b44..dc4e6eb 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@moonrepo/setup-rust",
-  "version": "0.4.3",
+  "version": "0.5.0",
   "description": "A GitHub action for setting up Rust and Cargo.",
   "main": "dist/index.js",
   "scripts": {
diff --git a/src/rust.ts b/src/rust.ts
index a2a2459..6aac44f 100644
--- a/src/rust.ts
+++ b/src/rust.ts
@@ -69,10 +69,18 @@ export function parseConfig(configPath: string): Partial<Toolchain> {
 
 	const config = TOML.parse(contents) as unknown as ToolchainConfig;
 
-	if (config.toolchain.channel) {
-		core.debug('Found channel in [toolchain] section');
+	if (config.toolchain) {
+		if (core.getBooleanInput('inherit-toolchain')) {
+			core.debug('Inheriting entire [toolchain] section');
 
-		return { channel: config.toolchain.channel };
+			return { ...config.toolchain };
+		}
+
+		if (config.toolchain.channel) {
+			core.debug('Found channel in [toolchain] section');
+
+			return { channel: config.toolchain.channel };
+		}
 	}
 
 	core.debug('No channel found in [toolchain] section');