Skip to content

Commit

Permalink
feat!: more lints and error fixes
Browse files Browse the repository at this point in the history
This introduces one error type as well.
  • Loading branch information
cking committed Feb 17, 2023
1 parent b3be4f3 commit 8b5ee40
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 27 deletions.
109 changes: 106 additions & 3 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,22 @@ output:

linters:
enable:
- errcheck
- errname
- errorlint
- gocritic
- gofmt
- goerr113
- gofumpt
- goheader
- goimports
- gosec
- gosimple
- govet
- ineffassign
- revive
- staticcheck
- testpackage
- thelper
- typecheck
- unused

disable-all: true

Expand All @@ -25,5 +30,103 @@ linters-settings:
- style
- performance

gofumpt:
extra-rules: true

goheader:
values:
const:
COMPANY: z0ne
regexp:
FILE: "[a-zA-Z0-9_]+\\.go"
template: |-
{{ FILE }} Copyright (c) {{ YEAR }} {{ COMPANY }}.
All Rights Reserved.
Licensed under the Apache 2.0 License.
See LICENSE the project root for license information.
SPDX-License-Identifier: Apache-2.0
govet:
check-shadowing: true
enable-all: true

revive:
rules:
- name: add-constant
arguments:
- maxLitCount: "3"
allowStrs: '""'
allowInts: "0,1,2"
allowFloats: "0.0,0.,1.0,1.,2.0,2."
- name: argument-limit
arguments: [4]
- name: atomic
- name: bare-return
- name: blank-imports
- name: bool-literal-in-expr
- name: call-to-gc
- name: cognitive-complexity
arguments: [10]
- name: comment-spacings
arguments: []
- name: confusing-naming
- name: confusing-results
- name: constant-logical-expr
- name: context-as-argument
- name: context-keys-type
- name: cyclomatic
arguments: [10]
- name: datarace
- name: deep-exit
- name: defer
- name: dot-imports
- name: duplicated-imports
- name: early-return
- name: empty-block
- name: empty-lines
- name: error-naming
- name: error-return
- name: error-strings
- name: errorf
- name: exported
arguments:
- "checkPrivateReceivers"
- "sayRepetitiveInsteadOfStutters"
- name: flag-parameter
- name: function-result-limit
arguments: [2]
- name: function-length
arguments: [50, 0]
- name: get-return
- name: identical-branches
- name: if-return
- name: increment-decrement
- name: indent-error-flow
- name: imports-blacklist
arguments:
- "crypto/md5"
- "crypto/sha1"
- name: import-shadowing
- name: line-length-limit
arguments: [120]
- name: max-public-structs
arguments: [5]
- name: time-equal
- name: time-naming
- name: var-naming
- name: var-declaration
- name: unconditional-recursion
- name: unexported-naming
- name: unexported-return
- name: unhandled-error
- name: unnecessary-stmt
- name: unreachable-code
- name: unused-parameter
- name: unused-receiver
- name: use-any
- name: useless-break
- name: waitgroup-by-value

issues:
exclude-use-default: false
13 changes: 13 additions & 0 deletions error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// error.go Copyright (c) 2023 z0ne.
// All Rights Reserved.
// Licensed under the Apache 2.0 License.
// See LICENSE the project root for license information.
//
// SPDX-License-Identifier: Apache-2.0

package mgx

import "errors"

// ErrTooManyAppliedMigrations is returned when more migrations are applied than defined
var ErrTooManyAppliedMigrations = errors.New("too many applied migrations")
11 changes: 10 additions & 1 deletion migration.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
// migration.go Copyright (c) 2023 z0ne.
// All Rights Reserved.
// Licensed under the Apache 2.0 License.
// See LICENSE the project root for license information.
//
// SPDX-License-Identifier: Apache-2.0

// Package mgx is a simple migration tool for pgx
package mgx

Expand All @@ -16,14 +23,16 @@ type Migration interface {
}

type migrationFuncWrapper struct {
name string
fn MigrationFunc
name string
}

// Run the migration
func (m *migrationFuncWrapper) Run(ctx context.Context, tx Commands) error {
return m.fn(ctx, tx)
}

// String returns the name of the migration
func (m *migrationFuncWrapper) String() string {
return m.name
}
Expand Down
50 changes: 32 additions & 18 deletions migrator.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
// migrator.go Copyright (c) 2023 z0ne.
// All Rights Reserved.
// Licensed under the Apache 2.0 License.
// See LICENSE the project root for license information.
//
// SPDX-License-Identifier: Apache-2.0

package mgx

