Compare commits

18 Commits

Author SHA1 Message Date
1cdc101cec chore(deps): update dependency golangci/golangci-lint to v2.3.1
All checks were successful
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-amd64) (push) Successful in 14s
Lint Markdown files / Run markdown linter (pull_request) Successful in 4s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-arm64) (push) Successful in 45s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-amd64) (pull_request) Successful in 1m16s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-arm64) (pull_request) Successful in 46s
2025-08-12 19:12:19 +00:00
681e6726b1 Merge pull request 'chore(deps): update docker/login-action action to v3.5.0' (#27) from renovate/actions into master
All checks were successful
Lint Markdown files / Run markdown linter (push) Successful in 4s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-amd64) (push) Successful in 1m20s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-arm64) (push) Successful in 46s
2025-08-12 16:35:14 +00:00
72422e032d chore(deps): update docker/login-action action to v3.5.0
All checks were successful
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-amd64) (push) Successful in 13s
Lint Markdown files / Run markdown linter (pull_request) Successful in 3s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-amd64) (pull_request) Successful in 2m13s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-arm64) (push) Successful in 46s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-arm64) (pull_request) Successful in 45s
2025-08-12 16:29:24 +00:00
2f17abedb9 fix: be compliant with golanci linter
All checks were successful
Lint Markdown files / Run markdown linter (push) Successful in 13s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-amd64) (push) Successful in 30s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-arm64) (push) Successful in 1m38s
2025-08-12 16:28:40 +02:00
d2cf678b97 chore(deps): update actions/checkout to v4.3.0
Some checks failed
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-arm64) (push) Failing after 1m34s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-amd64) (push) Failing after 1m44s
Lint Markdown files / Run markdown linter (push) Successful in 6s
2025-08-12 08:48:22 +02:00
87918c2339 fix(ci): disable tests
Some checks failed
Lint Markdown files / Run markdown linter (push) Successful in 5s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-amd64) (push) Failing after 2m7s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-arm64) (push) Failing after 1m34s
2025-08-12 08:34:22 +02:00
7253c2ed5b fix(ci): rename workflows
Some checks failed
Run Golang tests / Run unit tests (stable, ubuntu-latest-amd64) (push) Failing after 17s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-amd64) (push) Failing after 29s
Lint Markdown files / Run markdown linter (push) Successful in 13s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-arm64) (push) Failing after 1m34s
Run Golang tests / Run unit tests (stable, ubuntu-latest-arm64) (push) Failing after 14s
2025-08-12 08:33:25 +02:00
8708af6a5a fix(ci): rename workflows
Some checks failed
Run Golang tests / Run unit tests (stable, ubuntu-latest-amd64) (push) Failing after 21s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-amd64) (push) Failing after 25s
Lint Markdown files / Run markdown linter (push) Successful in 15s
Lint Golang files / Run golang CI linter (stable, ubuntu-latest-arm64) (push) Failing after 1m20s
Run Golang tests / Run unit tests (stable, ubuntu-latest-arm64) (push) Failing after 13s
2025-08-12 08:24:30 +02:00
b525c82ccb chore(ci): add golangci-lint
Some checks failed
Golang Tests / unittest (stable, ubuntu-latest-amd64) (push) Failing after 5s
Golang CI lint / golangci (stable, ubuntu-latest-amd64) (push) Failing after 26s
Markdown linter / markdown-lint (push) Successful in 4s
Golang Tests / unittest (stable, ubuntu-latest-arm64) (push) Failing after 16s
Golang CI lint / golangci (stable, ubuntu-latest-arm64) (push) Failing after 2m37s
2025-06-01 12:18:46 +02:00
d39989d224 chore(ci): update workflow_dispatch for update docker hub description
All checks were successful
Markdown linter / markdown-lint (push) Successful in 16s
2025-05-31 22:04:27 +02:00
dfe4fd60cf chore(deps): update davidanson/markdownlint-cli2-action action to v20
All checks were successful
Markdown linter / markdown-lint (pull_request) Successful in 4s
Markdown linter / markdown-lint (push) Successful in 4s
2025-05-29 13:18:28 +00:00
d1e111fe0d feat(riscv64): add support
All checks were successful
Markdown linter / markdown-lint (push) Successful in 14s
2025-05-29 13:16:30 +02:00
f40cb5f965 chore(ci): use DavidAnson/markdownlint-cli2-action v19.1.0
All checks were successful
Markdown linter / markdown-lint (push) Successful in 4s
2025-05-29 13:15:43 +02:00
02d980440f chore(deps): update git.cryptic.systems/volker.raschek/markdownlint docker tag to v0.45.0
All checks were successful
Markdown linter / markdown-lint (pull_request) Successful in 1m11s
Markdown linter / markdown-lint (push) Successful in 12s
2025-05-28 13:13:08 +00:00
7baa16a257 chore(ci): remove golang tests
All checks were successful
Markdown linter / markdown-lint (push) Successful in 2s
2025-05-13 20:34:31 +02:00
df3192ab75 chore(ci): remove golangci-linter
Some checks failed
Markdown linter / markdown-lint (push) Successful in 11s
Golang Tests / unittest (push) Failing after 17s
2025-05-13 20:26:33 +02:00
b316124df4 chore(ci): add golangci-linter
Some checks failed
Markdown linter / markdown-lint (push) Successful in 12s
Golang Tests / unittest (push) Failing after 20s
golangci-lint / lint (stable, ubuntu-latest) (push) Failing after 1m10s
2025-05-13 20:21:56 +02:00
fe9a5278f7 chore(deps): update module github.com/fsnotify/fsnotify to v1.9.0
All checks were successful
Markdown linter / markdown-lint (pull_request) Successful in 15s
Markdown linter / markdown-lint (push) Successful in 11s
2025-05-13 16:14:15 +00:00
14 changed files with 162 additions and 48 deletions

View File

@ -0,0 +1,29 @@
name: "Lint Golang files"
on:
pull_request:
types: [ "opened", "reopened", "synchronize" ]
push:
branches: [ '**' ]
tags-ignore: [ '**' ]
workflow_dispatch: {}
permissions:
contents: read
jobs:
golangci:
name: "Run golang CI linter"
runs-on: ${{ matrix.os }}
strategy:
matrix:
go: [ stable ]
os: [ ubuntu-latest-amd64, ubuntu-latest-arm64 ]
steps:
- uses: actions/checkout@v4.3.0
- uses: actions/setup-go@v5.5.0
with:
go-version: ${{ matrix.go }}
- uses: golangci/golangci-lint-action@v8.0.0
with:
version: v2.3.1 # renovate: datasource=github-releases depName=golangci/golangci-lint

View File

@ -1,4 +1,4 @@
# name: Golang Tests
# name: "Run Golang tests"
# on:
# pull_request:
@ -6,16 +6,37 @@
# push:
# branches: [ '**' ]
# tags-ignore: [ '**' ]
# workflow_dispatch: {}
# jobs:
# unittest:
# runs-on:
# - ubuntu-latest
# integration-test:
# name: "Run integration tests"
# runs-on: ${{ matrix.os }}
# strategy:
# matrix:
# go: [ stable ]
# os: [ ubuntu-latest-amd64, ubuntu-latest-arm64 ]
# steps:
# - uses: actions/checkout@v4.2.2
# - uses: actions/checkout@v4.3.0
# - uses: actions/setup-go@v5.5.0
# with:
# go-version: stable
# go-version: ${{ matrix.go }}
# - env:
# GOPROXY: ${{ vars.GOPROXY }}
# run: make test/integration
# unit-test:
# name: "Run unit tests"
# runs-on: ${{ matrix.os }}
# strategy:
# matrix:
# go: [ stable ]
# os: [ ubuntu-latest-amd64, ubuntu-latest-arm64 ]
# steps:
# - uses: actions/checkout@v4.3.0
# - uses: actions/setup-go@v5.5.0
# with:
# go-version: ${{ matrix.go }}
# - env:
# GOPROXY: ${{ vars.GOPROXY }}
# run: make test/unit

View File

