chore(): docker-compose

This commit is contained in:
2025-08-27 21:29:52 +02:00
parent 75dfeaffd2
commit 5552258f20
9 changed files with 89 additions and 62 deletions

22
Dockerfile Normal file
View File

@@ -0,0 +1,22 @@
FROM golang:1.24 as build
WORKDIR /app
# Copy module files and download dependencies
COPY go.mod go.sum ./
RUN go mod download
# Copy the rest of the application source and build
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /invoiceapi cmd/invoiceapi/main.go
EXPOSE 8080
FROM alpine:3
# the test program:
COPY --from=build /invoiceapi /invoiceapi
# the tls certificates:
# NB: this pulls directly from the upstream image, which already has ca-certificates:
CMD [ "/invoiceapi" ]

View File

@@ -2,28 +2,24 @@ docker run --rm -p 3030:3000 gotenberg/gotenberg:8
## Configuration ## Configuration
This application is configured using a `config.json` file in the root of the project. You can use the `config.json.example` file as a starting point. This application can be configured using a `config.json` file in the root of the project, or by using environment variables. Values set in environment variables will override the values from the `config.json` file.
```json You can use the `config.example.json` file as a starting point for your `config.json`.
{
"email": { ### Environment Variables
"smtp": {
"host": "smtp.example.com", The following environment variables can be used for configuration:
"port": 587,
"username": "user", | Variable | Description |
"password": "password" | --------------------- | --------------------------------------------- |
}, | `PDF_HOSTNAME` | The hostname of the PDF generator (Gotenberg) |
"from": "from@example.com" | `GITEA_URL` | The URL of your Gitea instance |
}, | `GITEA_TOKEN` | Your Gitea API token |
"pdf": { | `EMAIL_FROM` | The "From" address for sending emails |
"hostname": "http://localhost:3030" | `EMAIL_SMTP_HOST` | The SMTP server host |
}, | `EMAIL_SMTP_PORT` | The SMTP server port |
"gitea": { | `EMAIL_SMTP_USER` | The username for SMTP authentication |
"url": "https://gitea.example.com", | `EMAIL_SMTP_PASSWORD` | The password for SMTP authentication |
"token": "your-gitea-token"
}
}
```
## API Endpoints ## API Endpoints

22
docker-compose.yml Normal file
View File

@@ -0,0 +1,22 @@
services:
invoiceapi:
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080"
depends_on:
- gotenberg
environment:
- PDF_HOSTNAME=http://gotenberg:3000
volumes:
- ./config.json:/config.json
develop:
watch:
- action: rebuild
path: .
ignore:
- .git
gotenberg:
image: gotenberg/gotenberg:8
restart: unless-stopped

1
go.mod
View File

