feat(terraform): support opentofu for terraform version detection (#6910)

Support OpenTofu

This is a revitalization of https://github.com/starship/starship/pull/6072

Co-authored-by: Bojan Rajkovic <brajkovic@coderinserepeat.com>
This commit is contained in:
Joey Marianer
2025-09-06 10:14:17 -07:00
committed by GitHub
parent 95bf53f6b9
commit ef7d8bd442
4 changed files with 66 additions and 17 deletions
+10
View File
@@ -1618,6 +1618,16 @@
"symbol": "💠 ",
"style": "bold 105",
"disabled": false,
"commands": [
[
"terraform",
"version"
],
[
"tofu",
"version"
]
],
"detect_extensions": [
"tf",
"tfplan",
+6 -4
View File
@@ -4600,9 +4600,10 @@ format = 'via [🏎 $version](red bold)'
## Terraform
The `terraform` module shows the currently selected [Terraform workspace](https://www.terraform.io/docs/language/state/workspaces.html) and version.
It supports both Hashicorp Terraform and OpenTofu for version detection.
> [!TIP]
> By default the Terraform version is not shown, since this is slow for current versions of Terraform when a lot of plugins are in use.
> By default the Terraform/OpenTofu version is not shown, since this is slow for current versions when a lot of plugins are in use.
> If you still want to enable it, [follow the example shown below](#with-terraform-version).
By default the module will be shown if any of the following conditions are met:
@@ -4613,7 +4614,7 @@ By default the module will be shown if any of the following conditions are met:
### Options
| Option | Default | Description |
| ------------------- | ------------------------------------ | ------------------------------------------------------------------------- |
| ------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------- |
| `format` | `'via [$symbol$workspace]($style) '` | The format string for the module. |
| `version_format` | `'v${raw}'` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` |
| `symbol` | `'💠'` | A format string shown before the terraform workspace. |
@@ -4622,6 +4623,7 @@ By default the module will be shown if any of the following conditions are met:
| `detect_folders` | `['.terraform']` | Which folders should trigger this module. |
| `style` | `'bold 105'` | The style for the module. |
| `disabled` | `false` | Disables the `terraform` module. |
| `commands` | `[ [ 'terraform', 'version' ], [ 'tofu', 'version' ] ]` | How to detect what the Terraform version is. |
### Variables
@@ -4642,7 +4644,7 @@ By default the module will be shown if any of the following conditions are met:
# ~/.config/starship.toml
[terraform]
format = '[🏎💨 $version$workspace]($style) '
format = 'via [$symbol$version $workspace]($style) '
```
#### Without Terraform version
@@ -4651,7 +4653,7 @@ format = '[🏎💨 $version$workspace]($style) '
# ~/.config/starship.toml
[terraform]
format = '[🏎💨 $workspace]($style) '
format = 'via [$symbol$workspace]($style) '
```
## Time
+7
View File
@@ -16,6 +16,7 @@ pub struct TerraformConfig<'a> {
pub detect_extensions: Vec<&'a str>,
pub detect_files: Vec<&'a str>,
pub detect_folders: Vec<&'a str>,
pub commands: Vec<Vec<&'a str>>,
}
impl Default for TerraformConfig<'_> {
@@ -29,6 +30,12 @@ impl Default for TerraformConfig<'_> {
detect_extensions: vec!["tf", "tfplan", "tfstate"],
detect_files: vec![],
detect_folders: vec![".terraform"],
commands: vec![
// terraform is usually `terraform`
vec!["terraform", "version"],
// but for opentofu users, it'll be `tofu`
vec!["tofu", "version"],
],
}
}
}
+34 -4
View File
@@ -37,7 +37,10 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
.map(|variable| match variable {
"version" => {
let terraform_version = parse_terraform_version(
context.exec_cmd("terraform", &["version"])?.stdout.as_str(),
context
.exec_cmds_return_first(config.commands.clone())?
.stdout
.as_str(),
)?;
VersionFormatter::format_module_version(
module.get_name(),
@@ -84,13 +87,15 @@ fn get_terraform_workspace(context: &Context) -> Option<String> {
}
fn parse_terraform_version(version: &str) -> Option<String> {
// `terraform version` output looks like this
// Terraform v0.12.14
// With potential extra output if it detects you are not running the latest version
// `terraform version` or `tofu version` output looks like this
// Terraform v0.12.14/OpenTofu v1.7.2
// with potential extra output if it detects you are not running the latest version
let version = version
.lines()
.next()?
.trim_start_matches("Terraform ")
.trim_start_matches("OpenTofu ")
.trim()
.trim_start_matches('v');
@@ -111,6 +116,22 @@ mod tests {
assert_eq!(parse_terraform_version(input), Some("0.12.14".to_string()));
}
#[test]
fn test_parse_opentofu_version_release() {
let input = "OpenTofu v1.7.2";
assert_eq!(parse_terraform_version(input), Some("1.7.2".to_string()));
}
#[test]
fn test_parse_opentofu_version_multiline() {
let input = "OpenTofu v1.7.2
on darwin_arm64
+ provider registry.opentofu.org/hashicorp/helm v2.14.0
+ provider registry.opentofu.org/hashicorp/kubernetes v2.31.0
";
assert_eq!(parse_terraform_version(input), Some("1.7.2".to_string()));
}
#[test]
fn test_parse_terraform_version_prerelease() {
let input = "Terraform v0.12.14-rc1";
@@ -120,6 +141,15 @@ mod tests {
);
}
#[test]
fn test_parse_opentofu_version_prerelease() {
let input = "OpenTofu v1.8.0-alpha1";
assert_eq!(
parse_terraform_version(input),
Some("1.8.0-alpha1".to_string())
)
}
#[test]
fn test_parse_terraform_version_development() {
let input = "Terraform v0.12.14-dev (cca89f74)";