ci: linter (#14)

* ci: add linter

* chore: update dependencies

* remove package.json

* feat: use enums

* ci: rename workflow
This commit is contained in:
martin 2023-12-23 21:58:57 +01:00 committed by GitHub
parent b52e18aca1
commit 7e3d56c3e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 71 additions and 72 deletions

View file

@ -1,4 +1,4 @@
name: Publish Release name: docker
on: on:
workflow_dispatch: workflow_dispatch:
@ -16,7 +16,7 @@ on:
branches: ["main"] branches: ["main"]
jobs: jobs:
build_docker_release: build_and_push:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
@ -33,7 +33,6 @@ jobs:
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }} ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}
tags: | tags: |
type=raw,value=latest,enable=${{ github.event_name == 'release' }} type=raw,value=latest,enable=${{ github.event_name == 'release' }}
type=sha
type=ref,event=branch type=ref,event=branch
type=ref,event=pr type=ref,event=pr
type=raw,value=${{ inputs.tags }},enable=${{ github.event_name == 'workflow_dispatch' }} type=raw,value=${{ inputs.tags }},enable=${{ github.event_name == 'workflow_dispatch' }}

View file

@ -13,7 +13,14 @@ jobs:
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Run unit tests - name: Run unit tests
run: go test -v ./src/tests run: go test -v ./src/tests
- name: Run formatter - name: Run formatter
run: test -z $(gofmt -l ./src) run: test -z $(gofmt -l ./src)
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.55.2

View file

@ -10,7 +10,6 @@ RUN go build -o /go/bin/immich-exporter ./src
FROM alpine:3.18 FROM alpine:3.18
COPY --from=builder /go/bin/immich-exporter /go/bin/immich-exporter COPY --from=builder /go/bin/immich-exporter /go/bin/immich-exporter
COPY package.json /go/bin/
WORKDIR /go/bin WORKDIR /go/bin

2
go.mod
View file

@ -16,5 +16,5 @@ require (
github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/common v0.45.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect
golang.org/x/sys v0.15.0 // indirect golang.org/x/sys v0.15.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect google.golang.org/protobuf v1.32.0 // indirect
) )

8
go.sum
View file

@ -5,8 +5,6 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
@ -31,10 +29,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

14
makefile Normal file
View file

@ -0,0 +1,14 @@
build:
go build -o ./qbittorrent-exporter.out ./src
dev :
go run ./src
dev-env :
go run ./src -e
format :
go fmt ./src
lint:
docker run --rm -v ./:/app -w /app golangci/golangci-lint:latest golangci-lint run -v
test:
go test -v ./src/tests
update:
go get -u ./src && go mod tidy

View file

@ -1,24 +0,0 @@
{
"name": "immich-exporter",
"version": "1.2.0",
"description": "exporter for immich",
"main": "src/main.go",
"scripts": {
"build" : "go build -o ./immich-exporter.out ./src && ./immich-exporter.out",
"build:env" : "go build -o ./immich-exporter.out ./src && ./immich-exporter.out -e",
"dev" : "go run ./src",
"dev:env" : "go run ./src -e",
"test": "go test -v ./src/tests",
"update": "go get -u ./src && go mod tidy"
},
"keywords": [
"exporter",
"immich",
"grafana",
"dashboard",
"metrics",
"prometheus"
],
"author": "martabal",
"license": "MIT"
}

View file

