Skip to content

Show Starr download paths as a list and read PATHS_0 - #835

Merged
davidnewhall merged 5 commits into
mainfrom
fix/starr-paths-list
Oct 27, 2026
Merged

davidnewhall merged 5 commits into
mainfrom
fix/starr-paths-list

Conversation

@davidnewhall

@davidnewhall davidnewhall commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • The Starr settings field is the paths list, one directory per line. The help text is UN_*_PATHS_0, so UN_SONARR_0_PATHS_0 from the compose file shows up and locks the field.
  • Paths is a normal string slice. It was a custom slice whose env decoder only accepted one comma-separated value, so the _0 name never applied.
  • The old singular path field is gone. Config files that still contain it ignore that line.
  • Fixes (2) in v1.0.0 Config Inconsistencies and Bugs #831

Test plan

  • UN_SONARR_0_PATHS_0=/downloads shows /downloads on the Sonarr form and the question mark says UN_SONARR_0_PATHS_#.
  • Saving a Starr app writes paths and does not write path.
  • go test -count=1 ./pkg/unpackerr/ ./pkg/configdef/

davidnewhall and others added 3 commits October 26, 2026 21:15
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The focused frontend, backend, schema, and test changes are consistent, with no unresolved issues identified in static review; tests were not executed.

No open issues 🎉

What changed in this PR

Aligns Starr download-path settings across the WebUI and backend, addressing the indexed environment-variable mismatch reported in #831.

Changes:

  • Displays download paths as a multiline list and recognizes indexed UN_*_PATHS_0 overrides.
  • Uses a standard string slice and removes the legacy singular path field.
  • Updates API definitions, localized help, and regression tests.
File Description
pkg/​unpackerr/​openapi.json Removes singular path from the API schema.
pkg/​unpackerr/​handlers.go Changes Starr paths to a standard string slice.
pkg/​unpackerr/​configput_test.go Updates PUT tests to use path lists.
pkg/​unpackerr/​configclone.go Preserves deep copying of path slices.
pkg/​unpackerr/​configapi_test.go Updates GET test fixtures to use path lists.
pkg/​unpackerr/​cnfgfile.go Removes legacy singular-path handling.
pkg/​unpackerr/​cnfgfile_test.go Tests indexed environment paths and updates schema checks.
pkg/​configdef/​help.go Removes singular-path help aliases.
pkg/​configdef/​definitions_test.go Checks the plural paths help key.
frontend/​src/​pages/​settings/​StarrForm.svelte Adds multiline path editing and list serialization.
frontend/​src/​lib/​types.ts Removes the singular path property.
frontend/​src/​lib/​slug.ts Removes the singular path environment mapping.
frontend/​src/​lib/​i18n/​locales/​nl.json Updates Dutch path-list help.
frontend/​src/​lib/​i18n/​locales/​es.json Updates Spanish path-list help.
frontend/​src/​lib/​i18n/​locales/​en.json Updates English path-list help.
frontend/​src/​lib/​i18n/​locales/​el.json Updates Greek path-list help.
frontend/​src/​lib/​env.spec.ts Tests indexed Starr path matching and display.

Review effort: Balanced

Comment thread pkg/unpackerr/handlers.go
Comment thread pkg/unpackerr/cnfgfile.go

@qwen-pr-bot qwen-pr-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. Reviewed 9cde866c against base 9f02ad8, and since this one changes both runtime behavior and what the form renders, I built and ran both commits before signing off.

Three changes actually ship: StarrConfig.Paths drops its custom StringSlice type for a plain []string; the deprecated singular path field, its help alias, and the validateApp merge shim are gone; and the Starr form renders download paths as a two-line textarea (one per line) bound to the PATHS env name. i18n, the OpenAPI schema, and the test suite follow along consistently.

The crux is why the type swap matters: cnfg only routes indexed env names (PATHS_0, PATHS_1, …) to plain slices. A type implementing UnmarshalENV short-circuits to the single-value path, so at the base commit the UN_SONARR_0_PATHS_0 the compose example teaches was silently dropped — my harness confirmed it never reaches the field, never lands in the env-used list the lock badge reads, and doesn't create a phantom instance either. The bare comma-split UN_*_PATHS was the one form that worked. Your change flips exactly that, which is what #831(2) is asking for.

Same Sonarr settings form, config with paths = ["/downloads"]: at base the old singular Path input renders empty, the file's value is invisible to it.

Sonarr form at base 9f02ad8

At head with UN_SONARR_0_PATHS_0=/downloads set, the Paths textarea shows the env value, locked, and the question mark reads UN_SONARR_0_PATHS_#.

Sonarr form at head 9cde866c

Two non-blocking notes posted inline: the bare UN_*_PATHS comma form is now ignored as well (it worked before, though nothing documented it), and the "config files that still contain path ignore that line" claim is true but unguarded by a test.

Executed validation

  • go build ./... — clean.
  • go test -count=1 ./pkg/unpackerr/ ./pkg/configdef/ (the test plan here) — pass; go test -count=1 ./... — all packages pass.
  • Frontend at head: npm ci && npx vitest run — 46/46 across 13 files (45 at base, all pass); npm run check — 0 errors.
  • Disposable harness around unmarshalConfig at both commits: at head UN_SONARR_0_PATHS_0/_1 fill the live list in index order with the file snapshot untouched and the suffix recorded in the env-used map; at base the same names are ignored while the bare comma form works. A conf file containing the deprecated path = line loads without error at head; the line is inert.
  • Served both builds from this checkout on loopback (test config, proxy auth) and captured the Sonarr settings form via Chromium over CDP — the screenshots above are the actual rendered difference.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread pkg/unpackerr/cnfgfile.go
conf.DeleteDelay.Duration = u.DeleteDelay.Duration
}

if conf.Path != "" && !slices.Contains(conf.Paths, conf.Path) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The shim was half the legacy surface. UN_*_PATH (which the old UI badge literally told people to set) and bare UN_*_PATHS=/a,/b (the old StringSlice comma-split) are ignored by this commit too, and since they're never consumed they never reach /api/config/env, so the UI shows no sign they exist. Verified both at base: one worked and locked the field, the other never showed up anywhere in the UI even though the file-side path line was merged here. The repo's own compose examples and definitions.yml documented the indexed form all along, so the blast radius is mostly people who followed the old badge, but upgrade notes should mention the env side as well. If it's wanted, a one-line startup warning naming those two forms is a cheap ~15 lines. Not a blocker.


let rows = $state<InstanceRow<StarrConfig>[]>([])
let orig = $state<Record<string, StarrConfig>>({})
let pathsText = $state<Record<string, string>>({})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove(id) never deletes the orphaned pathsText[id] entry. Nothing reads it since every consumer keys off row.id, so it's harmless, but delete it alongside the row so the two stay in sync while this map is new.

Comment thread pkg/unpackerr/cnfgfile.go

for idx, path := range conf.Paths {
conf.Paths[idx] = expandHomedir(path)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UN_*_PATHS_0= (present but empty) now lands as Paths=[""], which skips this default fill, whereas the old StringSlice decoder treated an empty value as a no-op. Nobody sets an empty path in practice, but filtering blank entries before this check keeps the fallback honest when it does happen.

Co-authored-by: Cursor <cursoragent@cursor.com>
@davidnewhall
davidnewhall merged commit af4c765 into main Oct 27, 2026
10 checks passed
@davidnewhall
davidnewhall deleted the fix/starr-paths-list branch October 27, 2026 05:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants