Compare commits
6 commits
Author | SHA1 | Date | |
---|---|---|---|
7a3780f3e1 | |||
34ca6f0f7e | |||
1629523d84 | |||
be890e2e75 | |||
4a7b2d84c8 | |||
f64d5c2420 |
13 changed files with 94 additions and 9 deletions
|
@ -6,6 +6,7 @@ stages:
|
||||||
include:
|
include:
|
||||||
- local: .gitlab/_common.gitlab-ci.yml
|
- local: .gitlab/_common.gitlab-ci.yml
|
||||||
- local: .gitlab/_rules.gitlab-ci.yml
|
- local: .gitlab/_rules.gitlab-ci.yml
|
||||||
|
- local: /.gitlab/test.gitlab-ci.yml
|
||||||
- local: /.gitlab/build.gitlab-ci.yml
|
- local: /.gitlab/build.gitlab-ci.yml
|
||||||
- local: /.gitlab/deploy.gitlab-ci.yml
|
- local: /.gitlab/deploy.gitlab-ci.yml
|
||||||
- template: Jobs/Secret-Detection.gitlab-ci.yml
|
- template: Jobs/Secret-Detection.gitlab-ci.yml
|
||||||
|
|
|
@ -12,3 +12,13 @@ image: docker:$DOCKER_VERSION-git
|
||||||
.login_registry:
|
.login_registry:
|
||||||
before_script:
|
before_script:
|
||||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||||
|
|
||||||
|
.go-cache:
|
||||||
|
variables:
|
||||||
|
GOPATH: $CI_PROJECT_DIR/.go
|
||||||
|
before_script:
|
||||||
|
- mkdir -p .go
|
||||||
|
- export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
|
||||||
|
cache:
|
||||||
|
paths:
|
||||||
|
- .go/pkg/mod/
|
||||||
|
|
|
@ -15,7 +15,7 @@ build_release:
|
||||||
--build-arg GOLANG_VERSION=$GOLANG_VERSION
|
--build-arg GOLANG_VERSION=$GOLANG_VERSION
|
||||||
--build-arg NODE_VERSION=$NODE_VERSION
|
--build-arg NODE_VERSION=$NODE_VERSION
|
||||||
--build-arg ALPINE_VERSION=$ALPINE_VERSION
|
--build-arg ALPINE_VERSION=$ALPINE_VERSION
|
||||||
--build-arg APP_VERSION=$CI_COMMIT_TAG
|
--build-arg VERSION=$CI_COMMIT_TAG
|
||||||
--build-arg BUILD_TIME=$CI_JOB_STARTED_AT
|
--build-arg BUILD_TIME=$CI_JOB_STARTED_AT
|
||||||
--tag $CURRENT_IMAGE
|
--tag $CURRENT_IMAGE
|
||||||
--tag $LATEST_IMAGE
|
--tag $LATEST_IMAGE
|
||||||
|
|
17
.gitlab/test.gitlab-ci.yml
Normal file
17
.gitlab/test.gitlab-ci.yml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
unit_tests:
|
||||||
|
rules: !reference [.rules:default, rules]
|
||||||
|
stage: test
|
||||||
|
image: golang:$GOLANG_VERSION-alpine
|
||||||
|
extends:
|
||||||
|
- .go-cache
|
||||||
|
script:
|
||||||
|
- ./scripts/swagger.sh install
|
||||||
|
- ./scripts/swagger.sh init
|
||||||
|
- go install gotest.tools/gotestsum@latest
|
||||||
|
- gotestsum --junitfile report.xml --format testname -- ./... -coverprofile=profile.cov
|
||||||
|
- go tool cover -func profile.cov
|
||||||
|
coverage: '/\(statements\)(?:\s+)?(\d+(?:\.\d+)?%)/'
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
reports:
|
||||||
|
junit: report.xml
|
|
@ -115,6 +115,7 @@ services:
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=1000
|
||||||
- PGID=1000
|
- PGID=1000
|
||||||
|
- SWAGGER_HOST=https://cafe.test
|
||||||
labels:
|
labels:
|
||||||
- 'traefik.enable=true'
|
- 'traefik.enable=true'
|
||||||
- 'traefik.http.routers.backend.rule=Host(`cafe.test`) && PathPrefix(`/api`)'
|
- 'traefik.http.routers.backend.rule=Host(`cafe.test`) && PathPrefix(`/api`)'
|
||||||
|
|
|
@ -39,9 +39,8 @@ WORKDIR /app
|
||||||
COPY ./scripts/entrypoint.sh .
|
COPY ./scripts/entrypoint.sh .
|
||||||
|
|
||||||
COPY --from=logo /logo.txt .
|
COPY --from=logo /logo.txt .
|
||||||
COPY --from=nodeBuilder /app/dist/ ./templates/
|
COPY --from=nodeBuilder /app/dist/ ./web/
|
||||||
COPY --from=goBuilder /app/cafe-plaetschwiesle .
|
COPY --from=goBuilder /app/cafe-plaetschwiesle .
|
||||||
COPY config.toml .
|
|
||||||
|
|
||||||
ARG VERSION
|
ARG VERSION
|
||||||
ENV VERSION=$VERSION
|
ENV VERSION=$VERSION
|
||||||
|
|
4
internal/env/env.go
vendored
4
internal/env/env.go
vendored
|
@ -14,8 +14,8 @@ type Config struct {
|
||||||
TimeZone string `env:"TZ" envDefault:"Etc/UTC" validate:"timezone"`
|
TimeZone string `env:"TZ" envDefault:"Etc/UTC" validate:"timezone"`
|
||||||
Port int `env:"PORT" envDefault:"8080" validate:"min=1024,max=49151"`
|
Port int `env:"PORT" envDefault:"8080" validate:"min=1024,max=49151"`
|
||||||
LogLevel string `env:"LOG_LEVEL" envDefault:"info" validate:"oneof=debug info warn error panic fatal"`
|
LogLevel string `env:"LOG_LEVEL" envDefault:"info" validate:"oneof=debug info warn error panic fatal"`
|
||||||
Version string `env:"APP_VERSION" envDefault:"v0.0.0"`
|
Version string `env:"VERSION" envDefault:"v0.0.0"`
|
||||||
SwaggerHost string `env:"SWAGGER_HOST" envDefault:"https://cafe.test"`
|
SwaggerHost string `env:"SWAGGER_HOST"`
|
||||||
DB_Host string `env:"DB_HOST"`
|
DB_Host string `env:"DB_HOST"`
|
||||||
DB_User string `env:"DB_USER"`
|
DB_User string `env:"DB_USER"`
|
||||||
DB_Password string `env:"DB_PASSWORD"`
|
DB_Password string `env:"DB_PASSWORD"`
|
||||||
|
|
|
@ -4,6 +4,13 @@ import (
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func longCacheLifetime(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
|
return func(c echo.Context) error {
|
||||||
|
c.Response().Header().Set(echo.HeaderCacheControl, "public, max-age=31536000")
|
||||||
|
return next(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func authHeader(next echo.HandlerFunc) echo.HandlerFunc {
|
func authHeader(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
return func(c echo.Context) error {
|
return func(c echo.Context) error {
|
||||||
c.Response().Header().Set("Remote-Groups", c.Request().Header.Get("Remote-Groups"))
|
c.Response().Header().Set("Remote-Groups", c.Request().Header.Get("Remote-Groups"))
|
||||||
|
|
|
@ -29,11 +29,22 @@ func InitRouter() *echo.Echo {
|
||||||
e.Pre(middleware.RemoveTrailingSlash())
|
e.Pre(middleware.RemoveTrailingSlash())
|
||||||
|
|
||||||
e.Validator = &CustomValidator{Validator: newValidator()}
|
e.Validator = &CustomValidator{Validator: newValidator()}
|
||||||
|
e.Renderer = initTemplates()
|
||||||
|
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetupRoutes(e *echo.Echo, ctrl *controller.Controller, env *env.Config) {
|
func SetupRoutes(e *echo.Echo, ctrl *controller.Controller, env *env.Config) {
|
||||||
|
favicon := e.Group("/favicon", longCacheLifetime)
|
||||||
|
favicon.Static("/", "web/favicon")
|
||||||
|
fonts := e.Group("/fonts", longCacheLifetime)
|
||||||
|
fonts.Static("/", "web/fonts")
|
||||||
|
img := e.Group("/img", longCacheLifetime)
|
||||||
|
img.Static("/", "web/img")
|
||||||
|
|
||||||
|
e.Static("/css", "web/css")
|
||||||
|
e.Static("/js", "web/js")
|
||||||
|
|
||||||
api := e.Group("/api")
|
api := e.Group("/api")
|
||||||
{
|
{
|
||||||
tableGroup := api.Group("/tables")
|
tableGroup := api.Group("/tables")
|
||||||
|
@ -75,13 +86,13 @@ func SetupRoutes(e *echo.Echo, ctrl *controller.Controller, env *env.Config) {
|
||||||
health := api.Group("/health", authHeader)
|
health := api.Group("/health", authHeader)
|
||||||
{
|
{
|
||||||
health.GET("", func(ctx echo.Context) error {
|
health.GET("", func(ctx echo.Context) error {
|
||||||
return ctx.String(http.StatusOK, ".")
|
return ctx.String(http.StatusOK, env.Version)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if env.SwaggerHost != "" {
|
if env.SwaggerHost != "" {
|
||||||
docs.SwaggerInfo.Title = "Cafe"
|
docs.SwaggerInfo.Title = "Café Plätschwiesle"
|
||||||
docs.SwaggerInfo.Description = "This is the backend of a cafe"
|
docs.SwaggerInfo.Description = "This is the backend of Café Plätschwiesle"
|
||||||
docs.SwaggerInfo.Version = env.Version
|
docs.SwaggerInfo.Version = env.Version
|
||||||
docs.SwaggerInfo.BasePath = "/api"
|
docs.SwaggerInfo.BasePath = "/api"
|
||||||
parsed, _ := url.Parse(env.SwaggerHost)
|
parsed, _ := url.Parse(env.SwaggerHost)
|
||||||
|
@ -90,5 +101,12 @@ func SetupRoutes(e *echo.Echo, ctrl *controller.Controller, env *env.Config) {
|
||||||
api.GET("/swagger/*", echoSwagger.WrapHandler)
|
api.GET("/swagger/*", echoSwagger.WrapHandler)
|
||||||
zap.L().Info("swagger running", zap.String("url", env.SwaggerHost+"/api/swagger/index.html"))
|
zap.L().Info("swagger running", zap.String("url", env.SwaggerHost+"/api/swagger/index.html"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e.GET("/robots.txt", func(ctx echo.Context) error {
|
||||||
|
return ctx.String(http.StatusOK, "User-agent: *\nDisallow: /")
|
||||||
|
})
|
||||||
|
e.RouteNotFound("*", func(c echo.Context) error {
|
||||||
|
return c.Render(http.StatusOK, "index.html", nil)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
22
internal/router/templates.go
Normal file
22
internal/router/templates.go
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/labstack/echo/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Template struct {
|
||||||
|
templates *template.Template
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
|
||||||
|
return t.templates.ExecuteTemplate(w, name, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initTemplates() *Template {
|
||||||
|
return &Template{
|
||||||
|
templates: template.Must(template.ParseGlob("web/*.html")),
|
||||||
|
}
|
||||||
|
}
|
|
@ -103,6 +103,7 @@ export default defineComponent({
|
||||||
visible: () => maker.value,
|
visible: () => maker.value,
|
||||||
},
|
},
|
||||||
{ label: "Abmelden", icon: "pi pi-fw pi-power-off", command: () => emit("logout") },
|
{ label: "Abmelden", icon: "pi pi-fw pi-power-off", command: () => emit("logout") },
|
||||||
|
{ label: store.getters.getVersion, icon: "pi pi-fw pi-github", disabled: true },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { createApp } from "vue";
|
import { createApp, version } from "vue";
|
||||||
import { OpenAPI, UsersService } from "@/services/openapi";
|
import { OpenAPI, UsersService } from "@/services/openapi";
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import router from "./router";
|
import router from "./router";
|
||||||
|
@ -26,6 +26,7 @@ async function getHealth() {
|
||||||
store.commit("setGroups", groups);
|
store.commit("setGroups", groups);
|
||||||
const user = await UsersService.getUsers(response.headers.get("remote-name") || "Benutzer");
|
const user = await UsersService.getUsers(response.headers.get("remote-name") || "Benutzer");
|
||||||
store.commit("setUser", user);
|
store.commit("setUser", user);
|
||||||
|
store.commit("setVersion", await response.text());
|
||||||
}
|
}
|
||||||
|
|
||||||
getHealth().then(() => {
|
getHealth().then(() => {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { controller_User } from "@/services/openapi";
|
||||||
interface AppStateModel {
|
interface AppStateModel {
|
||||||
user: controller_User;
|
user: controller_User;
|
||||||
groups: string[];
|
groups: string[];
|
||||||
|
version: string;
|
||||||
}
|
}
|
||||||
export default createStore({
|
export default createStore({
|
||||||
state: {
|
state: {
|
||||||
|
@ -15,6 +16,7 @@ export default createStore({
|
||||||
show_hot_drinks: true,
|
show_hot_drinks: true,
|
||||||
},
|
},
|
||||||
groups: [""],
|
groups: [""],
|
||||||
|
version: "",
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
getUser(state: AppStateModel) {
|
getUser(state: AppStateModel) {
|
||||||
|
@ -26,6 +28,9 @@ export default createStore({
|
||||||
getUsername(state: AppStateModel) {
|
getUsername(state: AppStateModel) {
|
||||||
return state.user.username;
|
return state.user.username;
|
||||||
},
|
},
|
||||||
|
getVersion(state: AppStateModel) {
|
||||||
|
return state.version;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
setUser(state: AppStateModel, _user: controller_User) {
|
setUser(state: AppStateModel, _user: controller_User) {
|
||||||
|
@ -34,6 +39,9 @@ export default createStore({
|
||||||
setGroups(state: AppStateModel, groups: string[]) {
|
setGroups(state: AppStateModel, groups: string[]) {
|
||||||
state.groups = groups;
|
state.groups = groups;
|
||||||
},
|
},
|
||||||
|
setVersion(state: AppStateModel, version: string) {
|
||||||
|
state.version = version;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
actions: {},
|
actions: {},
|
||||||
modules: {
|
modules: {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue