Compare commits
7 Commits
2.0.0-rc.3
...
41c34c42cf
| Author | SHA1 | Date | |
|---|---|---|---|
| 41c34c42cf | |||
| 6998d07c6b | |||
| a5f5c37225 | |||
| fdda0ea669 | |||
| c10ab98997 | |||
| 8dc8c4eed3 | |||
| 3f49da49b6 |
@@ -6,6 +6,7 @@ on:
|
||||
- "*"
|
||||
branches:
|
||||
- main
|
||||
- dev/main
|
||||
|
||||
jobs:
|
||||
webserver:
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -40,3 +40,5 @@ atlas.hcl
|
||||
.scannerwork
|
||||
Backend/logs
|
||||
.worktime.txt
|
||||
|
||||
*_templ.go
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
db
|
||||
Dockerfile
|
||||
*_templ.go
|
||||
|
||||
@@ -1,24 +1,34 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM --platform=$BUILDPLATFORM golang:alpine AS build
|
||||
FROM --platform=$BUILDPLATFORM golang:alpine AS base
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ENV CGO_ENABLED=0 \
|
||||
GOOS=$TARGETOS \
|
||||
GOARCH=$TARGETARCH
|
||||
|
||||
FROM base AS fetch-stage
|
||||
WORKDIR /app
|
||||
COPY go.mod go.sum /app/
|
||||
RUN go mod download && go mod verify
|
||||
|
||||
COPY . .
|
||||
FROM ghcr.io/a-h/templ:latest AS generate-stage
|
||||
COPY --chown=65532:65532 . /app
|
||||
WORKDIR /app
|
||||
RUN ["templ", "generate"]
|
||||
|
||||
FROM base AS build
|
||||
COPY --from=generate-stage /app /app
|
||||
WORKDIR /app
|
||||
RUN go build -o server .
|
||||
|
||||
FROM alpine:3.22
|
||||
RUN apk add --no-cache tzdata typst
|
||||
WORKDIR /app
|
||||
COPY --from=build /app/server /app/server
|
||||
COPY ./doc/static /doc/static
|
||||
COPY ./doc/templates /doc/templates
|
||||
|
||||
COPY migrations /app/migrations
|
||||
|
||||
COPY doc /doc
|
||||
|
||||
COPY /static /app/static
|
||||
ENTRYPOINT ["./server"]
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"log/slog"
|
||||
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
"github.com/golang-migrate/migrate/v4/database/postgres"
|
||||
_ "github.com/golang-migrate/migrate/v4/database/postgres"
|
||||
_ "github.com/golang-migrate/migrate/v4/source/file"
|
||||
_ "github.com/lib/pq"
|
||||
@@ -20,21 +21,34 @@ func OpenDatabase() (models.IDatabase, error) {
|
||||
dbPassword := helper.GetEnv("POSTGRES_API_PASS", "password")
|
||||
dbTz := helper.GetEnv("TZ", "Europe/Berlin")
|
||||
|
||||
connStr := fmt.Sprintf("postgres://%s:%s@%s:5432/%s?sslmode=disable&TimeZone=%s", dbUser, dbPassword, dbHost, dbName, dbTz)
|
||||
connStr := fmt.Sprintf(
|
||||
"host=%s user=%s dbname=%s password=%s sslmode=disable TimeZone=%s",
|
||||
dbHost, dbUser, dbName, dbPassword, dbTz)
|
||||
|
||||
return sql.Open("postgres", connStr)
|
||||
}
|
||||
|
||||
func Migrate() error {
|
||||
dbHost := helper.GetEnv("POSTGRES_HOST", "localhost")
|
||||
dbName := helper.GetEnv("POSTGRES_DB", "arbeitszeitmessung")
|
||||
// dbUser := helper.GetEnv("POSTGRES_USER", "api_nutzer")
|
||||
dbPassword := helper.GetEnv("POSTGRES_PASSWORD", "password")
|
||||
dbTz := helper.GetEnv("TZ", "Europe/Berlin")
|
||||
|
||||
migrations := helper.GetEnv("MIGRATIONS_PATH", "../migrations")
|
||||
connStr := fmt.Sprintf(
|
||||
"host=%s user=%s dbname=%s password=%s sslmode=disable TimeZone=%s",
|
||||
dbHost, "migrate", dbName, dbPassword, dbTz)
|
||||
|
||||
connStr := fmt.Sprintf("postgres://%s:%s@%s:5432/%s?sslmode=disable&TimeZone=%s", "migrate", dbPassword, dbHost, dbName, dbTz)
|
||||
m, err := migrate.New(fmt.Sprintf("file://%s", migrations), connStr)
|
||||
db, err := sql.Open("postgres", connStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
driver, err := postgres.WithInstance(db, &postgres.Config{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m, err := migrate.NewWithDatabaseInstance("file:///app/migrations", "postgres", driver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -50,11 +50,13 @@ func main() {
|
||||
|
||||
defer models.DB.(*sql.DB).Close()
|
||||
|
||||
if helper.GetEnv("GO_ENV", "production") != "debug" {
|
||||
err = Migrate()
|
||||
if err != nil {
|
||||
slog.Error("Failed to migrate the database to newest version", "Error", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fs := http.FileServer(http.Dir("./static"))
|
||||
endpoints.CreateSessionManager(24 * time.Hour)
|
||||
|
||||
@@ -78,14 +78,8 @@
|
||||
border-style: var(--tw-border-style);
|
||||
border-width: 1px;
|
||||
border-color: var(--color-neutral-800);
|
||||
transition-property:
|
||||
color, background-color, border-color, outline-color,
|
||||
text-decoration-color, fill, stroke, --tw-gradient-from,
|
||||
--tw-gradient-via, --tw-gradient-to;
|
||||
transition-timing-function: var(
|
||||
--tw-ease,
|
||||
var(--default-transition-timing-function)
|
||||
);
|
||||
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;
|
||||
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
||||
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
||||
}
|
||||
|
||||
|
||||
@@ -205,45 +205,24 @@
|
||||
.top-0 {
|
||||
top: calc(var(--spacing) * 0);
|
||||
}
|
||||
.top-1 {
|
||||
top: calc(var(--spacing) * 1);
|
||||
}
|
||||
.top-1\/2 {
|
||||
top: calc(1/2 * 100%);
|
||||
}
|
||||
.top-2 {
|
||||
top: calc(var(--spacing) * 2);
|
||||
}
|
||||
.top-2\.5 {
|
||||
top: calc(var(--spacing) * 2.5);
|
||||
}
|
||||
.top-25 {
|
||||
top: calc(var(--spacing) * 25);
|
||||
}
|
||||
.top-26 {
|
||||
top: calc(var(--spacing) * 26);
|
||||
}
|
||||
.top-\[0\.125rem\] {
|
||||
top: 0.125rem;
|
||||
}
|
||||
.right-1 {
|
||||
right: calc(var(--spacing) * 1);
|
||||
}
|
||||
.right-2 {
|
||||
right: calc(var(--spacing) * 2);
|
||||
}
|
||||
.right-2\.5 {
|
||||
right: calc(var(--spacing) * 2.5);
|
||||
}
|
||||
.left-1 {
|
||||
left: calc(var(--spacing) * 1);
|
||||
}
|
||||
.left-1\/2 {
|
||||
left: calc(1/2 * 100%);
|
||||
}
|
||||
.z-10 {
|
||||
z-index: 10;
|
||||
}
|
||||
.z-100 {
|
||||
z-index: 100;
|
||||
}
|
||||
@@ -404,9 +383,6 @@
|
||||
.h-2 {
|
||||
height: calc(var(--spacing) * 2);
|
||||
}
|
||||
.h-3 {
|
||||
height: calc(var(--spacing) * 3);
|
||||
}
|
||||
.h-3\.5 {
|
||||
height: calc(var(--spacing) * 3.5);
|
||||
}
|
||||
@@ -431,9 +407,6 @@
|
||||
.w-2 {
|
||||
width: calc(var(--spacing) * 2);
|
||||
}
|
||||
.w-3 {
|
||||
width: calc(var(--spacing) * 3);
|
||||
}
|
||||
.w-3\.5 {
|
||||
width: calc(var(--spacing) * 3.5);
|
||||
}
|
||||
@@ -443,9 +416,6 @@
|
||||
.w-5 {
|
||||
width: calc(var(--spacing) * 5);
|
||||
}
|
||||
.w-9 {
|
||||
width: calc(var(--spacing) * 9);
|
||||
}
|
||||
.w-9\/10 {
|
||||
width: calc(9/10 * 100%);
|
||||
}
|
||||
@@ -458,9 +428,6 @@
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
.flex-shrink {
|
||||
flex-shrink: 1;
|
||||
}
|
||||
.flex-shrink-0 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -476,21 +443,10 @@
|
||||
.basis-\[content\] {
|
||||
flex-basis: content;
|
||||
}
|
||||
.border-collapse {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.-translate-x-1 {
|
||||
--tw-translate-x: calc(var(--spacing) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.-translate-x-1\/2 {
|
||||
--tw-translate-x: calc(calc(1/2 * 100%) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.-translate-y-1 {
|
||||
--tw-translate-y: calc(var(--spacing) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.-translate-y-1\/2 {
|
||||
--tw-translate-y: calc(calc(1/2 * 100%) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
@@ -501,9 +457,6 @@
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
.resize {
|
||||
resize: both;
|
||||
}
|
||||
.scroll-m-2 {
|
||||
scroll-margin: calc(var(--spacing) * 2);
|
||||
}
|
||||
@@ -661,9 +614,6 @@
|
||||
.bg-red-600 {
|
||||
background-color: var(--color-red-600);
|
||||
}
|
||||
.mask-repeat {
|
||||
mask-repeat: repeat;
|
||||
}
|
||||
.p-1 {
|
||||
padding: calc(var(--spacing) * 1);
|
||||
}
|
||||
@@ -740,16 +690,9 @@
|
||||
.uppercase {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.underline {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
.opacity-0 {
|
||||
opacity: 0%;
|
||||
}
|
||||
.outline {
|
||||
outline-style: var(--tw-outline-style);
|
||||
outline-width: 1px;
|
||||
}
|
||||
.filter {
|
||||
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
||||
}
|
||||
@@ -1195,11 +1138,6 @@
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-outline-style {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: solid;
|
||||
}
|
||||
@property --tw-blur {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
@@ -1272,7 +1210,6 @@
|
||||
--tw-border-style: solid;
|
||||
--tw-divide-y-reverse: 0;
|
||||
--tw-font-weight: initial;
|
||||
--tw-outline-style: solid;
|
||||
--tw-blur: initial;
|
||||
--tw-brightness: initial;
|
||||
--tw-contrast: initial;
|
||||
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
templ TeamPage(weeks []models.WorkWeek, userWeek models.WorkWeek) {
|
||||
@Base()
|
||||
@headerComponent()
|
||||
<div class="grid-main divide-y-1">
|
||||
<div class="grid-sub lg:divide-x-1 max-md:divide-y-1 responsive @container">
|
||||
<div class="grid-main divide-y-1 @container">
|
||||
<div class="grid-sub lg:divide-x-1 max-md:divide-y-1 responsive">
|
||||
<div class="grid-cell col-span-full bg-neutral-300 lg:border-0">
|
||||
<h2 class="text-xl uppercase font-bold">Eigene Abrechnung</h2>
|
||||
</div>
|
||||
@@ -34,7 +34,7 @@ templ workWeekComponent(week models.WorkWeek, onlyAccept bool) {
|
||||
year, kw := week.WeekStart.ISOWeek()
|
||||
progress := (float32(week.WorktimeVirtual.Hours()) / week.User.ArbeitszeitPerWoche) * 100
|
||||
}}
|
||||
<div class="employeComponent grid-sub responsive lg:divide-x-1 max-md:divide-y-1 @container">
|
||||
<div class="employeComponent grid-sub responsive lg:divide-x-1 max-md:divide-y-1">
|
||||
<div class="grid-cell flex flex-col max-md:bg-neutral-300 gap-2">
|
||||
if !onlyAccept {
|
||||
<div class="lg:hidden">
|
||||
|
||||
@@ -45,7 +45,7 @@ func TeamPage(weeks []models.WorkWeek, userWeek models.WorkWeek) templ.Component
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"grid-main divide-y-1\"><div class=\"grid-sub lg:divide-x-1 max-md:divide-y-1 responsive @container\"><div class=\"grid-cell col-span-full bg-neutral-300 lg:border-0\"><h2 class=\"text-xl uppercase font-bold\">Eigene Abrechnung</h2></div></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"grid-main divide-y-1 @container\"><div class=\"grid-sub lg:divide-x-1 max-md:divide-y-1 responsive\"><div class=\"grid-cell col-span-full bg-neutral-300 lg:border-0\"><h2 class=\"text-xl uppercase font-bold\">Eigene Abrechnung</h2></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -96,7 +96,7 @@ func workWeekComponent(week models.WorkWeek, onlyAccept bool) templ.Component {
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
year, kw := week.WeekStart.ISOWeek()
|
||||
progress := (float32(week.WorktimeVirtual.Hours()) / week.User.ArbeitszeitPerWoche) * 100
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div class=\"employeComponent grid-sub responsive lg:divide-x-1 max-md:divide-y-1 @container\"><div class=\"grid-cell flex flex-col max-md:bg-neutral-300 gap-2\">")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div class=\"employeComponent grid-sub responsive lg:divide-x-1 max-md:divide-y-1\"><div class=\"grid-cell flex flex-col max-md:bg-neutral-300 gap-2\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ echo "Creating PostgreSQL user and setting permissions... $POSTGRES_USER for API
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||
CREATE ROLE migrate LOGIN ENCRYPTED PASSWORD '$POSTGRES_PASSWORD';
|
||||
GRANT USAGE, CREATE ON SCHEMA public TO migrate;
|
||||
GRANT CONNECT ON DATABASE arbeitszeitmessung TO migrate;
|
||||
EOSQL
|
||||
|
||||
# psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||
|
||||
56
DBB/initdb/01_create_user.sh
Executable file
56
DBB/initdb/01_create_user.sh
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
set -e # Exit on error
|
||||
|
||||
echo "Creating PostgreSQL user and setting permissions... $POSTGRES_USER for API user $POSTGRES_API_USER"
|
||||
|
||||
|
||||
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||
CREATE ROLE migrate LOGIN ENCRYPTED PASSWORD '$POSTGRES_PASSWORD';
|
||||
GRANT USAGE, CREATE ON SCHEMA public TO migrate;
|
||||
GRANT CONNECT ON DATABASE arbeitszeitmessung TO migrate;
|
||||
EOSQL
|
||||
|
||||
# psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||
|
||||
# GRANT SELECT, INSERT, UPDATE ON anwesenheit, abwesenheit, user_password, wochen_report, s_feiertage TO $POSTGRES_API_USER;
|
||||
# GRANT DELETE ON abwesenheit TO $POSTGRES_API_USER;
|
||||
# GRANT SELECT ON s_personal_daten, s_abwesenheit_typen, s_anwesenheit_typen, s_feiertage TO $POSTGRES_API_USER;
|
||||
# GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO $POSTGRES_API_USER;
|
||||
# EOSQL
|
||||
|
||||
echo "User creation and permissions setup complete!"
|
||||
|
||||
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||
|
||||
-- privilege roles
|
||||
DO \$\$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'app_base') THEN
|
||||
CREATE ROLE app_base NOLOGIN;
|
||||
END IF;
|
||||
END
|
||||
\$\$;
|
||||
|
||||
-- dynamic login role
|
||||
DO \$\$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '$POSTGRES_API_USER') THEN
|
||||
CREATE ROLE $POSTGRES_API_USER
|
||||
LOGIN
|
||||
ENCRYPTED PASSWORD '$POSTGRES_API_PASS';
|
||||
END IF;
|
||||
END
|
||||
\$\$;
|
||||
|
||||
-- grant base privileges
|
||||
GRANT app_base TO $POSTGRES_API_USER;
|
||||
GRANT CONNECT ON DATABASE $POSTGRES_DB TO $POSTGRES_API_USER;
|
||||
GRANT USAGE ON SCHEMA public TO $POSTGRES_API_USER;
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
|
||||
EOSQL
|
||||
|
||||
# psql -v ON_ERROR_STOP=1 --username root --dbname arbeitszeitmessung
|
||||
@@ -13,9 +13,14 @@ services:
|
||||
- ${POSTGRES_PATH}/initdb:/docker-entrypoint-initdb.d
|
||||
ports:
|
||||
- ${POSTGRES_PORT}:5432
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready", "-U", "${POSTGRES_USER}", "--dbname", "${POSTGRES_DB}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
backend:
|
||||
image: git.letsstein.de/tom/arbeitszeitmessung-webserver
|
||||
image: git.letsstein.de/tom/arbeitszeitmessung-webserver:dev
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
@@ -24,12 +29,8 @@ services:
|
||||
ports:
|
||||
- ${WEB_PORT}:8080
|
||||
depends_on:
|
||||
- db
|
||||
db:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ${LOG_PATH}:/app/logs
|
||||
restart: unless-stopped
|
||||
|
||||
# document-creator:
|
||||
# image: git.letsstein.de/tom/arbeitszeitmessung-doc-creator
|
||||
# container_name: ${TYPST_CONTAINER}
|
||||
# restart: unless-stopped
|
||||
|
||||
@@ -5,7 +5,6 @@ POSTGRES_API_PASS=password # Postgres API Passwort (fü
|
||||
POSTGRES_PATH=__ROOT__/DB # Datebank Pfad (relativ zu Docker Ordner oder absoluter pfad mit /...)
|
||||
POSTGRES_DB=arbeitszeitmessung # Postgres Datenbank Name
|
||||
POSTGRES_PORT=127.0.0.1:5432 # Postgres Port normalerweise nicht freigegeben. regex:^[0-9]{1,5}$
|
||||
MIGRATIONS_PATH=__ROOT__/migrations # Pfad zu DB migrations (wenn nicht verändert wurde, bei default bleiben)
|
||||
TZ=Europe/Berlin # Zeitzone
|
||||
API_TOKEN=dont_access # API Token für ESP Endpoints
|
||||
WEB_PORT=8000 # Port unter welchem Webserver erreichbar ist. regex:^[0-9]{1,5}$
|
||||
|
||||
66
Jenkinsfile
vendored
66
Jenkinsfile
vendored
@@ -1,66 +0,0 @@
|
||||
pipeline {
|
||||
environment {
|
||||
DOCKER_USERNAME = 'jenkins'
|
||||
DOCKER_PASSWORD = credentials('gitea_jenkins')
|
||||
SONAR_TOKEN = credentials('sonarcube_token')
|
||||
POSTGRES_USER = 'postgres'
|
||||
POSTGRES_PASSWORD = 'password'
|
||||
POSTGRES_DB = 'arbeitszeitmessung'
|
||||
}
|
||||
|
||||
agent any
|
||||
|
||||
stages {
|
||||
stage('Test') {
|
||||
agent {
|
||||
docker {
|
||||
image ''
|
||||
args ''
|
||||
args ''
|
||||
}
|
||||
}
|
||||
steps {
|
||||
script {
|
||||
sh '''
|
||||
docker run -d --rm \
|
||||
--name test-db \
|
||||
-e POSTGRES_USER={$POSTGRES_USER} \
|
||||
-e POSTGRES_PASSWORD={$POSTGRES_PASSWORD} \
|
||||
-e POSTGRES_DB={$POSTGRES_DB} \
|
||||
-v ./DB/initdb:/docker-entrypoint-initdb.d\
|
||||
-p "5432:5432" \
|
||||
postgres:16
|
||||
'''
|
||||
// docker.image('golang:1.24.5').withRun(
|
||||
// '-u root:root --network=host'
|
||||
// ) { go ->
|
||||
// // wait for DB to start
|
||||
// sh '''
|
||||
// cd Backend \
|
||||
// go mod download && go mod tidy \
|
||||
// go test ./... -v
|
||||
|
||||
// '''
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('SonarCube Analysis') {
|
||||
steps {
|
||||
sh 'make scan'
|
||||
}
|
||||
}
|
||||
stage('Building image arbeitszeit-backend') {
|
||||
when {
|
||||
anyOf {
|
||||
changeset 'Jenkinsfile'
|
||||
changeset 'Makefile'
|
||||
changeset 'Backend/**'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
sh 'make backend'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Makefile
2
Makefile
@@ -44,7 +44,7 @@ generateFrontend:
|
||||
|
||||
|
||||
backend: generateFrontend login_registry
|
||||
docker buildx build --platform linux/amd64,linux/arm64 -t ${IMAGE_REGISTRY}/${PACKAGE_OWNER}/arbeitszeitmessung:latest Backend --push
|
||||
docker buildx build --platform linux/amd64,linux/arm64 -t ${IMAGE_REGISTRY}/${PACKAGE_OWNER}/arbeitszeitmessung-webserver:dev Backend --push
|
||||
# docker buildx build --platform linux/amd64,linux/arm64 -t ${IMAGE_REGISTRY}/${PACKAGE_OWNER}/arbeitszeitmessung:${GIT_COMMIT} Backend //--push
|
||||
|
||||
test:
|
||||
|
||||
26
Readme.md
26
Readme.md
@@ -120,3 +120,29 @@ Antwort `202` Akzeptiert und eingefügt
|
||||
|
||||
Antwort `409` Konflikt
|
||||
Die vorherige Buchung am selben Tag hat den gleichen Buchungstyp
|
||||
|
||||
# Filestrukture
|
||||
|
||||
```
|
||||
├── Backend (Webserver)
|
||||
│ ├── doc (Templates for Document Creator --> typst used to create PDF Reports)
|
||||
│ │ ├── static
|
||||
│ │ └── templates
|
||||
│ ├── endpoints (HTML Server endpoints (see main.go for Routes))
|
||||
│ ├── helper (Helper classes)
|
||||
│ │ ├── logs
|
||||
│ │ └── paramParser
|
||||
│ ├── logs (Log Folder, no sourcecode)
|
||||
│ ├── migrations (DB Migrations Folder, no direct sourcecode)
|
||||
│ ├── models (DB Models and their function)
|
||||
│ ├── src (Tailwind src --> used to config css formatter)
|
||||
│ ├── static (Webserver static, used to server static content, e.g. JS and CSS files)
|
||||
│ │ └── css
|
||||
│ └── templates (HTML Templates for every page written in templ and compiled to go)
|
||||
├── Cron (all Cron Scripts)
|
||||
├── DB (local Database mount Point)
|
||||
│ └── initdb (initialization scripts for DB)
|
||||
├── Docker (Docker Files, only docker-compose.yaml used)
|
||||
├── docs
|
||||
└── └── images
|
||||
```
|
||||
|
||||
@@ -123,9 +123,8 @@ echo "Created logs folder at $LOG_PATH"
|
||||
|
||||
echo -e "\n\n"
|
||||
echo "Start containers with docker compose up -d? [y/N]"
|
||||
read -r start_containersmkdi
|
||||
read -r start_containers
|
||||
if [[ "$start_containers" =~ ^[Yy]$ ]]; then
|
||||
|
||||
cd Docker
|
||||
docker compose up -d
|
||||
echo "Containers started."
|
||||
@@ -172,6 +171,7 @@ if [[ "$setup_cron" =~ ^[Yy]$ ]]; then
|
||||
|
||||
( crontab -l ; echo "$cron_timing $(pwd)/$file" )| awk '!x[$0]++' | crontab -
|
||||
echo "Added entry to crontab: $cron_timing $(pwd)/$file."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
if systemctl is-active --quiet cron.service ; then
|
||||
|
||||
Reference in New Issue
Block a user