Skip to content

Commit b3a1c7e

Browse files
authored
Merge pull request #2 from etilite/dev
feat: init v0.1.0
2 parents bb6775d + 106179f commit b3a1c7e

File tree

17 files changed

+505
-1
lines changed

17 files changed

+505
-1
lines changed

.github/workflows/docker.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: docker push
2+
on:
3+
release:
4+
types:
5+
- created
6+
7+
jobs:
8+
docker:
9+
permissions:
10+
contents: read
11+
packages: write
12+
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Set up QEMU
16+
uses: docker/setup-qemu-action@v3
17+
18+
- name: Set up Docker Buildx
19+
uses: docker/setup-buildx-action@v3
20+
21+
- name: Docker meta
22+
id: meta
23+
uses: docker/metadata-action@v5
24+
with:
25+
# list of Docker images to use as base name for tags
26+
images: |
27+
etilite/qr-coder
28+
flavor: |
29+
latest=false
30+
tags: |
31+
type=raw,value=development,enable=${{ github.event_name != 'release' }}
32+
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
33+
type=semver,pattern={{version}}
34+
type=semver,pattern={{major}}.{{minor}}
35+
type=sha,enable=true,priority=100,prefix=,suffix=,format=short
36+
37+
- name: Login to DockerHub
38+
uses: docker/login-action@v3
39+
with:
40+
username: ${{ secrets.DOCKERHUB_USERNAME }}
41+
password: ${{ secrets.DOCKERHUB_TOKEN }}
42+
43+
- name: Build the Docker image and push
44+
uses: docker/build-push-action@v5
45+
with:
46+
file: ./build/Dockerfile
47+
platforms: linux/amd64,linux/arm64
48+
push: true
49+
tags: ${{ steps.meta.outputs.tags }}
50+
labels: ${{ steps.meta.outputs.labels }}
51+
build-args: |
52+
GIT_REF=${{ github.sha }}
53+
cache-from: type=gha
54+
cache-to: type=gha,mode=min
55+

.github/workflows/go.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: go build
2+
3+
on:
4+
push:
5+
branches: [ "master" ]
6+
pull_request:
7+
branches: [ "master" ]
8+
9+
jobs:
10+
11+
test:
12+
strategy:
13+
matrix:
14+
go-version: ['1.22.3', 'stable']
15+
os: [ ubuntu-latest, macos-13, windows-latest ]
16+
targetplatform: [ x86, x64 ]
17+
18+
runs-on: ${{ matrix.os }}
19+
20+
steps:
21+
22+
- name: Checkout code
23+
uses: actions/checkout@v4
24+
25+
- name: Set up Go ${{ matrix.go-version }}
26+
uses: actions/setup-go@v5
27+
with:
28+
go-version: ${{ matrix.go-version }}
29+
cache: false
30+
31+
- name: Build
32+
run: go build -v ./...
33+
34+
- name: Lint
35+
uses: golangci/[email protected]
36+
with:
37+
version: latest
38+
args: --timeout 5m
39+
skip-cache: true
40+
41+
- name: Test
42+
run: go test -race -v -timeout 30m ./... -coverprofile ./coverage.txt
43+
44+
- name: Codecov
45+
uses: codecov/codecov-action@v4
46+
env:
47+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
48+
with:
49+
files: ./coverage.txt
50+
slug: etilite/qr-coder

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/.idea

Makefile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
.PHONY: up down dev-up dev-down run test test-race clean
2+
3+
up:
4+
docker-compose --file ./build/docker-compose.yml up -d --remove-orphans
5+
6+
down:
7+
docker-compose --file ./build/docker-compose.yml down
8+
9+
dev-up:
10+
docker-compose --file ./build/docker-compose.yml up -d --build --remove-orphans
11+
12+
dev-down:
13+
docker-compose --file ./build/docker-compose.yml down --rmi all -v
14+
15+
run:
16+
CGO_ENABLED=0 go build -ldflags='-w -s' -o app ./cmd/qr-coder && HTTP_ADDR=:8080 ./app
17+
18+
test:
19+
go test -v -shuffle=on -count=2 -short -cover ./...
20+
21+
test-race:
22+
go test -race ./...
23+
24+
clean:
25+
rm app