@ -4,7 +4,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"immich-exp/src/models" "immich-exp/src/models"
"io/ioutil" "io"
"net/http" "net/http"
"sync" "sync"
@ -22,6 +22,28 @@ var (
mutex sync.Mutex mutex sync.Mutex
) )
type Data struct {
URL string
HTTPMethod string
}
var httpGetUsers = Data{
URL: "/api/user?isAll=true",
HTTPMethod: http.MethodGet,
}
var httpServerVersion = Data{
URL: "/api/server-info/version",
HTTPMethod: http.MethodGet,
}
var httpStatistics = Data{
URL: "/api/server-info/statistics",
HTTPMethod: http.MethodGet,
}
var httpGetJobs = Data{
URL: "/api/jobs",
HTTPMethod: http.MethodGet,
}
var unmarshalError = "Can not unmarshal JSON" var unmarshalError = "Can not unmarshal JSON"
func Allrequests(r *prometheus.Registry) { func Allrequests(r *prometheus.Registry) {
@ -63,10 +85,10 @@ func Analyze(r *prometheus.Registry) {
func GetAllUsers(c chan func() (*models.StructAllUsers, error)) { func GetAllUsers(c chan func() (*models.StructAllUsers, error)) {
defer wg.Done() defer wg.Done()
resp, err := Apirequest("/api/user?isAll=true", "GET") resp, err := Apirequest(httpGetUsers.URL, httpGetUsers.HTTPMethod)
if err == nil { if err == nil {
body, err := ioutil.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Fatalln(err) log.Fatalln(err)
} else { } else {
@ -85,10 +107,10 @@ func GetAllUsers(c chan func() (*models.StructAllUsers, error)) {
func ServerVersion(r *prometheus.Registry) { func ServerVersion(r *prometheus.Registry) {
defer wg.Done() defer wg.Done()
resp, err := Apirequest("/api/server-info/version", "GET") resp, err := Apirequest(httpServerVersion.URL, httpServerVersion.HTTPMethod)
if err == nil { if err == nil {
body, err := ioutil.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Fatalln(err) log.Fatalln(err)
} else { } else {
@ -105,10 +127,10 @@ func ServerVersion(r *prometheus.Registry) {
func ServerInfo(c chan func() (*models.StructServerInfo, error)) { func ServerInfo(c chan func() (*models.StructServerInfo, error)) {
defer wg.Done() defer wg.Done()
resp, err := Apirequest("/api/server-info/statistics", "GET") resp, err := Apirequest(httpStatistics.URL, httpStatistics.HTTPMethod)
if err == nil { if err == nil {
body, err := ioutil.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Fatalln(err) log.Fatalln(err)
} else { } else {
@ -126,10 +148,10 @@ func ServerInfo(c chan func() (*models.StructServerInfo, error)) {
func GetAllJobsStatus(c chan func() (*models.StructAllJobsStatus, error)) { func GetAllJobsStatus(c chan func() (*models.StructAllJobsStatus, error)) {
defer wg.Done() defer wg.Done()
resp, err := Apirequest("/api/jobs", "GET") resp, err := Apirequest(httpGetJobs.URL, httpGetJobs.HTTPMethod)
if err == nil { if err == nil {
body, err := ioutil.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Fatalln(err) log.Fatalln(err)
} else { } else {
@ -158,7 +180,7 @@ func Apirequest(uri string, method string) (*http.Response, error) {
if err != nil { if err != nil {
err := fmt.Errorf("Can't connect to server") err := fmt.Errorf("Can't connect to server")
mutex.Lock() mutex.Lock()
if models.GetPromptError() == false { if !models.GetPromptError() {
log.Error(err.Error()) log.Error(err.Error())
models.SetPromptError(true) models.SetPromptError(true)
} }
@ -175,17 +197,15 @@ func Apirequest(uri string, method string) (*http.Response, error) {
mutex.Unlock() mutex.Unlock()
return resp, nil return resp, nil
case http.StatusNotFound: case http.StatusNotFound:
err := fmt.Errorf("%d", resp.StatusCode)
log.Fatal("Error code ", resp.StatusCode, " for ", models.Getbaseurl()+uri) log.Fatal("Error code ", resp.StatusCode, " for ", models.Getbaseurl()+uri)
return resp, err return resp, fmt.Errorf("%d", resp.StatusCode)
case http.StatusUnauthorized, http.StatusForbidden: case http.StatusUnauthorized, http.StatusForbidden:
err := fmt.Errorf("%d", resp.StatusCode)
log.Fatal("Api key unauthorized") log.Fatal("Api key unauthorized")
return resp, err return resp, fmt.Errorf("%d", resp.StatusCode)
default: default:
err := fmt.Errorf("%d", resp.StatusCode) err := fmt.Errorf("%d", resp.StatusCode)
mutex.Lock() mutex.Lock()

View file

@ -1,7 +1,6 @@
package main package main
import ( import (
"encoding/json"
"flag" "flag"
"fmt" "fmt"
immich "immich-exp/src/immich" immich "immich-exp/src/immich"
@ -20,16 +19,24 @@ import (
) )
const DEFAULTPORT = 8090 const DEFAULTPORT = 8090
const AUTHOR = "martabal"
const VERSION = "1.2.0"
const PROJECT_NAME = "immich-exporter"
func main() { func main() {
loadenv() loadenv()
projectinfo() fmt.Printf("%s (version %s)\n", PROJECT_NAME, VERSION)
fmt.Println("Author: ", AUTHOR)
fmt.Println("Using log level: ", log.GetLevel())
log.Info("Immich URL: ", models.Getbaseurl()) log.Info("Immich URL: ", models.Getbaseurl())
log.Info("Started") log.Info("Started")
http.HandleFunc("/metrics", metrics) http.HandleFunc("/metrics", metrics)
addr := ":" + strconv.Itoa(models.GetPort()) addr := ":" + strconv.Itoa(models.GetPort())
log.Info("Listening on port ", models.GetPort()) log.Info("Listening on port ", models.GetPort())
http.ListenAndServe(addr, nil) err := http.ListenAndServe(addr, nil)
if err != nil {
log.Fatalln(err)
}
} }
func metrics(w http.ResponseWriter, r *http.Request) { func metrics(w http.ResponseWriter, r *http.Request) {
@ -40,25 +47,6 @@ func metrics(w http.ResponseWriter, r *http.Request) {
h.ServeHTTP(w, r) h.ServeHTTP(w, r)
} }
func projectinfo() {
fileContent, err := os.ReadFile("./package.json")
if err != nil {
log.Fatal(err)
return
}
var res map[string]interface{}
err = json.Unmarshal(fileContent, &res)
if err != nil {
log.Fatal(err)
return
}
fmt.Print(res["name"], " (version ", res["version"], ")\n")
fmt.Print("Author: ", res["author"], "\n")
fmt.Print("Using log level: ", log.GetLevel(), "\n")
}
func loadenv() { func loadenv() {
var envfile bool var envfile bool
flag.BoolVar(&envfile, "e", false, "Use .env file") flag.BoolVar(&envfile, "e", false, "Use .env file")