tfv 5.0.1 → 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 -132
- package/demo.gif +0 -0
- package/demo.tape +230 -0
- package/index.js +0 -4
- package/lib/commands/apply.js +8 -3
- package/lib/commands/current.js +25 -0
- package/lib/commands/destroy.js +8 -3
- 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 +8 -3
- 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,229 +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:
|
|
59
|
-
tfv apply --file main.tf --file network.tf -- -auto-approve -target=<TARGET> -var="env=prod"
|
|
104
|
+
### Switch version
|
|
60
105
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
106
|
+
```sh
|
|
107
|
+
tfv use 1.9.0
|
|
108
|
+
tfv use latest # latest installed version
|
|
109
|
+
tfv use 1.8.0 --provider tofu
|
|
110
|
+
```
|
|
65
111
|
|
|
66
|
-
|
|
67
|
-
Accepts all terraform flags after --
|
|
68
|
-
Example:
|
|
69
|
-
tfv plan --file main.tf --file network.tf -- -auto-approve -target=<TARGET> -var="env=prod"
|
|
112
|
+
No `sudo`. Copies binary to `~/.tfv/bin/terraform`.
|
|
70
113
|
|
|
71
|
-
|
|
72
|
-
-h, --help Show help [boolean]
|
|
73
|
-
-v, --version Show version number [boolean]
|
|
74
|
-
```
|
|
114
|
+
---
|
|
75
115
|
|
|
76
|
-
|
|
116
|
+
### Auto-switch
|
|
77
117
|
|
|
78
|
-
|
|
118
|
+
Detects and switches to the version your project requires. Installs it if not already in store.
|
|
79
119
|
|
|
80
|
-
|
|
120
|
+
```sh
|
|
121
|
+
tfv auto-switch
|
|
122
|
+
tfv as # alias
|
|
123
|
+
tfv as --provider tofu
|
|
124
|
+
```
|
|
81
125
|
|
|
82
|
-
|
|
83
|
-
* [Table of Contents](#table-of-contents)
|
|
84
|
-
* [Modules](#modules)
|
|
85
|
-
* [install](#install)
|
|
86
|
-
* [use](#use)
|
|
87
|
-
* [list](#list)
|
|
88
|
-
* [remove](#remove)
|
|
89
|
-
* [auto-switch](#auto-switch)
|
|
90
|
-
* [plan](#plan)
|
|
91
|
-
* [apply](#apply)
|
|
92
|
-
* [destroy](#destroy)
|
|
93
|
-
<!--te-->
|
|
126
|
+
Reads version from (in priority order):
|
|
94
127
|
|
|
95
|
-
|
|
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"`
|
|
96
132
|
|
|
97
|
-
|
|
133
|
+
---
|
|
98
134
|
|
|
99
|
-
|
|
100
|
-
| ---------------- | ------------------------------------------ |
|
|
101
|
-
| x.x.x | Installs terraform version x.x.x |
|
|
102
|
-
| x^ | Installs latest version of release x |
|
|
103
|
-
| x.x.^ | Installs latest version of release x.x |
|
|
104
|
-
| latest | Installs latest version of terraform |
|
|
135
|
+
### Shell hook — auto-switch on `cd`
|
|
105
136
|
|
|
106
|
-
|
|
107
|
-
tfv install <version>
|
|
108
|
-
```
|
|
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).
|
|
109
138
|
|
|
110
|
-
|
|
139
|
+
A directory is considered a terraform project if it contains:
|
|
140
|
+
- a `.terraform-version` file, **or**
|
|
141
|
+
- any `*.tf` files
|
|
111
142
|
|
|
112
143
|
```sh
|
|
113
|
-
|
|
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
|
|
114
148
|
```
|
|
115
149
|
|
|
116
|
-
|
|
150
|
+
Setup (one-time, add to your shell config):
|
|
117
151
|
|
|
118
152
|
```sh
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
> 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
|
|
123
155
|
|
|
124
|
-
|
|
156
|
+
# Zsh
|
|
157
|
+
echo 'eval "$(tfv shell-init zsh)"' >> ~/.zshrc
|
|
125
158
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
| x.x.x | use terraform version x.x.x |
|
|
129
|
-
| latest | use latest version of terraform |
|
|
159
|
+
# Fish
|
|
160
|
+
echo 'tfv shell-init fish | source' >> ~/.config/fish/config.fish
|
|
130
161
|
|
|
131
|
-
|
|
132
|
-
tfv
|
|
162
|
+
# PowerShell
|
|
163
|
+
echo 'Invoke-Expression (tfv shell-init powershell | Out-String)' >> $PROFILE
|
|
133
164
|
```
|
|
134
165
|
|
|
135
|
-
|
|
166
|
+
After setup, entering a terraform project switches the version automatically — no manual `tfv as` needed.
|
|
136
167
|
|
|
137
|
-
|
|
168
|
+
---
|
|
138
169
|
|
|
139
|
-
|
|
140
|
-
| ---------------|---------------|--------------------------------------------------------------------------------|
|
|
141
|
-
| | | Defaults to listing terraform versions installed locally (in tfv store) |
|
|
142
|
-
| `--local` | `-l` | Lists all terraform versions installed locally |
|
|
143
|
-
| `--remote` | `-r` | Lists all terraform versions available remotely, on terraform server |
|
|
170
|
+
### List versions
|
|
144
171
|
|
|
145
172
|
```sh
|
|
146
|
-
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
|
|
147
176
|
```
|
|
148
177
|
|
|
149
|
-
|
|
178
|
+
Active version is marked with 🚀.
|
|
150
179
|
|
|
151
|
-
|
|
152
|
-
tfv ls [option]
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
- #### _REMOVE_
|
|
180
|
+
---
|
|
156
181
|
|
|
157
|
-
|
|
182
|
+
### Current version
|
|
158
183
|
|
|
159
184
|
```sh
|
|
160
|
-
|
|
185
|
+
tfv current # shows active version + PATH status
|
|
186
|
+
tfv which # alias
|
|
187
|
+
tfv current --provider tofu
|
|
161
188
|
```
|
|
162
189
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
|
167
196
|
```
|
|
168
197
|
|
|
169
|
-
|
|
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`:
|
|
170
203
|
|
|
171
204
|
```sh
|
|
172
|
-
|
|
205
|
+
tfv pin # pin currently active version
|
|
206
|
+
tfv pin 1.9.0 # pin a specific version
|
|
207
|
+
tfv pin --provider tofu
|
|
173
208
|
```
|
|
174
209
|
|
|
175
|
-
|
|
210
|
+
---
|
|
176
211
|
|
|
177
|
-
|
|
212
|
+
### Upgrade
|
|
178
213
|
|
|
179
214
|
```sh
|
|
180
|
-
|
|
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
|
|
181
219
|
```
|
|
182
220
|
|
|
183
|
-
|
|
221
|
+
Also re-anchors `~/.tfv/bin` in PATH to ensure it takes precedence over any system-installed terraform.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### Remove
|
|
184
226
|
|
|
185
227
|
```sh
|
|
186
|
-
|
|
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
|
|
187
231
|
```
|
|
188
232
|
|
|
189
|
-
|
|
233
|
+
Warns if you're removing the currently active version.
|
|
190
234
|
|
|
191
|
-
|
|
235
|
+
---
|
|
192
236
|
|
|
193
|
-
|
|
194
|
-
tfv plan --file main.tf
|
|
195
|
-
```
|
|
237
|
+
### Terraform commands (via tfv)
|
|
196
238
|
|
|
197
|
-
|
|
239
|
+
All commands use the tfv-managed binary and accept extra terraform flags after `--`:
|
|
198
240
|
|
|
199
241
|
```sh
|
|
200
|
-
|
|
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
|
|
201
254
|
```
|
|
202
255
|
|
|
203
|
-
|
|
256
|
+
`--file` parses `.tf` files and auto-generates `-target` flags for every `resource`, `data`, and `module` block found. Comments are stripped before parsing.
|
|
204
257
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
258
|
+
All commands support `--provider tofu` to use OpenTofu instead.
|
|
259
|
+
|
|
260
|
+
---
|
|
208
261
|
|
|
209
|
-
|
|
262
|
+
## OpenTofu support
|
|
210
263
|
|
|
211
|
-
|
|
264
|
+
Every command works with OpenTofu via `--provider tofu` (or `--provider opentofu`):
|
|
212
265
|
|
|
213
266
|
```sh
|
|
214
|
-
|
|
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
|
|
215
272
|
```
|
|
216
273
|
|
|
217
|
-
|
|
274
|
+
OpenTofu binaries are stored separately from Terraform in `~/.tfv/store/opentofu/` and activated as `~/.tfv/bin/tofu`.
|
|
218
275
|
|
|
219
|
-
|
|
220
|
-
tfv apply --file main.tf -- -auto-approve
|
|
221
|
-
```
|
|
276
|
+
---
|
|
222
277
|
|
|
223
|
-
|
|
278
|
+
## Windows support
|
|
224
279
|
|
|
225
|
-
|
|
280
|
+
Everything works on Windows without administrator privileges:
|
|
226
281
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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`
|
|
230
285
|
|
|
231
|
-
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Help
|
|
232
289
|
|
|
233
290
|
```sh
|
|
234
|
-
|
|
291
|
+
tfv --help
|
|
292
|
+
tfv <command> --help
|
|
235
293
|
```
|
package/demo.gif
ADDED
|
Binary file
|