README.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,26 @@
11
# qr-coder
2-
Microservice to generate qr-code
2+
Microservice to generate QR-codes in png format.
3+
Text content is encoded in UTF-8.
4+
5+
## Usage
6+
### Build project
7+
### Get docker Image
8+
You can use pre-built Docker images to run `qr-coder`
9+
```
10+
docker run -it --rm -d -p 8080:8080 --name qr-coder \
11+
-e HTTP_ADDR=:8080 \
12+
etilite/qr-coder:latest
13+
```
14+
15+
#### request
16+
`POST http://localhost:8080/generate`
17+
```json
18+
{
19+
"size": 256,
20+
"content": "https://github.com/etilite/qr-coder"
21+
}
22+
```
23+
#### response
24+
![response](https://github.com/etilite/qr-coder/assets/39223859/bd1c0946-905f-4244-9027-279e795bbdb3)
25+
26+
png image

build/Dockerfile

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
ARG GO_VERSION=1.22.3
2+
ARG DISTROLESS_IMAGE=gcr.io/distroless/static:nonroot
3+
############################
4+
# STEP 1 build executable binary
5+
############################
6+
FROM golang:${GO_VERSION} as builder
7+
8+
# Ensure ca-certficates are up to date
9+
RUN update-ca-certificates
10+
11+
WORKDIR /app/
12+
13+
# use modules
14+
COPY go.mod go.sum ./
15+
16+
ENV GO111MODULE=on
17+
RUN go mod download && go mod verify
18+
19+
COPY . .
20+
21+
# Build the static binary
22+
RUN CGO_ENABLED=0 go build \
23+
-ldflags='-w -s -extldflags "-static"' -a \
24+
-o app ./cmd/qr-coder
25+
26+
############################
27+
# STEP 2 build a small image
28+
############################
29+
FROM ${DISTROLESS_IMAGE}
30+
31+
COPY --from=builder --chown=nonroot:nonroot /app/app /app
32+
33+
ENTRYPOINT ["/app"]

build/docker-compose.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
version: '3.8'
2+
3+
services:
4+
qr-coder:
5+
image: etilite/qr-coder:latest
6+
build:
7+
context: ./../
8+
dockerfile: ./build/Dockerfile
9+
container_name: qr-coder
10+
ports:
11+
- "8080:8080"
12+
environment:
13+
- HTTP_ADDR=:8080

cmd/qr-coder/main.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package main
2+
3+
import (
4+
"log/slog"
5+
"os"
6+
"os/signal"
7+
"syscall"
8+
"time"
9+
10+
"github.com/etilite/qr-coder/internal/app"
11+
httpserver "github.com/etilite/qr-coder/internal/delivery/http"
12+
)
13+
14+
const (
15+
shutdownTime time.Duration = 10 * time.Second
16+
)
17+
18+
func main() {
19+
cfg := app.NewConfigFromEnv()
20+
21+
a := app.New(cfg)
22+
23+
server := httpserver.NewServer(cfg.HTTPAddr)
24+
25+
if err := a.Run(server); err != nil {
26+
slog.Error("unable to start app", "error", err)
27+
panic(err)
28+
}
29+
30+
shutdown := make(chan bool)
31+
gracefulStop(shutdown)
32+
<-shutdown
33+
slog.Info("signal caught, shutting down")
34+
35+
go aggressiveStop()
36+
37+
if err := a.Stop(); err != nil {
38+
slog.Error("unable to stop app", "error", err)
39+
panic(err)
40+
}
41+
}
42+
43+
func gracefulStop(shutdown chan<- bool) {
44+
c := make(chan os.Signal)
45+
signal.Notify(c,
46+
syscall.SIGHUP,
47+
syscall.SIGINT,
48+
syscall.SIGTERM,
49+
syscall.SIGQUIT)
50+
51+
go func() {
52+
<-c
53+
shutdown <- true
54+
}()
55+
}
56+
57+
func aggressiveStop() {
58+
ticker := time.NewTicker(shutdownTime)
59+
<-ticker.C
60+
61+
slog.Warn("application is aggressive stopped")
62+
os.Exit(0)
63+
}

go.mod

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module github.com/etilite/qr-coder
2+
3+
go 1.22
4+
5+
require (
6+
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
7+
github.com/stretchr/testify v1.9.0
8+
)
9+
10+
require (
11+
github.com/davecgh/go-spew v1.1.1 // indirect
12+
github.com/pmezard/go-difflib v1.0.0 // indirect
13+
gopkg.in/yaml.v3 v3.0.1 // indirect
14+
)

go.sum

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
5+
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
6+
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
7+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
8+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
9+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
10+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
11+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
12+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)