@ -1,20 +1,19 @@
name: Markdown linter
name: "Lint Markdown files"
on:
pull_request:
types: [ "opened", "reopened", "synchronize" ]
push:
branches: [ '**' ]
tags-ignore: [ '**' ]
branches: [ '*' ]
tags-ignore: [ '*' ]
workflow_dispatch: {}
jobs:
markdown-lint:
container:
image: git.cryptic.systems/volker.raschek/markdownlint:0.44.0
runs-on:
- ubuntu-latest
name: "Run markdown linter"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.2.2
- name: Lint Markdown files
run: markdownlint --config .markdownlint.yaml .
- uses: actions/checkout@v4.3.0
- uses: DavidAnson/markdownlint-cli2-action@v19.1.0
with:
globs: '**/*.md'

View File

@ -1,4 +1,4 @@
name: Release
name: "Release"
on:
push:
@ -9,15 +9,15 @@ permissions:
jobs:
release:
runs-on:
- ubuntu-latest
name: "Release application"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.2.2
- uses: actions/checkout@v4.3.0
- uses: docker/setup-qemu-action@v3.6.0
- uses: actions/setup-go@v5.5.0
with:
go-version: stable
- uses: docker/login-action@v3.4.0
- uses: docker/login-action@v3.5.0
with:
registry: git.cryptic.systems
username: ${{ github.repository_owner }}
@ -28,10 +28,11 @@ jobs:
GOPROXY: ${{ vars.GOPROXY }}
uses: goreleaser/goreleaser-action@v6.3.0
with:
version: "~> v2"
version: v2.11.2 # renovate: datasource=github-releases depName=goreleaser/goreleaser
args: release --clean
sync-to-hub-docker-io:
name: "Upload Images to docker.io"
needs:
- release
runs-on: ubuntu-latest

View File

@ -4,16 +4,17 @@ on:
push:
branches: [ 'master' ]
paths: [ 'README.md' ]
workflow_dispatch: {}
jobs:
update-description-on-hub-docker-io:
runs-on:
- ubuntu-latest
steps:
- uses: actions/checkout@v4.2.2
- uses: actions/checkout@v4.3.0
- uses: peter-evans/dockerhub-description@v4.0.2
with:
username: ${{ secrets.DOCKER_IO_USERNAME }}
password: ${{ secrets.DOCKER_IO_PASSWORD }}
repository: volkerraschek/tarr
readme-filepath: README.md
readme-filepath: README.md

13
.golangci.yaml Normal file
View File

@ -0,0 +1,13 @@
version: "2"
linters:
default: standard
enable:
- errname
- gosec
exclusions:
rules: []
warn-unused: true
run:
tests: true

View File

@ -34,6 +34,7 @@ builds:
- amd64
- arm
- arm64
- riscv64
goarm:
- "6"
- "7"
@ -171,6 +172,25 @@ dockers:
skip_push: false
use: buildx
- build_flag_templates:
- --label=org.opencontainers.image.created={{ time "2006-01-02T15:04:05Z07:00" }}
- --label=org.opencontainers.image.description={{ .ProjectName }}
- --label=org.opencontainers.image.documentation={{ .ProjectName }}
- --label=org.opencontainers.image.revision={{ .FullCommit }}
- --label=org.opencontainers.image.source={{ .GitURL }}
- --label=org.opencontainers.image.title={{ .ProjectName }}
- --label=org.opencontainers.image.url=https://git.cryptic.systems/volker.raschek/{{ .ProjectName }}
- --label=org.opencontainers.image.version={{ trimprefix .Tag "v" }}
- --platform=linux/riscv64
- --pull
dockerfile: Dockerfile
goarch: riscv64
goos: linux
image_templates:
- 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}-riscv64'
skip_push: false
use: buildx
docker_manifests:
- name_template: 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}'
image_templates:
@ -178,6 +198,7 @@ docker_manifests:
- 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}-arm-v6'
- 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}-arm-v7'
- 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}-arm64'
- 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}-riscv64'
gitea_urls:
api: https://git.cryptic.systems/api/v1

View File

