Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
Borna Rajković | b2646e5aa1 | |
Borna Rajković | b4288b2abb |
35
README.md
35
README.md
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
Simple api used for tracking holidays
|
Simple api used for tracking holidays
|
||||||
|
|
||||||
To checkout application open [https://holiday.bbr-dev.info](https://holiday.bbr-dev.info)
|
To check out application, open [https://holiday.bbr-dev.info](https://holiday.bbr-dev.info)
|
||||||
|
|
||||||
## Endpoints
|
## Endpoints
|
||||||
|
|
||||||
|
@ -28,25 +28,25 @@ That endpoint accepts a list of required and optional parameters
|
||||||
- if defined year and rangeStart|rangeEnd parameters are ignored
|
- if defined year and rangeStart|rangeEnd parameters are ignored
|
||||||
|
|
||||||
|
|
||||||
`rangeStart|rangeEnd`
|
`range_start|range_end`
|
||||||
- returns holidays in given range with both ends being inclusive
|
- returns holidays in given range with both ends being inclusive
|
||||||
- if either limit isn't defined it is assumed to be up to or all from given limit (if rangeStart isn't defined all holidays before rangeEnd are returned and vice-verse)
|
- if either limit isn't defined it is assumed to be up to or all from given limit (if rangeStart isn't defined all holidays before rangeEnd are returned and vice-verse)
|
||||||
- dates must be formatted in ISO 8601 format [more info here](https://www.iso.org/iso-8601-date-and-time-format.html)
|
- dates must be formatted in ISO 8601 format [more info here](https://www.iso.org/iso-8601-date-and-time-format.html)
|
||||||
- eg. `rangeStart=2021-12-25&rangeEnd=2023-01-23`, `rangeStart=2023-01-20`
|
- eg. `range_start=2021-12-25&range_end=2023-01-23`, `range_start=2023-01-20`
|
||||||
- if defined year parameter is ignored
|
- if defined year parameter is ignored
|
||||||
|
|
||||||
`stateHoliday`
|
`state_holiday`
|
||||||
- if set true only holidays that are tagged as state holidays are returned, similar for if set false, if not set all holidays are returned
|
- if set true only holidays that are tagged as state holidays are returned, similar for if set false, if not set all holidays are returned
|
||||||
- eg. `stateHoliday=true`, `stateHoliday=false`
|
- eg. `state_holiday=true`, `state_holiday=false`
|
||||||
|
|
||||||
`religiousHoliday`
|
`religious_holiday`
|
||||||
- if set true only holidays that are tagged as religious holidays are returned, similar for if set false, if not set all holidays are returned
|
- if set true only holidays that are tagged as religious holidays are returned, similar for if set false, if not set all holidays are returned
|
||||||
- eg. `religiousHoliday=true`, `religiousHoliday=false`
|
- eg. `religious_holiday=true`, `religious_holiday=false`
|
||||||
|
|
||||||
#### Paging
|
#### Paging
|
||||||
`pageSize`
|
`page_size`
|
||||||
- returns at most pageSize number of holidays
|
- returns at most pageSize number of holidays
|
||||||
- eg. `pageSize=20`
|
- eg. `page_size=20`
|
||||||
- only applied if page is defined as well, by default set to 20
|
- only applied if page is defined as well, by default set to 20
|
||||||
|
|
||||||
`page`
|
`page`
|
||||||
|
@ -68,7 +68,7 @@ By default, responses are returned as a json array
|
||||||
},...]
|
},...]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
eg.
|
e.g.
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
"holidays": [{
|
"holidays": [{
|
||||||
|
@ -99,4 +99,19 @@ CSV Response
|
||||||
```
|
```
|
||||||
id,date,name,description,is_state_holiday,is_religious_holiday
|
id,date,name,description,is_state_holiday,is_religious_holiday
|
||||||
74a2a769-abf2-45d4-bdc4-442bbcc89138,2023-12-25,Christmas,TBD,true,true
|
74a2a769-abf2-45d4-bdc4-442bbcc89138,2023-12-25,Christmas,TBD,true,true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Development
|
||||||
|
|
||||||
|
To start server few environment variables need to be set up. This can be done by creating `.env` file with following content
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PSQL_HOST=localhost
|
||||||
|
PSQL_PORT=5432
|
||||||
|
PSQL_USER=holiday
|
||||||
|
PSQL_PASSWORD=holidayPassword
|
||||||
|
PSQL_DB=holiday
|
||||||
|
|
||||||
|
PROFILE=dev,basic-auth
|
||||||
|
AUTH_KEY=holiday:holidayPassword
|
||||||
```
|
```
|
|
@ -1,11 +1,10 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"holiday-api/domain/holiday"
|
"holiday-api/domain/holiday"
|
||||||
"log"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
@ -339,7 +338,7 @@ func render(c *gin.Context, status int, response any, contentType *string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Abort(c *gin.Context, err error, statusCode int, message string) {
|
func Abort(c *gin.Context, err error, statusCode int, message string) {
|
||||||
log.Output(1, fmt.Sprintf("error | %s | err: %v", message, errorMessage(err)))
|
slog.Error(message, slog.String("err", errorMessage(err)))
|
||||||
c.AbortWithError(statusCode, err)
|
c.AbortWithError(statusCode, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,10 +44,10 @@ window.addEventListener('load', () => {
|
||||||
query['country'] = country.value;
|
query['country'] = country.value;
|
||||||
query['contentType'] = contentType.value;
|
query['contentType'] = contentType.value;
|
||||||
if(stateHoliday.value === 'true' || stateHoliday.value === 'false') {
|
if(stateHoliday.value === 'true' || stateHoliday.value === 'false') {
|
||||||
query['stateHoliday'] = parseBoolean(stateHoliday.value);
|
query['state_holiday'] = parseBoolean(stateHoliday.value);
|
||||||
}
|
}
|
||||||
if(religiousHoliday.value === 'true' || religiousHoliday.value === 'false') {
|
if(religiousHoliday.value === 'true' || religiousHoliday.value === 'false') {
|
||||||
query['religiousHoliday'] = parseBoolean(religiousHoliday.value);
|
query['religious_holiday'] = parseBoolean(religiousHoliday.value);
|
||||||
}
|
}
|
||||||
console.log(dateSelector.value, dStartRange.value, dEndRange.value);
|
console.log(dateSelector.value, dStartRange.value, dEndRange.value);
|
||||||
switch(dateSelector.value) {
|
switch(dateSelector.value) {
|
||||||
|
@ -61,10 +61,10 @@ window.addEventListener('load', () => {
|
||||||
break;
|
break;
|
||||||
case 'range':
|
case 'range':
|
||||||
if(dStartRange.value) {
|
if(dStartRange.value) {
|
||||||
query['startRange'] = dStartRange.value;
|
query['range_start'] = dStartRange.value;
|
||||||
}
|
}
|
||||||
if(dEndRange.value) {
|
if(dEndRange.value) {
|
||||||
query['endRange'] = dEndRange.value;
|
query['range_end'] = dEndRange.value;
|
||||||
}
|
}
|
||||||
case 'all':
|
case 'all':
|
||||||
default:
|
default:
|
||||||
|
@ -78,10 +78,10 @@ window.addEventListener('load', () => {
|
||||||
query['country'] = country.value;
|
query['country'] = country.value;
|
||||||
query['type'] = contentType.value;
|
query['type'] = contentType.value;
|
||||||
if(stateHoliday.value === 'true' || stateHoliday.value === 'false') {
|
if(stateHoliday.value === 'true' || stateHoliday.value === 'false') {
|
||||||
query['stateHoliday'] = parseBoolean(stateHoliday.value);
|
query['state_holiday'] = parseBoolean(stateHoliday.value);
|
||||||
}
|
}
|
||||||
if(religiousHoliday.value === 'true' || religiousHoliday.value === 'false') {
|
if(religiousHoliday.value === 'true' || religiousHoliday.value === 'false') {
|
||||||
query['religiousHoliday'] = parseBoolean(religiousHoliday.value);
|
query['religious_holiday'] = parseBoolean(religiousHoliday.value);
|
||||||
}
|
}
|
||||||
console.log(dateSelector.value, dStartRange.value, dEndRange.value);
|
console.log(dateSelector.value, dStartRange.value, dEndRange.value);
|
||||||
switch(dateSelector.value) {
|
switch(dateSelector.value) {
|
||||||
|
@ -95,10 +95,10 @@ window.addEventListener('load', () => {
|
||||||
break;
|
break;
|
||||||
case 'range':
|
case 'range':
|
||||||
if(dStartRange.value) {
|
if(dStartRange.value) {
|
||||||
query['startRange'] = dStartRange.value;
|
query['range_start'] = dStartRange.value;
|
||||||
}
|
}
|
||||||
if(dEndRange.value) {
|
if(dEndRange.value) {
|
||||||
query['endRange'] = dEndRange.value;
|
query['range_end'] = dEndRange.value;
|
||||||
}
|
}
|
||||||
case 'all':
|
case 'all':
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
### v1.0.1
|
||||||
|
* Updated api documentation page
|
||||||
|
* Updated README.md
|
12
db.go
12
db.go
|
@ -16,12 +16,22 @@ func envMustExist(env string) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func envOrDefault(env string, defaultValue string) string {
|
||||||
|
if value, exists := os.LookupEnv(env); exists {
|
||||||
|
return value
|
||||||
|
} else {
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func connectToDb() (*sqlx.DB, error) {
|
func connectToDb() (*sqlx.DB, error) {
|
||||||
host := envMustExist("PSQL_HOST")
|
host := envMustExist("PSQL_HOST")
|
||||||
port := envMustExist("PSQL_PORT")
|
port := envMustExist("PSQL_PORT")
|
||||||
user := envMustExist("PSQL_USER")
|
user := envMustExist("PSQL_USER")
|
||||||
password := envMustExist("PSQL_PASSWORD")
|
password := envMustExist("PSQL_PASSWORD")
|
||||||
dbname := envMustExist("PSQL_DB")
|
dbname := envMustExist("PSQL_DB")
|
||||||
|
sslMode := envOrDefault("PSQL_SSLMODE", "disable")
|
||||||
|
schema := envOrDefault("PSQL_SCHEMA", "public")
|
||||||
|
|
||||||
return db.ConnectToDbNamed(host, port, user, password, dbname)
|
return db.ConnectToDbNamed(host, port, user, password, dbname, sslMode, schema)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,9 @@ var DevMigrations embed.FS
|
||||||
//go:embed prod/*.sql
|
//go:embed prod/*.sql
|
||||||
var ProdMigrations embed.FS
|
var ProdMigrations embed.FS
|
||||||
|
|
||||||
func ConnectToDbNamed(host string, port string, user string, password string, dbname string) (*sqlx.DB, error) {
|
func ConnectToDbNamed(host string, port string, user string, password string, dbname string, sslMode string, schema string) (*sqlx.DB, error) {
|
||||||
psqlInfo := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable",
|
psqlInfo := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=%s search_path=%s",
|
||||||
host, port, user, password, dbname)
|
host, port, user, password, dbname, sslMode, schema)
|
||||||
|
|
||||||
db, err := sqlx.Open("postgres", psqlInfo)
|
db, err := sqlx.Open("postgres", psqlInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -1,10 +1,10 @@
|
||||||
module holiday-api
|
module holiday-api
|
||||||
|
|
||||||
go 1.19
|
go 1.22
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gin-gonic/gin v1.9.1
|
github.com/gin-gonic/gin v1.9.1
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/jmoiron/sqlx v1.3.5
|
github.com/jmoiron/sqlx v1.3.5
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
github.com/lib/pq v1.10.9
|
github.com/lib/pq v1.10.9
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -34,6 +34,8 @@ github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
|
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
|
||||||
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
|
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
|
||||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
|
|
56
main.go
56
main.go
|
@ -1,36 +1,51 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
"holiday-api/api"
|
"holiday-api/api"
|
||||||
"holiday-api/db"
|
"holiday-api/db"
|
||||||
"holiday-api/migration"
|
"holiday-api/migration"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime/debug"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
godotenv.Load()
|
godotenv.Load()
|
||||||
log.SetPrefix("")
|
if !hasProfile("dev") {
|
||||||
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
|
}
|
||||||
|
if value := os.Getenv("LOG_FORMAT"); value == "json" {
|
||||||
|
slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{AddSource: true})))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
db, err := connectToDb()
|
commit, time := buildInfo()
|
||||||
|
slog.Info("build info", slog.String("commit", commit), slog.String("time", time))
|
||||||
|
|
||||||
|
client, err := connectToDb()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("couldn't connect to db: %v", err)
|
slog.Error("couldn't connect to client", slog.String("err", err.Error()))
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if err := migration.InitializeMigrations(db, migrationFolder()); err != nil {
|
if err := migration.InitializeMigrations(client, migrationFolder()); err != nil {
|
||||||
log.Fatalf("couldn't execute migrations: %v", err)
|
slog.Error("couldn't finish migration", slog.String("err", err.Error()))
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
server := api.SetupServer(db)
|
server := api.SetupServer(client)
|
||||||
|
|
||||||
log.Fatal(http.ListenAndServe(":5281", server))
|
port := ":" + getOrDefault("SERVER_PORT", "5281")
|
||||||
|
slog.Info("app is ready", slog.String("port", port))
|
||||||
|
if err := http.ListenAndServe(port, server); err != nil {
|
||||||
|
slog.Error("Couldn't start server!\n", slog.Any("err", err.Error()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasProfile(value string) bool {
|
func hasProfile(value string) bool {
|
||||||
|
@ -49,3 +64,26 @@ func migrationFolder() fs.FS {
|
||||||
}
|
}
|
||||||
return db.ProdMigrations
|
return db.ProdMigrations
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildInfo() (string, string) {
|
||||||
|
revision := ""
|
||||||
|
time := ""
|
||||||
|
|
||||||
|
if info, ok := debug.ReadBuildInfo(); ok {
|
||||||
|
for _, setting := range info.Settings {
|
||||||
|
if setting.Key == "vcs.revision" {
|
||||||
|
revision = setting.Value
|
||||||
|
} else if setting.Key == "vcs.time" {
|
||||||
|
time = setting.Value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return revision, time
|
||||||
|
}
|
||||||
|
|
||||||
|
func getOrDefault(env string, defaultValue string) string {
|
||||||
|
if value, present := os.LookupEnv(env); present {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
|
20
makefile
20
makefile
|
@ -1,19 +1,11 @@
|
||||||
# scripts for building app
|
# scripts for building app
|
||||||
# requires go 1.19+ and git installed
|
# requires go 1.22+ and git installed
|
||||||
|
|
||||||
VERSION := 1.0.0
|
VERSION := $(shell git describe --tags --always)
|
||||||
|
|
||||||
serve:
|
|
||||||
go run ./...
|
|
||||||
|
|
||||||
setup:
|
|
||||||
go get
|
|
||||||
|
|
||||||
docker-dev:
|
docker-dev:
|
||||||
docker image build -t registry.bbr-dev.info/holiday-api/backend:$(VERSION)-dev .
|
docker image build -t registry.bbr-dev.info/holiday-api/backend/dev:latest .
|
||||||
docker tag registry.bbr-dev.info/holiday-api/backend:$(VERSION)-dev registry.bbr-dev.info/holiday-api/backend:latest-dev
|
docker image push registry.bbr-dev.info/holiday-api/backend/dev:latest
|
||||||
docker image push registry.bbr-dev.info/holiday-api/backend:$(VERSION)-dev
|
|
||||||
docker image push registry.bbr-dev.info/holiday-api/backend:latest-dev
|
|
||||||
|
|
||||||
|
|
||||||
docker-prod:
|
docker-prod:
|
||||||
|
@ -22,10 +14,6 @@ docker-prod:
|
||||||
docker image push registry.bbr-dev.info/holiday-api/backend:$(VERSION)
|
docker image push registry.bbr-dev.info/holiday-api/backend:$(VERSION)
|
||||||
docker image push registry.bbr-dev.info/holiday-api/backend:latest
|
docker image push registry.bbr-dev.info/holiday-api/backend:latest
|
||||||
|
|
||||||
release:
|
|
||||||
git tag $(VERSION)
|
|
||||||
git push origin $(VERSION)
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
go test ./...
|
go test ./...
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,11 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log/slog"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -92,7 +93,8 @@ func validateMigrations(db *sqlx.DB, migrations map[string]Migration, migrationF
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeMigration(db *sqlx.DB, name string, script string) error {
|
func executeMigration(db *sqlx.DB, name string, script string) error {
|
||||||
log.Printf("[INFO] script='%s' | migrations - executing", name)
|
logger := slog.Default().With(slog.String("script", name))
|
||||||
|
logger.Info("migrations - executing")
|
||||||
tx := db.MustBeginTx(context.Background(), nil)
|
tx := db.MustBeginTx(context.Background(), nil)
|
||||||
var err error = nil
|
var err error = nil
|
||||||
if _, e := tx.Exec(script); e != nil {
|
if _, e := tx.Exec(script); e != nil {
|
||||||
|
@ -102,10 +104,10 @@ func executeMigration(db *sqlx.DB, name string, script string) error {
|
||||||
err = e
|
err = e
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[ERROR] script='%s' | migrations - failed executing", name)
|
logger.Error("migrations - failed executing", slog.String("err", err.Error()))
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[INFO] script='%s' | migrations - succesfully executed", name)
|
logger.Info("migrations - successfully executed")
|
||||||
tx.Commit()
|
tx.Commit()
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
@ -119,9 +121,9 @@ func validateMigration(name string, migration Migration, script string) error {
|
||||||
calculatedHash := hash(script)
|
calculatedHash := hash(script)
|
||||||
|
|
||||||
if calculatedHash != migration.Hash {
|
if calculatedHash != migration.Hash {
|
||||||
err := fmt.Sprintf("migrations - mismatch in hash for %s (expected '%s', calculated '%s')", name, migration.Hash, calculatedHash)
|
err := errors.New(fmt.Sprintf("migrations - mismatch in hash for %s (expected '%s', calculated '%s')", name, migration.Hash, calculatedHash))
|
||||||
log.Printf("[ERROR] script='%s' err='%s' | migrations - failed executing", script, err)
|
slog.Error("migrations - failed validation", slog.String("script", name), slog.String("err", err.Error()))
|
||||||
return fmt.Errorf("migrations - mismatch in hashes for %s", name)
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue