diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 357928b..8da1e10 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,12 +22,12 @@ jobs: - name: Build run: make callhome - + - name: Lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v6 with: - version: latest - args: --no-config --disable-all --enable gosimple --enable govet --enable unused --enable deadcode --timeout 3m + version: v1.59.1 + args: --config .golangci.yml - name: Run tests run: make test diff --git a/.github/workflows/server-build.yml b/.github/workflows/server-build.yml index 5107941..8db478a 100644 --- a/.github/workflows/server-build.yml +++ b/.github/workflows/server-build.yml @@ -8,30 +8,30 @@ on: jobs: - push_to_registry: - name: Push Docker image to Docker Hub + build-and-push-image: runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + steps: - - name: Check out the repo - uses: actions/checkout@v3 - - - name: Log in to Docker Hub - uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to the Container registry + uses: docker/login-action@v3 with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_SECRET }} + - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + uses: docker/metadata-action@v5 with: - images: magistrala/callhome - - - name: Build and push Docker image - uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 - with: - context: docker/ - file: ./Dockerfile - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push Docker images + run: | + make latest + diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..476c49e --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,84 @@ +# Copyright (c) Abstract Machines +# SPDX-License-Identifier: Apache-2.0 + +run: + timeout: 10m + build-tags: + - "nats" + +issues: + max-issues-per-linter: 100 + max-same-issues: 100 + exclude: + - "string `Usage:\n` has (\\d+) occurrences, make it a constant" + - "string `For example:\n` has (\\d+) occurrences, make it a constant" + exclude-rules: + - path: cli/commands_test.go + linters: + - godot + +linters-settings: + gocritic: + enabled-checks: + - importShadow + - httpNoBody + - paramTypeCombine + - emptyStringTest + - builtinShadow + - exposedSyncMutex + disabled-checks: + - appendAssign + enabled-tags: + - diagnostic + disabled-tags: + - performance + - style + - experimental + - opinionated + misspell: + ignore-words: + - "mosquitto" + stylecheck: + checks: ["-ST1000", "-ST1003", "-ST1020", "-ST1021", "-ST1022"] + goheader: + template: |- + Copyright (c) Abstract Machines + SPDX-License-Identifier: Apache-2.0 + +linters: + disable-all: true + enable: + - gocritic + - gosimple + - errcheck + - govet + - unused + - goconst + - godot + - godox + - ineffassign + - misspell + - stylecheck + - whitespace + - gci + - gofmt + - goimports + - loggercheck + - goheader + - asasalint + - asciicheck + - bidichk + - contextcheck + - decorder + - dogsled + - errchkjson + - errname + - ginkgolinter + - gocheckcompilerdirectives + - gofumpt + - goprintffuncname + - importas + - makezero + - mirror + - nakedret + - dupword diff --git a/Makefile b/Makefile index 3846d2d..6b3dcf3 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ DOMAIN ?= deployments.magistrala.abstractmachines.fr all: $(PROGRAM) -.PHONY: all clean $(PROGRAM) +.PHONY: all clean $(PROGRAM) latest define make_docker docker build \ @@ -47,6 +47,7 @@ clean: docker-image: $(call make_docker) + dev-cert: $(call make_dev_cert) @@ -55,3 +56,7 @@ run: test: go test -v --race -covermode=atomic -coverprofile cover.out ./... + + +latest: docker-image + docker push magistrala/callhome:latest diff --git a/api/endpoint.go b/api/endpoint.go index 955c0a8..6ced587 100644 --- a/api/endpoint.go +++ b/api/endpoint.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package api import ( diff --git a/api/endpoint_test.go b/api/endpoint_test.go index f34c72e..4f34da3 100644 --- a/api/endpoint_test.go +++ b/api/endpoint_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package api import ( diff --git a/api/logging.go b/api/logging.go index 1a0a899..7bc00a6 100644 --- a/api/logging.go +++ b/api/logging.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package api import ( @@ -62,7 +65,7 @@ func (lm *loggingMiddleware) RetrieveSummary(ctx context.Context, filters callho return lm.svc.RetrieveSummary(ctx, filters) } -// ServeUI implements callhome.Service +// ServeUI implements callhome.Service. func (lm *loggingMiddleware) ServeUI(ctx context.Context, filters callhome.TelemetryFilters) (res []byte, err error) { defer func(begin time.Time) { message := fmt.Sprintf("Method serve ui event took %s to complete", time.Since(begin)) diff --git a/api/metrics.go b/api/metrics.go index cf9467e..44bdc7e 100644 --- a/api/metrics.go +++ b/api/metrics.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package api import ( @@ -54,7 +57,7 @@ func (mm *metricsMiddleware) RetrieveSummary(ctx context.Context, filters callho return mm.svc.RetrieveSummary(ctx, filters) } -// ServeUI implements callhome.Service +// ServeUI implements callhome.Service. func (mm *metricsMiddleware) ServeUI(ctx context.Context, filters callhome.TelemetryFilters) ([]byte, error) { defer func(begin time.Time) { mm.counter.With("method", "serve-ui").Add(1) diff --git a/api/requests.go b/api/requests.go index 4fd53fe..901aefc 100644 --- a/api/requests.go +++ b/api/requests.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package api import ( diff --git a/api/responses.go b/api/responses.go index 357d9ac..ef94c5f 100644 --- a/api/responses.go +++ b/api/responses.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package api import ( @@ -67,7 +70,7 @@ type uiRes struct { html []byte } -// Code implements magistrala.Response +// Code implements magistrala.Response. func (res uiRes) Code() int { if res.code == 0 { return http.StatusCreated @@ -76,12 +79,12 @@ func (res uiRes) Code() int { return res.code } -// Empty implements magistrala.Response +// Empty implements magistrala.Response. func (res uiRes) Empty() bool { return res.html == nil } -// Headers implements magistrala.Response +// Headers implements magistrala.Response. func (res uiRes) Headers() map[string]string { if res.headers == nil { return map[string]string{} @@ -97,17 +100,17 @@ type telemetrySummaryRes struct { TotalDeployments int `json:"total_deployments,omitempty"` } -// Code implements magistrala.Response +// Code implements magistrala.Response. func (*telemetrySummaryRes) Code() int { return http.StatusOK } -// Empty implements magistrala.Response +// Empty implements magistrala.Response. func (*telemetrySummaryRes) Empty() bool { return false } -// Headers implements magistrala.Response +// Headers implements magistrala.Response. func (res *telemetrySummaryRes) Headers() map[string]string { return map[string]string{} } diff --git a/api/transport.go b/api/transport.go index 1ce9f5a..73376d0 100644 --- a/api/transport.go +++ b/api/transport.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package api import ( @@ -15,7 +18,6 @@ import ( "github.com/absmach/magistrala/pkg/uuid" kithttp "github.com/go-kit/kit/transport/http" "github.com/go-zoo/bone" - "github.com/prometheus/client_golang/prometheus/promhttp" "go.opentelemetry.io/contrib/instrumentation/github.com/go-kit/kit/otelkit" "go.opentelemetry.io/otel/trace" diff --git a/api/utils.go b/api/utils.go index 2e6c6e3..2ef5acb 100644 --- a/api/utils.go +++ b/api/utils.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package api import ( @@ -29,7 +32,7 @@ func LoggingErrorEncoder(logger *slog.Logger, enc kithttp.ErrorEncoder) kithttp. } } -// ReadUintQuery reads the value of uint64 http query parameters for a given key +// ReadUintQuery reads the value of uint64 http query parameters for a given key. func ReadUintQuery(r *http.Request, key string, def uint64) (uint64, error) { vals := bone.GetQuery(r, key) if len(vals) > 1 { @@ -46,7 +49,7 @@ func ReadUintQuery(r *http.Request, key string, def uint64) (uint64, error) { return val, nil } -// ReadStringQuery reads the value of string http query parameters for a given key +// ReadStringQuery reads the value of string http query parameters for a given key. func ReadStringQuery(r *http.Request, key string, def string) (string, error) { vals := bone.GetQuery(r, key) if len(vals) > 1 { diff --git a/cmd/main.go b/cmd/main.go index 2fde69c..20250bd 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package main import ( @@ -49,7 +52,7 @@ func main() { logger, err := newLogger(os.Stdout, cfg.LogLevel) if err != nil { - log.Fatalf(fmt.Sprintf("failed to init logger: %s", err.Error())) + log.Fatalf("failed to init logger: %s", err.Error()) } timescaleDB, err := postgres.Setup(envPrefix, timescale.Migration()) if err != nil { @@ -60,18 +63,17 @@ func main() { if err != nil { log.Fatalf("Failed to init Jaeger: %s", err) } - defer func() { - if err := tp.Shutdown(context.Background()); err != nil { - log.Fatalf("Error shutting down tracer provider: %v", err) - } - }() tracer := tp.Tracer(svcName) svc, err := newService(ctx, logger, cfg.IPDatabaseFile, timescaleDB, tracer) if err != nil { log.Fatalf("failed to initialize service: %s", err) - return } + defer func() { + if err := tp.Shutdown(context.Background()); err != nil { + log.Fatalf("Error shutting down tracer provider: %v", err) + } + }() httpServerConfig := server.Config{Port: defSvcHttpPort} if err := env.Parse(&httpServerConfig, env.Options{Prefix: envPrefixHttp, AltPrefix: envPrefix}); err != nil { diff --git a/internal/clients/postgres/postgres.go b/internal/clients/postgres/postgres.go index 55a80c2..0056f63 100644 --- a/internal/clients/postgres/postgres.go +++ b/internal/clients/postgres/postgres.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package postgres import ( @@ -16,7 +19,7 @@ var ( errMigration = errors.New("failed to apply migrations") ) -// Config defines the options that are used when connecting to a TimescaleSQL instance +// Config defines the options that are used when connecting to a TimescaleSQL instance. type Config struct { Host string `env:"TIMESCALE_HOST" envDefault:"localhost"` Port string `env:"TIMESCALE_PORT" envDefault:"5432"` @@ -58,7 +61,7 @@ func SetupDB(cfg Config, migrations migrate.MemoryMigrationSource) (*sqlx.DB, er return db, nil } -// Connect creates a connection to the PostgreSQL instance +// Connect creates a connection to the PostgreSQL instance. func Connect(cfg Config) (*sqlx.DB, error) { url := fmt.Sprintf("host=%s port=%s user=%s dbname=%s password=%s sslmode=%s sslcert=%s sslkey=%s sslrootcert=%s", cfg.Host, cfg.Port, cfg.User, cfg.Name, cfg.Pass, cfg.SSLMode, cfg.SSLCert, cfg.SSLKey, cfg.SSLRootCert) @@ -70,7 +73,7 @@ func Connect(cfg Config) (*sqlx.DB, error) { return db, nil } -// MigrateDB applies any unapplied database migrations +// MigrateDB applies any unapplied database migrations. func MigrateDB(db *sqlx.DB, migrations migrate.MemoryMigrationSource) error { _, err := migrate.Exec(db.DB, "postgres", migrations, migrate.Up) if err != nil { diff --git a/internal/env/load.go b/internal/env/load.go index 30f9cea..7102c20 100644 --- a/internal/env/load.go +++ b/internal/env/load.go @@ -1,6 +1,9 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package env -// NewConfig gets configuration from environment variable +// NewConfig gets configuration from environment variable. func NewConfig[T any](opts ...Options) (T, error) { var cfg T if err := Parse(&cfg, opts...); err != nil { diff --git a/internal/env/parser.go b/internal/env/parser.go index 579b4d8..40081ef 100644 --- a/internal/env/parser.go +++ b/internal/env/parser.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package env import ( diff --git a/internal/server/http/http.go b/internal/server/http/http.go index ab7f893..e4cb817 100644 --- a/internal/server/http/http.go +++ b/internal/server/http/http.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package http import ( diff --git a/internal/server/server.go b/internal/server/server.go index 5706b34..23c21ab 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package server import ( diff --git a/location.go b/location.go index 5a4de0c..dc2d056 100644 --- a/location.go +++ b/location.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package callhome import ( @@ -27,7 +30,6 @@ func NewLocationService(dbfilepath string) (LocationService, error) { return &locationService{ db: db, }, nil - } // GetLocation returns the location information for a given IP address. diff --git a/mocks/location.go b/mocks/location.go index 37f3557..79e02f8 100644 --- a/mocks/location.go +++ b/mocks/location.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package mocks import ( diff --git a/mocks/service.go b/mocks/service.go index 0db963e..c496004 100644 --- a/mocks/service.go +++ b/mocks/service.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package mocks import ( @@ -13,7 +16,7 @@ type Service struct { mock.Mock } -// ServeUI implements callhome.Service +// ServeUI implements callhome.Service. func (*Service) ServeUI(ctx context.Context, filters callhome.TelemetryFilters) ([]byte, error) { return nil, nil } diff --git a/pkg/client/client.go b/pkg/client/client.go index 204504d..ac9de39 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package client import ( diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index 6315827..93bec22 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package client import ( diff --git a/service.go b/service.go index 2058bbb..cced4d0 100644 --- a/service.go +++ b/service.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package callhome import ( @@ -11,7 +14,7 @@ import ( const pageLimit = 1000 -// Service Service to receive homing telemetry data, persist and retrieve it. +// Service to receive homing telemetry data, persist and retrieve it. type Service interface { // Save saves the homing telemetry data and its location information. Save(ctx context.Context, t Telemetry) error @@ -61,7 +64,7 @@ func (ts *telemetryService) RetrieveSummary(ctx context.Context, filters Telemet return ts.repo.RetrieveSummary(ctx, filters) } -// ServeUI gets the callhome index html page +// ServeUI gets the callhome index html page. func (ts *telemetryService) ServeUI(ctx context.Context, filters TelemetryFilters) ([]byte, error) { tmpl := template.Must(template.ParseFiles("./web/template/index.html")) diff --git a/service_test.go b/service_test.go index 027ca4d..8ba0af1 100644 --- a/service_test.go +++ b/service_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package callhome_test import ( diff --git a/telemetry.go b/telemetry.go index 306492d..0abea5c 100644 --- a/telemetry.go +++ b/telemetry.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package callhome import ( diff --git a/timescale/errors.go b/timescale/errors.go index 9c0c561..2510a0b 100644 --- a/timescale/errors.go +++ b/timescale/errors.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package timescale import "errors" diff --git a/timescale/init.go b/timescale/init.go index 14e2336..c04b1ef 100644 --- a/timescale/init.go +++ b/timescale/init.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package timescale import ( @@ -5,7 +8,7 @@ import ( migrate "github.com/rubenv/sql-migrate" ) -// Migration of telemetry service +// Migration of Telemetry service. func Migration() migrate.MemoryMigrationSource { return migrate.MemoryMigrationSource{ Migrations: []*migrate.Migration{ diff --git a/timescale/mocks/mocks.go b/timescale/mocks/mocks.go index 0c1f694..ae1d2f9 100644 --- a/timescale/mocks/mocks.go +++ b/timescale/mocks/mocks.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package mocks import ( diff --git a/timescale/timescale.go b/timescale/timescale.go index 086309a..9485a19 100644 --- a/timescale/timescale.go +++ b/timescale/timescale.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package timescale import ( @@ -125,7 +128,7 @@ func (r repo) Save(ctx context.Context, t callhome.Telemetry) error { return nil } -// RetrieveSummary retrieve distinct +// RetrieveSummary retrieve distinct. func (r repo) RetrieveSummary(ctx context.Context, filters callhome.TelemetryFilters) (callhome.TelemetrySummary, error) { filterQuery, params := generateQuery(filters) var summary callhome.TelemetrySummary diff --git a/timescale/timescale_test.go b/timescale/timescale_test.go index 3952bc7..945ba06 100644 --- a/timescale/timescale_test.go +++ b/timescale/timescale_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package timescale import ( diff --git a/timescale/tracing/tracing.go b/timescale/tracing/tracing.go index 68ec426..599f507 100644 --- a/timescale/tracing/tracing.go +++ b/timescale/tracing/tracing.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package tracing import ( diff --git a/tracing/location.go b/tracing/location.go index 7570fcb..85741f2 100644 --- a/tracing/location.go +++ b/tracing/location.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package tracing import ( diff --git a/tracing/service.go b/tracing/service.go index e0fd842..1508476 100644 --- a/tracing/service.go +++ b/tracing/service.go @@ -1,3 +1,6 @@ +// Copyright (c) Abstract Machines +// SPDX-License-Identifier: Apache-2.0 + package tracing import (