@ -2,6 +2,7 @@ package main
import (
"fmt"
"log"
"os"
"path/filepath"
"time"
@ -26,7 +27,9 @@ autharr /etc/lidarr/config.xml`,
}
rootCmd.Flags().Bool("watch", false, "Listens for changes to the configuration and writes the token continuously to the output")
rootCmd.Execute()
if err := rootCmd.Execute(); err != nil {
log.Fatalln(err)
}
}
func runE(cmd *cobra.Command, args []string) error {
@ -84,10 +87,16 @@ func runWatch(cmd *cobra.Command, args []string) error {
select {
case <-cmd.Context().Done():
return nil
case err := <-errorChannel:
logrus.WithError(err).Errorln("Received from config watcher")
case err, open := <-errorChannel:
if !open {
return fmt.Errorf("error channel has been closed")
}
logrus.WithError(err).Errorln("received from config watcher")
case <-timer.C:
writeConfig(cachedConfig, dest)
err = writeConfig(cachedConfig, dest)
if err != nil {
logrus.WithError(err).Errorln("failed to write config")
}
case config := <-configChannel:
cachedConfig = config
timer.Reset(waitFor)
@ -105,18 +114,23 @@ func writeConfig(config *domain.Config, dest string) error {
case len(dest) > 0:
dirname := filepath.Dir(dest)
// #nosec G301
err := os.MkdirAll(dirname, 0755)
if err != nil {
return err
}
// #nosec G304
f, err := os.Create(dest)
if err != nil {
return err
}
defer func() { _ = f.Close() }()
f.WriteString(config.API.Token)
_, err = f.WriteString(config.API.Token)
if err != nil {
return err
}
}
return nil

View File

@ -3,6 +3,7 @@ package main
import (
"context"
"fmt"
"log"
"time"
"git.cryptic.systems/volker.raschek/tarr/pkg/config"
@ -95,7 +96,10 @@ healarr sonarr https://sonarr.example.com:8443 --api-token my-token`,
rootCmd.PersistentFlags().Bool("insecure", false, "Trust insecure TLS certificates")
rootCmd.PersistentFlags().Duration("timeout", time.Minute, "Timeout")
rootCmd.Execute()
err := rootCmd.Execute()
if err != nil {
log.Fatalln(err)
}
}
func runBazarrE(cmd *cobra.Command, args []string) error {
@ -152,7 +156,7 @@ func runE(cmd *cobra.Command, args []string, queryKey string) error {
switch {
case len(apiToken) <= 0 && len(configPath) <= 0:
return fmt.Errorf("At least --api-token oder --config must be defined")
return fmt.Errorf("at least --api-token oder --config must be defined")
case len(apiToken) > 0 && len(configPath) <= 0:
err = health.NewReadinessProbe(args[0]).
QueryAdd(queryKey, apiToken).
@ -175,7 +179,7 @@ func runE(cmd *cobra.Command, args []string, queryKey string) error {
return err
}
default:
return fmt.Errorf("Neither --api-token nor --config can be used at the same time.")
return fmt.Errorf("neither --api-token nor --config can be used at the same time")
}
return nil

2
go.mod
View File

@ -3,7 +3,7 @@ module git.cryptic.systems/volker.raschek/tarr
go 1.22.6
require (
github.com/fsnotify/fsnotify v1.8.0
github.com/fsnotify/fsnotify v1.9.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.9.1
github.com/stretchr/testify v1.10.0

4
go.sum
View File

@ -2,8 +2,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6N
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=

View File

@ -46,11 +46,12 @@ type YAMLConfig struct {
// Read reads the config struct from a file. The decoding format will be determined by the file extension like
// `xml` or `yaml`.
func ReadConfig(name string) (*domain.Config, error) {
// #nosec G304
f, err := os.Open(name)
if err != nil {
return nil, err
}
defer f.Close()
defer func() { _ = f.Close() }()
switch {
case strings.HasSuffix(name, "xml"):
@ -58,7 +59,7 @@ func ReadConfig(name string) (*domain.Config, error) {
case strings.HasSuffix(name, "yml") || strings.HasSuffix(name, "yaml"):
return readYAMLConfig(f)
default:
return nil, fmt.Errorf("Unsupported file extension")
return nil, fmt.Errorf("unsupported file extension")
}
}
@ -97,8 +98,8 @@ func readYAMLConfig(r io.Reader) (*domain.Config, error) {
}
func WatchConfig(ctx context.Context, name string) (<-chan *domain.Config, <-chan error) {
configChannel := make(chan *domain.Config, 0)
errorChannel := make(chan error, 0)
configChannel := make(chan *domain.Config)
errorChannel := make(chan error)
go func() {
wait := time.Second * 3
@ -110,14 +111,18 @@ func WatchConfig(ctx context.Context, name string) (<-chan *domain.Config, <-cha
errorChannel <- err
return
}
watcher.Add(name)
err = watcher.Add(name)
if err != nil {
errorChannel <- err
return
}
for {
select {
case <-ctx.Done():
close(configChannel)
close(errorChannel)
break
return
case event, open := <-watcher.Events:
if !open {
errorChannel <- fmt.Errorf("FSWatcher closed channel: %w", err)
@ -145,11 +150,12 @@ func WatchConfig(ctx context.Context, name string) (<-chan *domain.Config, <-cha
// WriteConfig writes the config struct into the file. The encoding format will be determined by the file extension like
// `xml` or `yaml`.
func WriteConfig(name string, config *domain.Config) error {
// #nosec G304
f, err := os.Create(name)
if err != nil {
return err
}
defer f.Close()
defer func() { _ = f.Close() }()
switch {
case strings.HasSuffix(name, "xml"):
@ -157,13 +163,13 @@ func WriteConfig(name string, config *domain.Config) error {
case strings.HasSuffix(name, "yml") || strings.HasSuffix(name, "yaml"):
return writeYAMLConfig(f, config)
default:
return fmt.Errorf("Unsupported file extension")
return fmt.Errorf("unsupported file extension")
}
}
func writeXMLConfig(w io.Writer, config *domain.Config) error {
xmlEncoder := xml.NewEncoder(w)
defer xmlEncoder.Close()
defer func() { _ = xmlEncoder.Close() }()
xmlConfig := &XMLConfig{
APIToken: config.API.Token,
@ -180,7 +186,7 @@ func writeXMLConfig(w io.Writer, config *domain.Config) error {
func writeYAMLConfig(w io.Writer, config *domain.Config) error {
yamlEncoder := yaml.NewEncoder(w)
defer yamlEncoder.Close()
defer func() { _ = yamlEncoder.Close() }()
yamlConfig := &YAMLConfig{
Auth: YAMLConfigAuth{

View File

@ -24,6 +24,7 @@ func TestReadWriteConfig_XML(t *testing.T) {
t.Cleanup(func() { _ = os.RemoveAll(tmpDir) })
expectedXMLConfigName := filepath.Join(tmpDir, "expected_config.xml")
// #nosec G304
f, err := os.Create(expectedXMLConfigName)
require.NoError(err)
@ -38,6 +39,7 @@ func TestReadWriteConfig_XML(t *testing.T) {
err = config.WriteConfig(actualXMLConfigName, actualConfig)
require.NoError(err)
// #nosec G304
b, err := os.ReadFile(actualXMLConfigName)
require.NoError(err)
require.Equal(expectedXMLConfig, string(b))
@ -51,6 +53,7 @@ func TestReadWriteConfig_YAML(t *testing.T) {
t.Cleanup(func() { _ = os.RemoveAll(tmpDir) })
expectedYAMLConfigName := filepath.Join(tmpDir, "expected_config.yaml")
// #nosec G304
f, err := os.Create(expectedYAMLConfigName)
require.NoError(err)
@ -65,6 +68,7 @@ func TestReadWriteConfig_YAML(t *testing.T) {
err = config.WriteConfig(actualYAMLConfigName, actualConfig)
require.NoError(err)
// #nosec G304
b, err := os.ReadFile(actualYAMLConfigName)
require.NoError(err)
require.Equal(expectedYAMLConfig, string(b))

View File

@ -9,8 +9,8 @@ import (
"net/url"
)
var ErrNoAPIToken error = errors.New("No API token defined")
var ErrNoURL error = errors.New("No API token defined")
var ErrNoAPIToken error = errors.New("no API token defined")
var ErrNoURL error = errors.New("no API token defined")
type ReadinessProbe struct {
additionalQueryValues url.Values
@ -40,6 +40,7 @@ func (rp *ReadinessProbe) Run(ctx context.Context) error {
httpClient := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
// #nosec G402
InsecureSkipVerify: rp.insecure,
},
},
@ -64,7 +65,7 @@ func (rp *ReadinessProbe) Run(ctx context.Context) error {
}
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("Received unexpected HTTP status code %v", resp.StatusCode)
return fmt.Errorf("received unexpected HTTP status code %v", resp.StatusCode)
}
return nil