Skip to content

Commit ce756c4

Browse files
authored
feat: plugin-ify ?jp=<jsonpath> modifier (#19)
* feat(jsonpath): moved Secret Modifier `?jp=<jsonpath>` under `/plugin` This is a course-correction, as this modifier uses an external dependency, and so it should have been a plugin from the start. * feat(tooling): integrate govulncheck and modularize asdf setup - Add govulncheck to the toolchain and run it automatically during CI. - Modularize ASDF plugin and tool setup with task commands (tools.plugins, tools.update, tools.install). - Update developer guides and documentation to match the new bootstrap workflow. 💘 Generated with Crush Assisted-by: Crush:gemini-3.5-flash * fix: allow to install asdf plugins off main registry in CI * chore: fix `examples/viper`
1 parent d740b45 commit ce756c4

18 files changed

Lines changed: 119 additions & 30 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,19 @@ jobs:
2323
- name: Checkout code
2424
uses: actions/checkout@v6
2525

26-
- name: Install asdf & tools
27-
uses: asdf-vm/actions/install@v4
26+
- name: Install asdf
27+
uses: asdf-vm/actions/setup@v4
28+
29+
- name: Install Task
30+
run: |
31+
asdf plugin add task
32+
asdf install task
33+
34+
- name: Install (rest of the) Tools
35+
run: task tools.install
36+
37+
- name: Vulnerability Scan
38+
run: task vuln
2839

2940
- name: Build
3041
run: task build

.tool-versions

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
task 3.50.0
1+
task 3.51.1
22
golang 1.26.3
33
golangci-lint 2.12.2
4+
govulncheck 1.3.0

AGENTS.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ All development tasks are defined in `Taskfile.yaml`. **Always use `task` instea
5252
| `task lint-fix` | Run linter and automatically fix issues |
5353
| `task fmt` | Format code |
5454
| `task run -- <args>` | Run the project (passes args to `go run .`) |
55-
| `task update-dependencies` | Update and tidy Go modules |
55+
| `task dependencies.update` | Update and tidy Go modules |
56+
| `task tools.plugins` | Install all necessary asdf plugins |
57+
| `task tools.update` | Update all tools in `.tool-versions` to the latest available version via asdf |
58+
| `task tools.install` | Install all tools pinned in `.tool-versions` via asdf |
59+
| `task vuln` | Run govulncheck for vulnerability scanning |
5660
| `task doc.serve` | Run local godoc server (`pkgsite`) and open in browser |
5761

5862
## ⚙️ CI/CD
@@ -62,6 +66,7 @@ The project's CI pipeline (`.github/workflows/ci.yaml`) is driven entirely by `t
6266
- **Build**: `task build`
6367
- **Test**: `task test.ci` (generates `coverage.out` used for step summary)
6468
- **Lint & Format**: `task lint-fix` && `task fmt`
69+
- **Security Check**: `task vuln`
6570

6671
## 📂 Project Structure
6772

@@ -76,11 +81,11 @@ The project's CI pipeline (`.github/workflows/ci.yaml`) is driven entirely by `t
7681
- **`source/file/`**: `file://` source implementation.
7782
- **`source/env/`**: `env://` source implementation.
7883
- **`source/base64/`**: `base64://` source implementation.
79-
- **`modifier/jsonpath/`**: `jp` modifier implementation (JSONPath extraction).
8084
- **`modifier/base64/`**: `b64` modifier implementation (Base64 encoding).
8185
- **`modifier/base64_encoder/`**: `b64e` alias for `modifier/base64/`.
8286
- **`modifier/base64_decoder/`**: `b64d` modifier implementation (Base64 decoding).
8387
- **`plugin/`**: External plugins (opt-in).
88+
- **`modifier/jsonpath/`**: `jp` modifier implementation (JSONPath extraction).
8489
- **`modifier/tomlpath/`**: `tp` modifier implementation (TOML JSONPath extraction).
8590
- **`modifier/xpath/`**: `xp` modifier implementation (XPath extraction).
8691
- **`modifier/yamlpath/`**: `yp` modifier implementation (YAML JSONPath extraction).

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515
- WARNING: currently untested due to lack of test environment.
1616
- `kp://`: Keeper Secrets Manager source implementation (available in `plugin/source/keeper`).
1717
- WARNING: currently untested due to lack of test environment.
18+
- `?jp=`: JSONPath extractor modifier for JSON secrets (available in `plugin/modifier/jsonpath`).
1819
- **Tooling**:
1920
- Test tasks in `Taskfile.yaml` (`test`, `test.full`, `test.short`, `test.ci`) now support passing a specific directory path using `-- <path>`.
21+
- Added modular `tools.plugins`, `tools.update`, and `tools.install` tasks to `Taskfile.yaml` for robust `asdf`-based toolchain management.
22+
- Integrated `govulncheck` (v1.3.0) into `.tool-versions` toolchain and added `task vuln` for local vulnerability scanning.
23+
- Integrated `task vuln` check directly into the CI pipeline.
2024

2125
### Changed
2226

@@ -25,6 +29,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2529
- **Support**: Documented in [README](./README.md) that for now we are not going to support LastPass (`lp://`)
2630
nor Dashlane (`dl://`) as a source. They both lack a Golang SDK and/or a REST API.
2731

32+
### Removed
33+
34+
- **BREAKING CHANGE**: Removed `jp` (JSONPath) modifier from default built-in modifiers of `Spelunker` to completely free the core root module from any external production dependencies. It has been moved to a plugin under `plugin/modifier/jsonpath/` and must now be explicitly registered using `jsonpath.WithJSONPath()`.
35+
36+
2837
## [1.3.2] - 2026-04-07
2938

3039
### Changed

CONTRIBUTING.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,19 @@ the **human-scale nature of software review**:
2626

2727
### Install `asdf` and plugins
2828

29-
This repository depends on [asdf]. Once installed, please
30-
install all the [asdf plugins] used in this repository, by running
31-
(or something similar):
29+
This repository depends on [asdf].
30+
31+
Once asdf is installed, you can bootstrap the entire toolchain using the provided task commands:
3232

3333
```shell
34-
$ cut -d' ' -f1 .tool-versions | \
35-
while read PLUGIN; do
36-
asdf plugin add $PLUGIN || true
37-
done
38-
$ asdf install
34+
# 1. Install necessary asdf plugins (including non-default ones)
35+
$ task tools.plugins
36+
37+
# 2. Update and pin tools in .tool-versions to latest available versions (optional)
38+
$ task tools.update
39+
40+
# 3. Install all tools pinned in .tool-versions
41+
$ task tools.install
3942
```
4043

4144
### `task` toolchain

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,10 @@ will result in this sequence:
193193

194194
| Modifier (of Secrets) | Type (query) | Available as | Status | Doc |
195195
|-----------------------------------|------------------|:------------:|:------:|:----------------------------------------------------------------------------------------:|
196-
| JSONPath extractor | `?jp=<JSONPath>` | built-in || [link](https://pkg.go.dev/github.com/detro/spelunk@main/builtin/modifier/jsonpath) |
197196
| Base64 encoder | `?b64` | built-in || [link](https://pkg.go.dev/github.com/detro/spelunk@main/builtin/modifier/base64) |
198197
| Base64 encoder (alias for `?b64`) | `?b64e` | built-in || [link](https://pkg.go.dev/github.com/detro/spelunk@main/builtin/modifier/base64_encoder) |
199198
| Base64 decoder | `?b64d` | built-in || [link](https://pkg.go.dev/github.com/detro/spelunk@main/builtin/modifier/base64_decoder) |
199+
| JSONPath extractor | `?jp=<JSONPath>` | plug-in || [link](https://pkg.go.dev/github.com/detro/spelunk@main/plugin/modifier/jsonpath) |
200200
| XPath extractor | `?xp=<XPath>` | plug-in || [link](https://pkg.go.dev/github.com/detro/spelunk@main/plugin/modifier/xpath) |
201201
| YAML JSONPath extractor | `?yp=<JSONPath>` | plug-in || [link](https://pkg.go.dev/github.com/detro/spelunk@main/plugin/modifier/yamlpath) |
202202
| TOML JSONPath extractor | `?tp=<JSONPath>` | plug-in || [link](https://pkg.go.dev/github.com/detro/spelunk@main/plugin/modifier/tomlpath) |

Taskfile.yaml

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ tasks:
2727
lint:
2828
cmd: golangci-lint run --allow-parallel-runners --verbose
2929

30+
vuln:
31+
desc: Run govulncheck for vulnerability scanning
32+
cmd: govulncheck ./...
33+
3034
lint-fix:
3135
cmd: golangci-lint run --fix --allow-parallel-runners --verbose
3236

@@ -42,11 +46,36 @@ tasks:
4246
mod.tidy:
4347
cmd: go mod tidy -v
4448

45-
update-dependencies:
49+
dependencies.update:
4650
deps:
4751
- mod.update
4852
- mod.tidy
4953

54+
tools.plugins:
55+
desc: Install all necessary asdf plugins
56+
cmd: |
57+
# Install all plugins listed in .tool-versions (will fail but continue for out-of-registry ones)
58+
cut -d' ' -f1 .tool-versions | while read -r plugin; do
59+
asdf plugin add "$plugin" || true
60+
done
61+
# Install out-of-registry plugins
62+
asdf plugin add govulncheck https://github.com/wizzardich/asdf-govulncheck.git
63+
64+
tools.update:
65+
desc: Update all tools in .tool-versions to latest available versions via asdf
66+
deps:
67+
- tools.plugins
68+
cmd: |
69+
cut -d' ' -f1 .tool-versions | while read -r plugin; do
70+
asdf set "$plugin" latest || true
71+
done
72+
73+
tools.install:
74+
desc: Install all tools in .tool-versions via asdf
75+
deps:
76+
- tools.plugins
77+
cmd: asdf install
78+
5079
doc.serve:
5180
cmds:
5281
- go install golang.org/x/pkgsite/cmd/pkgsite@latest

builtin/modifier/base64/base64_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import (
77

88
"github.com/detro/spelunk"
99
b64mod "github.com/detro/spelunk/builtin/modifier/base64"
10-
"github.com/detro/spelunk/builtin/modifier/jsonpath"
1110
"github.com/detro/spelunk/internal/testutil"
11+
"github.com/detro/spelunk/plugin/modifier/jsonpath"
1212
"github.com/detro/spelunk/types"
1313
"github.com/stretchr/testify/require"
1414
)
@@ -61,8 +61,8 @@ func TestSecretModifierBase64_Modify(t *testing.T) {
6161

6262
spelunker := spelunk.NewSpelunker(
6363
spelunk.WithSource(&testutil.MockSource{Typ: "test", Val: tt.val}),
64-
spelunk.WithModifier(&jsonpath.SecretModifierJSONPath{}),
6564
spelunk.WithModifier(&b64mod.SecretModifierBase64{}),
65+
jsonpath.WithJSONPath(),
6666
)
6767

6868
got, err := spelunker.DigUp(ctx, coord)

builtin/modifier/base64_decoder/base64_decoder_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import (
77

88
"github.com/detro/spelunk"
99
"github.com/detro/spelunk/builtin/modifier/base64_decoder"
10-
"github.com/detro/spelunk/builtin/modifier/jsonpath"
1110
"github.com/detro/spelunk/internal/testutil"
11+
"github.com/detro/spelunk/plugin/modifier/jsonpath"
1212
"github.com/detro/spelunk/types"
1313
"github.com/stretchr/testify/require"
1414
)
@@ -67,8 +67,8 @@ func TestSecretModifierBase64Decoder_Modify(t *testing.T) {
6767

6868
spelunker := spelunk.NewSpelunker(
6969
spelunk.WithSource(&testutil.MockSource{Typ: "test", Val: tt.val}),
70-
spelunk.WithModifier(&jsonpath.SecretModifierJSONPath{}),
7170
spelunk.WithModifier(&base64_decoder.SecretModifierBase64Decoder{}),
71+
jsonpath.WithJSONPath(),
7272
)
7373

7474
got, err := spelunker.DigUp(ctx, coord)

examples/viper/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ func main() {
3838

3939
// 3. Unmarshal with DecodeHook
4040
// We need to tell Viper how to handle the types.SecretCoord (TextUnmarshaler).
41-
// We use mapstructure.StringToTextUnmarshalerHookFunc() to bridge string -> SecretCoord.
41+
// We use mapstructure.TextUnmarshallerHookFunc() to bridge string -> SecretCoord.
4242
opts := viper.DecodeHook(mapstructure.ComposeDecodeHookFunc(
43-
mapstructure.StringToTextUnmarshalerHookFunc(),
43+
mapstructure.TextUnmarshallerHookFunc(),
4444
mapstructure.StringToTimeDurationHookFunc(),
4545
mapstructure.StringToSliceHookFunc(","),
4646
))

0 commit comments

Comments
 (0)