@@ -4,6 +4,7 @@ go 1.24.5
require ( require (
code.gitea.io/sdk/gitea v0.21.0 code.gitea.io/sdk/gitea v0.21.0
github.com/caarlos0/env/v10 v10.0.0
github.com/gomarkdown/markdown v0.0.0-20250810172220-2e2c11897d1a github.com/gomarkdown/markdown v0.0.0-20250810172220-2e2c11897d1a
github.com/jedib0t/go-pretty/v6 v6.6.8 github.com/jedib0t/go-pretty/v6 v6.6.8
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible

2
go.sum
View File

@@ -2,6 +2,8 @@ code.gitea.io/sdk/gitea v0.21.0 h1:69n6oz6kEVHRo1+APQQyizkhrZrLsTLXey9142pfkD4=
code.gitea.io/sdk/gitea v0.21.0/go.mod h1:tnBjVhuKJCn8ibdyyhvUyxrR1Ca2KHEoTWoukNhXQPA= code.gitea.io/sdk/gitea v0.21.0/go.mod h1:tnBjVhuKJCn8ibdyyhvUyxrR1Ca2KHEoTWoukNhXQPA=
github.com/42wim/httpsig v1.2.3 h1:xb0YyWhkYj57SPtfSttIobJUPJZB9as1nsfo7KWVcEs= github.com/42wim/httpsig v1.2.3 h1:xb0YyWhkYj57SPtfSttIobJUPJZB9as1nsfo7KWVcEs=
github.com/42wim/httpsig v1.2.3/go.mod h1:nZq9OlYKDrUBhptd77IHx4/sZZD+IxTBADvAPI9G/EM= github.com/42wim/httpsig v1.2.3/go.mod h1:nZq9OlYKDrUBhptd77IHx4/sZZD+IxTBADvAPI9G/EM=
github.com/caarlos0/env/v10 v10.0.0 h1:yIHUBZGsyqCnpTkbjk8asUlx6RFhhEs+h7TOBdgdzXA=
github.com/caarlos0/env/v10 v10.0.0/go.mod h1:ZfulV76NvVPw3tm591U4SwL3Xx9ldzBP9aGxzeN7G18=
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/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0= github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=

View File

@@ -22,7 +22,7 @@ func New(log *slog.Logger, invoice invoicer, mail mailer) *Service {
} }
type invoicer interface { type invoicer interface {
Generate(creditor, deptor model.Entity, mindur time.Duration, rate float64, repos []invoice.Repo) (document io.ReadCloser, report report.Report, err error) Generate(creditor, deptor model.Entity, mindur time.Duration, rate float64, repos []invoice.Repo) (document io.ReadCloser, report *report.Report, err error)
} }
type mailer interface { type mailer interface {

View File

@@ -5,37 +5,43 @@ import (
"os" "os"
"git.schreifuchs.ch/lou-taylor/accounting/internal/email" "git.schreifuchs.ch/lou-taylor/accounting/internal/email"
"github.com/caarlos0/env/v10"
) )
// PDF holds the configuration for the PDF generator. // PDF holds the configuration for the PDF generator.
type PDF struct { type PDF struct {
Hostname string `json:"hostname"` Hostname string `json:"hostname" env:"HOSTNAME"`
} }
// Gitea holds the configuration for the Gitea client. // Gitea holds the configuration for the Gitea client.
type Gitea struct { type Gitea struct {
URL string `json:"url"` URL string `json:"url" env:"URL"`
Token string `json:"token"` Token string `json:"token" env:"TOKEN"`
} }
// Config holds the configuration for the entire application. // Config holds the configuration for the entire application.
type Config struct { type Config struct {
Email email.Config `json:"email"` Email email.Config `json:"email" envPrefix:"EMAIL_"`
PDF PDF `json:"pdf"` PDF PDF `json:"pdf" envPrefix:"PDF_"`
Gitea Gitea `json:"gitea"` Gitea Gitea `json:"gitea" envPrefix:"GITEA_"`
} }
// Load loads the configuration from a JSON file. // Load loads the configuration from a JSON file and environment variables.
func Load(path string) (*Config, error) { func Load(path string) (*Config, error) {
cfg := &Config{}
file, err := os.Open(path) file, err := os.Open(path)
if err != nil { if err == nil {
defer file.Close()
decoder := json.NewDecoder(file)
if err := decoder.Decode(cfg); err != nil {
return nil, err
}
} else if !os.IsNotExist(err) {
return nil, err return nil, err
} }
defer file.Close()
cfg := &Config{} if err := env.Parse(cfg); err != nil {
decoder := json.NewDecoder(file)
if err := decoder.Decode(cfg); err != nil {
return nil, err return nil, err
} }

View File

@@ -8,15 +8,15 @@ import (
) )
type Config struct { type Config struct {
SMTP SMTPConfig SMTP SMTPConfig `envPrefix:"SMTP_"`
From string From string `env:"FROM"`
} }
type SMTPConfig struct { type SMTPConfig struct {
Host string Host string `env:"HOST"`
Port string Port string `env:"PORT"`
User string User string `env:"USER"`
Password string Password string `env:"PASSWORD"`
} }
type Service struct { type Service struct {

22
main.go
View File

@@ -1,22 +0,0 @@
package main
import (
"git.schreifuchs.ch/lou-taylor/accounting/internal/api"
)
func main() {
// var cfg invoice.Config
// file, err := os.Open("config.json")
// if err != nil {
// panic(err)
// }
// defer file.Close()
// decoder := json.NewDecoder(file)
// err = decoder.Decode(&cfg)
// if err != nil {
// panic(err)
// }
//
// invoice.Generate(cfg)
api.Start(":8080")
}