tfv 5.0.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +27 -3
- package/README.md +190 -129
- package/demo.gif +0 -0
- package/demo.tape +230 -0
- package/index.js +0 -4
- package/lib/commands/apply.js +9 -4
- package/lib/commands/current.js +25 -0
- package/lib/commands/destroy.js +9 -4
- package/lib/commands/fmt.js +26 -0
- package/lib/commands/init.js +26 -0
- package/lib/commands/install.js +22 -13
- package/lib/commands/list.js +20 -11
- package/lib/commands/pin.js +26 -0
- package/lib/commands/plan.js +9 -4
- package/lib/commands/remove.js +17 -12
- package/lib/commands/shell-init.js +25 -0
- package/lib/commands/switch.js +28 -7
- package/lib/commands/upgrade.js +26 -0
- package/lib/commands/use.js +17 -13
- package/lib/commands/validate.js +21 -0
- package/lib/modules/current.js +52 -0
- package/lib/modules/install.js +155 -89
- package/lib/modules/list.js +66 -105
- package/lib/modules/pin.js +35 -0
- package/lib/modules/ps1.js +37 -29
- package/lib/modules/remote.js +68 -15
- package/lib/modules/remove.js +35 -21
- package/lib/modules/shell-init.js +113 -0
- package/lib/modules/switch.js +125 -41
- package/lib/modules/terraform-command.js +49 -67
- package/lib/modules/upgrade.js +93 -0
- package/lib/modules/use.js +58 -54
- package/lib/utils/formatVersions.js +57 -5
- package/lib/utils/paths.js +156 -0
- package/lib/utils/postInstall.js +37 -13
- package/lib/utils/store.js +17 -6
- package/package.json +11 -9
- package/test/extractTargets.test.js +75 -0
- package/test/formatVersions.test.js +126 -0
- package/test/moduleImports.test.js +45 -0
- package/test/paths.test.js +69 -0
- package/test/versionResolution.test.js +92 -0
|
@@ -2,27 +2,51 @@ name: Publish tfv to npm registry
|
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
|
-
|
|
5
|
+
tags:
|
|
6
|
+
- 'v[0-9]+.[0-9]+.[0-9]+' # only trigger on semver tags: v6.0.0, v6.1.0, etc.
|
|
6
7
|
|
|
7
8
|
permissions:
|
|
8
9
|
contents: read
|
|
9
10
|
id-token: write
|
|
10
11
|
|
|
11
12
|
jobs:
|
|
12
|
-
|
|
13
|
+
test:
|
|
13
14
|
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- uses: actions/setup-node@v4
|
|
19
|
+
with:
|
|
20
|
+
node-version: 22
|
|
21
|
+
cache: 'npm'
|
|
14
22
|
|
|
23
|
+
- run: npm ci
|
|
24
|
+
|
|
25
|
+
- run: npm test
|
|
26
|
+
|
|
27
|
+
publish:
|
|
28
|
+
needs: test
|
|
29
|
+
runs-on: ubuntu-latest
|
|
15
30
|
steps:
|
|
16
31
|
- uses: actions/checkout@v4
|
|
17
32
|
|
|
18
33
|
- uses: actions/setup-node@v4
|
|
19
34
|
with:
|
|
20
|
-
node-version:
|
|
35
|
+
node-version: 22
|
|
21
36
|
registry-url: https://registry.npmjs.org
|
|
22
37
|
cache: 'npm'
|
|
23
38
|
|
|
24
39
|
- run: npm ci
|
|
25
40
|
|
|
41
|
+
- name: Verify package version matches git tag
|
|
42
|
+
run: |
|
|
43
|
+
PKG_VERSION="v$(node -p "require('./package.json').version")"
|
|
44
|
+
GIT_TAG="${{ github.ref_name }}"
|
|
45
|
+
if [ "$PKG_VERSION" != "$GIT_TAG" ]; then
|
|
46
|
+
echo "Version mismatch: package.json=$PKG_VERSION, tag=$GIT_TAG"
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
|
|
26
50
|
- run: npm publish --access public
|
|
27
51
|
env:
|
|
28
52
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/README.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# tfv — Terraform & OpenTofu Version Manager
|
|
2
2
|
|
|
3
|
+
```
|
|
3
4
|
_ ________ __
|
|
4
5
|
_| |__ / _____|\ \ / /
|
|
5
6
|
|_ ___\ | |___ \ \ / /
|
|
@@ -7,226 +8,286 @@
|
|
|
7
8
|
| |___ | | \ \/ /
|
|
8
9
|
\______\_| \__/
|
|
9
10
|
|
|
10
|
-
Happy terraforming
|
|
11
|
-
|
|
11
|
+
Happy terraforming! 😍🥂
|
|
12
|
+
---------------------------------
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`tfv` lets you install, switch, and manage multiple versions of **Terraform** and **OpenTofu** without `sudo`. All binaries live in `~/.tfv/` — upgrading `tfv` itself never wipes your installed versions.
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+

|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
16
22
|
|
|
17
23
|
```sh
|
|
18
24
|
npm install -g tfv
|
|
19
25
|
```
|
|
20
26
|
|
|
21
|
-
|
|
27
|
+
`tfv` automatically adds `~/.tfv/bin` to your PATH on install (shell configs + Windows User PATH). Restart your terminal once after install.
|
|
22
28
|
|
|
23
|
-
|
|
24
|
-
npm i -g tfv
|
|
25
|
-
```
|
|
29
|
+
---
|
|
26
30
|
|
|
27
|
-
##
|
|
31
|
+
## How it works
|
|
28
32
|
|
|
29
|
-
```
|
|
30
|
-
tfv
|
|
33
|
+
```
|
|
34
|
+
npm install -g tfv
|
|
35
|
+
│
|
|
36
|
+
▼
|
|
37
|
+
postInstall.js
|
|
38
|
+
├── creates ~/.tfv/bin/, ~/.tfv/store/, ~/.tfv/cache/
|
|
39
|
+
└── adds ~/.tfv/bin to PATH (shell configs / Windows registry)
|
|
40
|
+
│
|
|
41
|
+
▼
|
|
42
|
+
tfv install 1.9.0
|
|
43
|
+
├── fetches version list → ~/.tfv/cache/terraform-versions.json (1hr TTL)
|
|
44
|
+
├── downloads zip → system temp dir (with progress bar)
|
|
45
|
+
├── verifies SHA256 → HashiCorp / OpenTofu checksums
|
|
46
|
+
├── extracts binary only → ~/.tfv/store/terraform/1.9.0
|
|
47
|
+
└── records arch → ~/.tfv/store/terraform/arch.json
|
|
48
|
+
│
|
|
49
|
+
▼
|
|
50
|
+
tfv use 1.9.0
|
|
51
|
+
├── copies ~/.tfv/store/terraform/1.9.0 → ~/.tfv/bin/terraform
|
|
52
|
+
└── writes active version → ~/.tfv/active.json
|
|
53
|
+
|
|
54
|
+
│
|
|
55
|
+
▼
|
|
56
|
+
terraform plan ← resolves to ~/.tfv/bin/terraform (same binary as tfv)
|
|
57
|
+
tfv plan ← spawns ~/.tfv/bin/terraform directly (no PATH lookup)
|
|
31
58
|
```
|
|
32
59
|
|
|
33
|
-
|
|
60
|
+
Both `terraform` and `tfv` commands always use the **exact same binary**.
|
|
34
61
|
|
|
35
|
-
|
|
36
|
-
tfv -h
|
|
37
|
-
```
|
|
62
|
+
---
|
|
38
63
|
|
|
39
|
-
|
|
64
|
+
## Store layout
|
|
40
65
|
|
|
41
66
|
```
|
|
42
|
-
tfv
|
|
67
|
+
~/.tfv/
|
|
68
|
+
bin/
|
|
69
|
+
terraform ← active terraform binary (no sudo, no symlinks)
|
|
70
|
+
tofu ← active opentofu binary
|
|
71
|
+
store/
|
|
72
|
+
terraform/
|
|
73
|
+
1.9.0 ← installed versions (binary renamed to version number)
|
|
74
|
+
1.7.3
|
|
75
|
+
arch.json ← { "1.9.0": "arm64", "1.7.3": "amd64" }
|
|
76
|
+
opentofu/
|
|
77
|
+
1.8.0
|
|
78
|
+
arch.json
|
|
79
|
+
cache/
|
|
80
|
+
terraform-versions.json ← remote list cached for 1 hour
|
|
81
|
+
opentofu-versions.json
|
|
82
|
+
active.json ← { "terraform": "1.9.0", "opentofu": null }
|
|
83
|
+
```
|
|
43
84
|
|
|
44
|
-
|
|
85
|
+
---
|
|
45
86
|
|
|
46
|
-
|
|
87
|
+
## Commands
|
|
47
88
|
|
|
48
|
-
|
|
89
|
+
### Install
|
|
49
90
|
|
|
50
|
-
|
|
91
|
+
```sh
|
|
92
|
+
tfv install latest # latest stable
|
|
93
|
+
tfv install 1.9.0 # exact version
|
|
94
|
+
tfv install 1.9.^ # latest 1.9.x patch
|
|
95
|
+
tfv install 1.8.0-beta1 # explicit pre-release (warns you)
|
|
96
|
+
tfv install latest --provider tofu # OpenTofu
|
|
97
|
+
tfv install 1.9.0 --arch amd64 # override architecture
|
|
98
|
+
```
|
|
51
99
|
|
|
52
|
-
|
|
100
|
+
Aliases: `tfv i`
|
|
53
101
|
|
|
54
|
-
|
|
102
|
+
---
|
|
55
103
|
|
|
56
|
-
|
|
57
|
-
Accepts all terraform flags after --
|
|
58
|
-
Example: tfv apply --file main.tf --file network.tf -- -auto-approve -target=<TARGET> -var="env=prod"
|
|
104
|
+
### Switch version
|
|
59
105
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
106
|
+
```sh
|
|
107
|
+
tfv use 1.9.0
|
|
108
|
+
tfv use latest # latest installed version
|
|
109
|
+
tfv use 1.8.0 --provider tofu
|
|
110
|
+
```
|
|
63
111
|
|
|
64
|
-
|
|
65
|
-
Accepts all terraform flags after --
|
|
66
|
-
Example: tfv plan --file main.tf --file network.tf -- -auto-approve -target=<TARGET> -var="env=prod"
|
|
112
|
+
No `sudo`. Copies binary to `~/.tfv/bin/terraform`.
|
|
67
113
|
|
|
68
|
-
|
|
69
|
-
-h, --help Show help [boolean]
|
|
70
|
-
-v, --version Show version number [boolean]
|
|
71
|
-
```
|
|
114
|
+
---
|
|
72
115
|
|
|
73
|
-
|
|
116
|
+
### Auto-switch
|
|
74
117
|
|
|
75
|
-
|
|
118
|
+
Detects and switches to the version your project requires. Installs it if not already in store.
|
|
76
119
|
|
|
77
|
-
|
|
120
|
+
```sh
|
|
121
|
+
tfv auto-switch
|
|
122
|
+
tfv as # alias
|
|
123
|
+
tfv as --provider tofu
|
|
124
|
+
```
|
|
78
125
|
|
|
79
|
-
|
|
80
|
-
* [Table of Contents](#table-of-contents)
|
|
81
|
-
* [Modules](#modules)
|
|
82
|
-
* [install](#install)
|
|
83
|
-
* [use](#use)
|
|
84
|
-
* [list](#list)
|
|
85
|
-
* [remove](#remove)
|
|
86
|
-
* [auto-switch](#auto-switch)
|
|
87
|
-
* [plan](#plan)
|
|
88
|
-
* [apply](#apply)
|
|
89
|
-
* [destroy](#destroy)
|
|
90
|
-
<!--te-->
|
|
126
|
+
Reads version from (in priority order):
|
|
91
127
|
|
|
92
|
-
|
|
128
|
+
1. `.terraform-version` file in current directory
|
|
129
|
+
2. `terraform.tfstate` → `terraform_version` field
|
|
130
|
+
3. `required_version` in any `.tf` file — supports all constraint operators:
|
|
131
|
+
`=`, `>=`, `>`, `<=`, `<`, `!=`, `~>`, and compound `">= 1.3, < 2.0"`
|
|
93
132
|
|
|
94
|
-
|
|
133
|
+
---
|
|
95
134
|
|
|
96
|
-
|
|
97
|
-
| ---------------- | ------------------------------------------ |
|
|
98
|
-
| x.x.x | Installs terraform version x.x.x |
|
|
99
|
-
| x^ | Installs latest version of release x |
|
|
100
|
-
| x.x.^ | Installs latest version of release x.x |
|
|
101
|
-
| latest | Installs latest version of terraform |
|
|
135
|
+
### Shell hook — auto-switch on `cd`
|
|
102
136
|
|
|
103
|
-
|
|
104
|
-
tfv install <version>
|
|
105
|
-
```
|
|
137
|
+
Wraps `cd` so that entering a directory automatically switches the terraform version — but **only if the directory looks like a terraform project**. Non-terraform folders have zero overhead (one filesystem check, no subprocess).
|
|
106
138
|
|
|
107
|
-
|
|
139
|
+
A directory is considered a terraform project if it contains:
|
|
140
|
+
- a `.terraform-version` file, **or**
|
|
141
|
+
- any `*.tf` files
|
|
108
142
|
|
|
109
143
|
```sh
|
|
110
|
-
|
|
144
|
+
cd ~/Downloads # no .tf files → nothing happens
|
|
145
|
+
cd ~/projects/react-app # no .tf files → nothing happens
|
|
146
|
+
cd ~/projects/infra # has main.tf → auto-switch runs silently
|
|
147
|
+
cd ~/projects/platform # has .terraform-version → auto-switch runs silently
|
|
111
148
|
```
|
|
112
149
|
|
|
113
|
-
|
|
150
|
+
Setup (one-time, add to your shell config):
|
|
114
151
|
|
|
115
152
|
```sh
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
> NOTE: The default *system-architecture* is the architecture of your computer (arm64, amd64, x64, etc...)
|
|
153
|
+
# Bash
|
|
154
|
+
echo 'eval "$(tfv shell-init bash)"' >> ~/.bashrc
|
|
120
155
|
|
|
121
|
-
|
|
156
|
+
# Zsh
|
|
157
|
+
echo 'eval "$(tfv shell-init zsh)"' >> ~/.zshrc
|
|
122
158
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
| x.x.x | use terraform version x.x.x |
|
|
126
|
-
| latest | use latest version of terraform |
|
|
159
|
+
# Fish
|
|
160
|
+
echo 'tfv shell-init fish | source' >> ~/.config/fish/config.fish
|
|
127
161
|
|
|
128
|
-
|
|
129
|
-
tfv
|
|
162
|
+
# PowerShell
|
|
163
|
+
echo 'Invoke-Expression (tfv shell-init powershell | Out-String)' >> $PROFILE
|
|
130
164
|
```
|
|
131
165
|
|
|
132
|
-
|
|
166
|
+
After setup, entering a terraform project switches the version automatically — no manual `tfv as` needed.
|
|
133
167
|
|
|
134
|
-
|
|
168
|
+
---
|
|
135
169
|
|
|
136
|
-
|
|
137
|
-
| ---------------|---------------|--------------------------------------------------------------------------------|
|
|
138
|
-
| | | Defaults to listing terraform versions installed locally (in tfv store) |
|
|
139
|
-
| `--local` | `-l` | Lists all terraform versions installed locally |
|
|
140
|
-
| `--remote` | `-r` | Lists all terraform versions available remotely, on terraform server |
|
|
170
|
+
### List versions
|
|
141
171
|
|
|
142
172
|
```sh
|
|
143
|
-
tfv list
|
|
173
|
+
tfv list # installed versions (default)
|
|
174
|
+
tfv ls --remote # all available versions from HashiCorp
|
|
175
|
+
tfv ls --remote --provider tofu # all available OpenTofu versions
|
|
144
176
|
```
|
|
145
177
|
|
|
146
|
-
|
|
178
|
+
Active version is marked with 🚀.
|
|
147
179
|
|
|
148
|
-
|
|
149
|
-
tfv ls [option]
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
- #### _REMOVE_
|
|
180
|
+
---
|
|
153
181
|
|
|
154
|
-
|
|
182
|
+
### Current version
|
|
155
183
|
|
|
156
184
|
```sh
|
|
157
|
-
|
|
185
|
+
tfv current # shows active version + PATH status
|
|
186
|
+
tfv which # alias
|
|
187
|
+
tfv current --provider tofu
|
|
158
188
|
```
|
|
159
189
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
190
|
+
Example output:
|
|
191
|
+
```
|
|
192
|
+
Active terraform version: 1.9.0
|
|
193
|
+
Binary: /Users/you/.tfv/bin/terraform
|
|
194
|
+
Reported: Terraform v1.9.0
|
|
195
|
+
PATH OK — 'terraform' resolves to tfv-managed binary
|
|
164
196
|
```
|
|
165
197
|
|
|
166
|
-
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
### Pin version
|
|
201
|
+
|
|
202
|
+
Writes a `.terraform-version` file in the current directory so teammates get the same version via `tfv auto-switch`:
|
|
167
203
|
|
|
168
204
|
```sh
|
|
169
|
-
|
|
205
|
+
tfv pin # pin currently active version
|
|
206
|
+
tfv pin 1.9.0 # pin a specific version
|
|
207
|
+
tfv pin --provider tofu
|
|
170
208
|
```
|
|
171
209
|
|
|
172
|
-
|
|
210
|
+
---
|
|
173
211
|
|
|
174
|
-
|
|
212
|
+
### Upgrade
|
|
175
213
|
|
|
176
214
|
```sh
|
|
177
|
-
|
|
215
|
+
tfv upgrade # upgrade active 1.6.3 → latest 1.6.x patch
|
|
216
|
+
tfv upgrade 1.9 # install + use latest 1.9.x
|
|
217
|
+
tfv upgrade latest # install + use absolute latest
|
|
218
|
+
tfv upgrade --provider tofu
|
|
178
219
|
```
|
|
179
220
|
|
|
180
|
-
|
|
221
|
+
Also re-anchors `~/.tfv/bin` in PATH to ensure it takes precedence over any system-installed terraform.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### Remove
|
|
181
226
|
|
|
182
227
|
```sh
|
|
183
|
-
|
|
228
|
+
tfv remove 1.7.3
|
|
229
|
+
tfv rm 1.7.3 1.6.6 # remove multiple
|
|
230
|
+
tfv rm 1.8.0 --provider tofu
|
|
184
231
|
```
|
|
185
232
|
|
|
186
|
-
|
|
233
|
+
Warns if you're removing the currently active version.
|
|
187
234
|
|
|
188
|
-
|
|
235
|
+
---
|
|
189
236
|
|
|
190
|
-
|
|
191
|
-
tfv plan --file main.tf
|
|
192
|
-
```
|
|
237
|
+
### Terraform commands (via tfv)
|
|
193
238
|
|
|
194
|
-
|
|
239
|
+
All commands use the tfv-managed binary and accept extra terraform flags after `--`:
|
|
195
240
|
|
|
196
241
|
```sh
|
|
197
|
-
|
|
242
|
+
tfv init
|
|
243
|
+
tfv validate
|
|
244
|
+
tfv fmt
|
|
245
|
+
tfv fmt -- -recursive
|
|
246
|
+
|
|
247
|
+
tfv plan
|
|
248
|
+
tfv plan --file main.tf # extract targets from file
|
|
249
|
+
tfv plan --file main.tf --file network.tf # multiple files
|
|
250
|
+
tfv plan --file main.tf -- -var="env=prod" # with extra terraform flags
|
|
251
|
+
|
|
252
|
+
tfv apply --file main.tf -- -auto-approve
|
|
253
|
+
tfv destroy --file main.tf -- -auto-approve
|
|
198
254
|
```
|
|
199
255
|
|
|
200
|
-
|
|
256
|
+
`--file` parses `.tf` files and auto-generates `-target` flags for every `resource`, `data`, and `module` block found. Comments are stripped before parsing.
|
|
201
257
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
258
|
+
All commands support `--provider tofu` to use OpenTofu instead.
|
|
259
|
+
|
|
260
|
+
---
|
|
205
261
|
|
|
206
|
-
|
|
262
|
+
## OpenTofu support
|
|
207
263
|
|
|
208
|
-
|
|
264
|
+
Every command works with OpenTofu via `--provider tofu` (or `--provider opentofu`):
|
|
209
265
|
|
|
210
266
|
```sh
|
|
211
|
-
|
|
267
|
+
tfv install latest --provider tofu
|
|
268
|
+
tfv use 1.8.0 --provider tofu
|
|
269
|
+
tfv list --remote --provider tofu
|
|
270
|
+
tfv current --provider tofu
|
|
271
|
+
tfv plan --provider tofu
|
|
212
272
|
```
|
|
213
273
|
|
|
214
|
-
|
|
274
|
+
OpenTofu binaries are stored separately from Terraform in `~/.tfv/store/opentofu/` and activated as `~/.tfv/bin/tofu`.
|
|
215
275
|
|
|
216
|
-
|
|
217
|
-
tfv apply --file main.tf -- -auto-approve
|
|
218
|
-
```
|
|
276
|
+
---
|
|
219
277
|
|
|
220
|
-
|
|
278
|
+
## Windows support
|
|
221
279
|
|
|
222
|
-
|
|
280
|
+
Everything works on Windows without administrator privileges:
|
|
223
281
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
282
|
+
- Store: `%USERPROFILE%\.tfv\`
|
|
283
|
+
- PATH: updated via `[Environment]::SetEnvironmentVariable("PATH", ..., "User")` (User scope, no admin)
|
|
284
|
+
- Shell hooks: PowerShell profile integration via `tfv shell-init powershell`
|
|
227
285
|
|
|
228
|
-
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Help
|
|
229
289
|
|
|
230
290
|
```sh
|
|
231
|
-
|
|
291
|
+
tfv --help
|
|
292
|
+
tfv <command> --help
|
|
232
293
|
```
|
package/demo.gif
ADDED
|
Binary file
|