import (
"context"
"errors"
"fmt"
"log"
"time"
Expand Down Expand Up @@ -82,32 +88,39 @@ func (m *Migrator) Migrate(ctx context.Context, db Conn) error {
}

if count > len(m.migrations) {
return errors.New("migrator: applied migration number on db cannot be greater than the defined migration list")
return ErrTooManyAppliedMigrations
}

m.logger.Log("Running missing migrations...", map[string]any{"missing": len(m.migrations) - count})

// plan migrations
for idx, migration := range m.migrations[count:] {
tx, err := db.Begin(ctx)
if err != nil {
return fmt.Errorf("migrator: error while starting transaction: %v", err)
err2 := m.applyMigration(ctx, db, migration, idx+count)
if err2 != nil {
return err2
}
}

insertVersion := fmt.Sprintf("INSERT INTO %s (id, version) VALUES ($1, $2)", m.tableName)
if err := migrate(ctx, tx, m.logger, insertVersion, migration, idx+count); err != nil {
if err := tx.Rollback(ctx); err != nil {
panic(fmt.Errorf("migrator: error while rolling back transaction: %v", err))
}
return fmt.Errorf("migrator: error while running migrations: %v", err)
}
return nil
}

err = tx.Commit(ctx)
if err != nil {
return fmt.Errorf("migrator: failed to commit transaction: %v", err)
func (m *Migrator) applyMigration(ctx context.Context, db Conn, migration Migration, version int) error {
tx, err := db.Begin(ctx)
if err != nil {
return fmt.Errorf("migrator: error while starting transaction: %w", err)
}

if errMigration := m.runMigration(ctx, tx, migration, version); errMigration != nil {
if errRollback := tx.Rollback(ctx); errRollback != nil {
panic(fmt.Errorf("migrator: error while rolling back transaction: %w", errRollback))
}
return fmt.Errorf("migrator: error while running migrations: %w", errMigration)
}

err = tx.Commit(ctx)
if err != nil {
return fmt.Errorf("migrator: failed to commit transaction: %w", err)
}
return nil
}

Expand Down Expand Up @@ -143,8 +156,8 @@ func (m *Migrator) countApplied(ctx context.Context, db Conn, tableName string)
return count, nil
}

func migrate(ctx context.Context, db pgx.Tx, logger Logger, insertVersion string, migration Migration, id int) (err error) {
logger.Log("applying migration", map[string]any{
func (m *Migrator) runMigration(ctx context.Context, db pgx.Tx, migration Migration, id int) (err error) {
m.logger.Log("applying migration", map[string]any{
"id": id,
"name": migration.String(),
})
Expand All @@ -154,12 +167,13 @@ func migrate(ctx context.Context, db pgx.Tx, logger Logger, insertVersion string
return fmt.Errorf("error executing golang migration %s: %w", migration.String(), err)
}

insertVersion := fmt.Sprintf("INSERT INTO %s (id, version) VALUES ($1, $2)", m.tableName)
if _, err = db.Exec(ctx, insertVersion, id, migration.String()); err != nil {
return fmt.Errorf("error updating migration versions: %w", err)
}
duration := time.Since(start)

logger.Log("applied migration", map[string]any{
m.logger.Log("applied migration", map[string]any{
"id": id,
"name": migration.String(),
"took": duration,
Expand Down
20 changes: 15 additions & 5 deletions migrator_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
// migrator_test.go Copyright (c) 2023 z0ne.
// All Rights Reserved.
// Licensed under the Apache 2.0 License.
// See LICENSE the project root for license information.
//
// SPDX-License-Identifier: Apache-2.0

package mgx_test

import (
"context"
_ "embed"
"errors"
"fmt"
"os"
"testing"

Expand All @@ -14,7 +19,10 @@ import (

var migrations = []mgx.Migration{
mgx.NewRawMigration("raw migration: single query, create table foo", "CREATE TABLE foo (id INT PRIMARY KEY)"),
mgx.NewRawMigration("raw migration: multi query, create table bar, alter table bar", "CREATE TABLE bar (id INT PRIMARY KEY); ALTER TABLE bar ADD COLUMN name VARCHAR(255)"),
mgx.NewRawMigration(
"raw migration: multi query, create table bar, alter table bar",
"CREATE TABLE bar (id INT PRIMARY KEY); ALTER TABLE bar ADD COLUMN name VARCHAR(255)",
),
mgx.NewMigration("fn migration", func(ctx context.Context, cmd mgx.Commands) error {
if _, err := cmd.Exec(ctx, "CREATE TABLE foobar (id INT PRIMARY KEY)"); err != nil {
return err
Expand All @@ -37,10 +45,12 @@ func (t *TestLogger) Log(_ string, _ map[string]any) {
}

func connectToDatabase(t *testing.T) *pgx.Conn {
t.Helper()

// create db connection
url := os.Getenv("POSTGRES")
if url == "" {
t.Fatal(errors.New("POSTGRES env variable is not set"))
t.Fatal("POSTGRES env variable is not set")
}

db, err := pgx.Connect(context.Background(), url)
Expand Down Expand Up @@ -144,7 +154,7 @@ func TestPending(t *testing.T) {

pending, err := migrator.Pending(context.Background(), db)
if err == nil && len(pending) != len(migrations) {
err = fmt.Errorf("there should be %d pending migrations, only %d found", len(migrations), len(pending))
t.Fatalf("there should be %d pending migrations, only %d found", len(migrations), len(pending))
}

if err != nil {
Expand Down
7 changes: 7 additions & 0 deletions pgx.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
// pgx.go Copyright (c) 2023 z0ne.
// All Rights Reserved.
// Licensed under the Apache 2.0 License.
// See LICENSE the project root for license information.
//
// SPDX-License-Identifier: Apache-2.0

package mgx

import (
Expand Down

0 comments on commit 8b5ee40

Please sign in to comment.