Move to Gitea: git.ryuvia.com/niklas/terdut-server
CI / test (push) Successful in 2m15s

The module path, the container image, the Helm chart and the CI pipeline all
named GitHub. They now name the Gitea instance everything else already runs on.

The workflows are rewritten rather than translated. Gitea's runner image is
ubuntu:22.04, whose nodejs is Node 12, so no JS action runs there at all --
actions/checkout@v4 dies with a SyntaxError before it does anything. Every step
is shell, checkout is a plain clone (this repo is public, so it needs no
credential), and the jobs that need docker or helm run in host mode because the
dind bridge a `container:` job gets cannot reach github.com or get.helm.sh.

Two consequences worth naming:

- upload-artifact/download-artifact are also JS actions, and there is no
  artifact store here, so the job that builds the binaries is the job that
  publishes them. Nothing is passed between jobs.
- setup-qemu-action is gone with the rest, and the runner has no binfmt
  registration. The Dockerfile's builder stage now runs on $BUILDPLATFORM and
  cross-compiles from TARGETARCH instead, which is what keeps the arm64 image
  buildable -- and makes it native rather than emulated.

The chart moves from a GitHub Pages index to an OCI artifact in Gitea's
registry. Publishing stays tag-only for the reason recorded in release.yaml: a
workflow triggered by the branch push cannot know the version it is about to be
tagged with.

The GitHub repository is left in place and untouched. Nothing pushes to it any
more, but its existing release downloads and chart index keep resolving.
This commit is contained in:
Niklas Ye
2026-08-19 20:39:10 +02:00
parent 766f43931c
commit 289eca8076
21 changed files with 313 additions and 228 deletions
+66
View File
@@ -0,0 +1,66 @@
name: CI
# The release workflow gates a tag, which is late: a broken commit sits green until
# somebody decides to publish. This runs the same checks on the way in.
#
# push is scoped to main rather than all branches so that a branch pushed as part of a
# pull request is not checked twice.
#
# No actions/checkout, deliberately -- same as the letsvisit and charts workflows. The
# runner image is ubuntu:22.04 whose `nodejs` package is Node 12, and actions/checkout@v4
# is built with ES2022 static initialiser blocks, so it dies with
# `SyntaxError: Unexpected token '{'` before running. Cloning with git directly avoids JS
# actions entirely. This repo is public, so the clone needs no credential at all.
#
# `${{ }}` values are passed through `env:` and referenced as quoted shell variables: a
# ref name is attacker-influenced by anyone who can push a branch or open a PR, and
# expanding one straight into `run:` is a shell-injection vector.
on:
push:
branches: [main]
pull_request:
# A rapid series of pushes only needs the last one checked.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
env:
REPO_URL: https://git.ryuvia.com/niklas/terdut-server.git
jobs:
test:
runs-on: ubuntu-latest
container:
# Runs inside the toolchain image rather than installing Go per job. Note this puts
# the job on the dind bridge, which cannot reach github.com or get.helm.sh --
# proxy.golang.org and git.ryuvia.com are reachable, which is all this job needs.
image: golang:1.26.6-bookworm
# act_runner destroys a job's own volumes when it finishes, so without these every
# run re-downloads the whole module graph. The names must appear in the runner's
# container.valid_volumes allowlist (charts/act-runner in the k8s repo); unlisted
# volumes are dropped silently, so a workflow that looks correct can still be
# running uncached.
volumes:
- go-mod-cache:/go/pkg/mod
- go-build-cache:/root/.cache/go-build
- gobin-cache:/go/bin
steps:
- name: Checkout
env:
REF_NAME: ${{ github.ref_name }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
if [ -n "$HEAD_SHA" ]; then
# A pull_request ref_name is "<n>/merge", which is not a fetchable branch.
git clone "$REPO_URL" .
git checkout -q "$HEAD_SHA"
else
git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" .
fi
- name: Vet
run: go vet ./...
- name: Test
run: go test ./...
+209
View File
@@ -0,0 +1,209 @@
name: Release
# Checkout, interpolation and caching conventions match ci.yaml -- see the header there
# for why there are no JS actions and why every `${{ }}` goes through `env:`.
#
# There is no upload-artifact/download-artifact equivalent here (both are JS actions, and
# this Gitea has no artifact store wired up), so the job that builds the binaries is also
# the job that publishes them. Nothing is handed between jobs at all.
on:
push:
tags:
- 'v*'
workflow_dispatch:
# A tag is not normally re-pushed, so this mostly matters when one is force-moved during
# a botched release -- the superseded run stops holding runner slots.
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: true
env:
REPO_URL: https://git.ryuvia.com/niklas/terdut-server.git
API: https://git.ryuvia.com/api/v1/repos/niklas/terdut-server
REGISTRY: git.ryuvia.com
IMAGE: git.ryuvia.com/niklas/terdut-server
jobs:
# Gates every publishing job below. A tag that fails here publishes nothing: the
# binaries, the image and the chart are all downstream of it.
test:
runs-on: ubuntu-latest
container:
image: golang:1.26.6-bookworm
volumes:
- go-mod-cache:/go/pkg/mod
- go-build-cache:/root/.cache/go-build
- gobin-cache:/go/bin
steps:
- name: Checkout
env:
REF_NAME: ${{ github.ref_name }}
run: git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" .
- name: Vet
run: go vet ./...
- name: Test
run: go test ./...
binaries:
needs: test
runs-on: ubuntu-latest
container:
image: golang:1.26.6-bookworm
volumes:
- go-mod-cache:/go/pkg/mod
- go-build-cache:/root/.cache/go-build
- gobin-cache:/go/bin
steps:
- name: Checkout
env:
REF_NAME: ${{ github.ref_name }}
run: git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" .
- name: Build every target
env:
REF_NAME: ${{ github.ref_name }}
run: |
set -eu
mkdir -p dist
for target in linux/amd64 linux/arm64 darwin/amd64 darwin/arm64; do
GOOS="${target%/*}"
GOARCH="${target#*/}"
out="dist/terdut-${REF_NAME}-${GOOS}-${GOARCH}"
echo "building $out"
GOOS="$GOOS" GOARCH="$GOARCH" go build \
-ldflags "-w -s -X main.version=${REF_NAME}" \
-o "$out" ./cmd/terdut
done
# Creating the release is made idempotent rather than assumed-new: a re-run of a
# failed release must not die on the release that already exists. Assets are
# replaced the same way, so a re-run repairs a partial upload.
- name: Publish the release
env:
REF_NAME: ${{ github.ref_name }}
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: |
set -eu
auth="Authorization: token $TOKEN"
body=$(curl -sf -H "$auth" "$API/releases/tags/$REF_NAME" || true)
if [ -z "$body" ]; then
body=$(curl -sf -X POST -H "$auth" -H 'Content-Type: application/json' \
-d "{\"tag_name\":\"$REF_NAME\",\"name\":\"$REF_NAME\"}" \
"$API/releases")
fi
# The release object serialises `id` first, so the first match is the release's
# own id and not one of the nested author/asset ids.
release_id=$(printf '%s' "$body" | grep -o '"id":[0-9]*' | head -1 | cut -d: -f2)
[ -n "$release_id" ] || { echo "::error::could not determine release id"; exit 1; }
echo "release id $release_id"
for f in dist/*; do
name=$(basename "$f")
# Drop an existing asset of the same name first: Gitea happily stores two
# attachments with one name, and the updater matches by name.
old=$(curl -sf -H "$auth" "$API/releases/$release_id/assets" \
| tr '}' '\n' | grep "\"name\":\"$name\"" \
| grep -o '"id":[0-9]*' | head -1 | cut -d: -f2 || true)
if [ -n "$old" ]; then
curl -sf -X DELETE -H "$auth" "$API/releases/$release_id/assets/$old" || true
fi
echo "uploading $name"
curl -sf -X POST -H "$auth" -F "attachment=@$f" \
"$API/releases/$release_id/assets?name=$name" > /dev/null
done
# Host mode on purpose (no `container:`): this is the only context with a Docker CLI
# pointed at the dind daemon. A `container:` job would sit on the dind bridge with no
# docker socket at all.
image:
needs: test
runs-on: ubuntu-latest
steps:
- name: Checkout
env:
REF_NAME: ${{ github.ref_name }}
run: git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" .
- name: Log in to the registry
env:
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: echo "$TOKEN" | docker login "$REGISTRY" -u niklas --password-stdin
# The default "docker" driver cannot build more than one platform at a time; the
# docker-container driver can. Reused across runs if it survived the last one.
- name: Prepare buildx
run: docker buildx create --name terdut --use 2>/dev/null || docker buildx use terdut
# No QEMU: the Dockerfile's builder stage runs on $BUILDPLATFORM and cross-compiles
# from TARGETARCH, so both platforms build natively. See the comment in Dockerfile.
- name: Build and push
env:
REF_NAME: ${{ github.ref_name }}
run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--build-arg "VERSION=${REF_NAME}" \
--tag "${IMAGE}:latest" \
--tag "${IMAGE}:${REF_NAME}" \
--push .
# Also host mode: helm is baked into the runner image, and a `container:` job could not
# install it -- get.helm.sh is unreachable from the dind bridge.
chart:
needs: test
runs-on: ubuntu-latest
steps:
- name: Checkout
env:
REF_NAME: ${{ github.ref_name }}
run: git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" .
# This job is the only thing that publishes the chart, which is what keeps the
# published metadata honest. There used to be a second publisher on every charts/**
# push to main, and the two raced for the same chart version with different answers:
# this one stamps version and appVersion from the tag, that one took Chart.yaml
# verbatim, where appVersion is the hardcoded "latest". Whichever landed first won,
# so the metadata of a release depended on which runner was quicker -- chart 0.9.0
# went out on 2026-08-08 reading appVersion "latest" that way.
#
# It could not be fixed by making both agree: the tag is pushed after the branch, so
# a workflow triggered by the main push cannot know the version it is about to be
# tagged with. One publisher, triggered by the tag.
#
# The cost is that the chart only ships with an app release. That is no real loss --
# the sed below ties the chart version to the app version, so a chart-only change
# has no version of its own to be released under anyway. Chart fixes ride the next
# tag.
- name: Stamp the chart version from the tag
env:
REF_NAME: ${{ github.ref_name }}
run: |
set -eu
if ! echo "$REF_NAME" | grep -qE '^v[0-9]'; then
echo "::error::refusing to publish a chart for non-version tag ${REF_NAME}"
exit 1
fi
CHART_VERSION="${REF_NAME#v}"
sed -i "s/^version:.*/version: ${CHART_VERSION}/" charts/terdut-server/Chart.yaml
sed -i "s/^appVersion:.*/appVersion: \"${REF_NAME}\"/" charts/terdut-server/Chart.yaml
cat charts/terdut-server/Chart.yaml
- name: Package and push
env:
REF_NAME: ${{ github.ref_name }}
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: |
set -eu
echo "$TOKEN" | helm registry login "$REGISTRY" -u niklas --password-stdin
# Isolated repo config: the machine-wide helm repo list is not this job's
# business, and one unreachable entry in it aborts otherwise-fine commands.
export HELM_REPOSITORY_CONFIG="$PWD/.helm-repos.yaml"
export HELM_REPOSITORY_CACHE="$PWD/.helm-cache"
: > "$HELM_REPOSITORY_CONFIG"
helm package charts/terdut-server -d dist
helm push "dist/terdut-server-${REF_NAME#v}.tgz" "oci://${REGISTRY}/niklas"
-34
View File
@@ -1,34 +0,0 @@
name: CI
# The release workflow gates a tag, which is late: a broken commit sits green
# until somebody decides to publish. This runs the same checks on the way in.
#
# push is scoped to main rather than all branches for two reasons: a branch
# pushed as part of a pull request would otherwise be checked twice, and
# gh-pages holds the published Helm chart index with no Go code in it, so
# `go vet ./...` there would fail on a missing go.mod.
on:
push:
branches: [main]
pull_request:
# A rapid series of pushes only needs the last one checked.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Vet
run: go vet ./...
- name: Test
run: go test ./...
-166
View File
@@ -1,166 +0,0 @@
name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
jobs:
# Gates every publishing job below. A tag that fails here publishes nothing:
# the binaries, the image and the chart are all downstream of it.
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Vet
run: go vet ./...
- name: Test
run: go test ./...
build:
needs: test
runs-on: ubuntu-latest
strategy:
matrix:
include:
- goos: linux
goarch: amd64
- goos: linux
goarch: arm64
- goos: darwin
goarch: amd64
- goos: darwin
goarch: arm64
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Build
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
run: |
go build \
-ldflags "-w -s -X main.version=${{ github.ref_name }}" \
-o terdut-${{ github.ref_name }}-${{ matrix.goos }}-${{ matrix.goarch }} \
./cmd/terdut
- uses: actions/upload-artifact@v4
with:
name: terdut-${{ github.ref_name }}-${{ matrix.goos }}-${{ matrix.goarch }}
path: terdut-${{ github.ref_name }}-${{ matrix.goos }}-${{ matrix.goarch }}
docker:
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
build-args: VERSION=${{ github.ref_name }}
tags: |
ghcr.io/yeniklas/terdut-server:latest
ghcr.io/yeniklas/terdut-server:${{ github.ref_name }}
chart:
needs: test
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Configure Git
run: |
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Install Helm
uses: azure/setup-helm@v4
# This job is the only thing that publishes the chart, which is what keeps
# the published metadata honest. There used to be a second publisher --
# chart-release.yml, on every charts/** push to main -- and the two raced
# for the same chart version with different answers: this one stamps
# version and appVersion from the tag, that one took Chart.yaml verbatim,
# where appVersion is the hardcoded "latest". Whichever landed first won
# and skip_existing turned the loser into a no-op, so the metadata of a
# release depended on which runner was quicker. Chart 0.9.0 went out on
# 2026-08-08 reading appVersion "latest" that way.
#
# It could not be fixed by making both agree: the tag is pushed after the
# branch, so a workflow triggered by the main push cannot know the version
# it is about to be tagged with. One publisher, triggered by the tag.
#
# The cost is that the chart only ships with an app release. That is no
# real loss -- the sed below ties the chart version to the app version, so
# a chart-only change has no version of its own to be released under
# anyway. Chart fixes ride the next tag.
- name: Update chart versions
run: |
VERSION="${{ github.ref_name }}"
if [[ ! "$VERSION" =~ ^v[0-9] ]]; then
echo "::error::refusing to publish a chart for non-version tag ${VERSION}"
exit 1
fi
CHART_VERSION="${VERSION#v}"
sed -i "s/^version:.*/version: ${CHART_VERSION}/" charts/terdut-server/Chart.yaml
sed -i "s/^appVersion:.*/appVersion: \"${VERSION}\"/" charts/terdut-server/Chart.yaml
- name: Run chart-releaser
uses: helm/chart-releaser-action@v1.6.0
with:
# Keeps a re-run of a failed release idempotent rather than failing on
# the chart that already went out. It is no longer papering over a
# race -- see above.
skip_existing: true
env:
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
release:
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/download-artifact@v4
with:
merge-multiple: true
- uses: softprops/action-gh-release@v2
with:
files: 'terdut-*'
+11 -2
View File
@@ -1,10 +1,19 @@
FROM golang:1.25-alpine AS builder # --platform=$BUILDPLATFORM pins the builder to the machine doing the building, so a
# multi-arch build compiles both targets natively instead of running an emulated arm64
# toolchain under QEMU. Go cross-compiles from TARGETOS/TARGETARCH, which BuildKit fills
# in per platform. The CI runner has no binfmt registration and no way to get one (the
# JS action that used to install it cannot run there), so this is not just an
# optimisation -- it is what makes the arm64 image buildable at all.
FROM --platform=$BUILDPLATFORM golang:1.25-alpine AS builder
WORKDIR /src WORKDIR /src
COPY go.mod go.sum ./ COPY go.mod go.sum ./
RUN go mod download RUN go mod download
COPY . . COPY . .
ARG VERSION=dev ARG VERSION=dev
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s -X main.version=${VERSION}" -o /terdut ./cmd/terdut ARG TARGETOS
ARG TARGETARCH
RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \
go build -ldflags="-w -s -X main.version=${VERSION}" -o /terdut ./cmd/terdut
FROM scratch FROM scratch
COPY --from=builder /terdut /terdut COPY --from=builder /terdut /terdut
+5 -4
View File
@@ -17,7 +17,7 @@ Incident management server for teams using Prometheus Alertmanager.
**Prerequisites:** Go 1.21+ **Prerequisites:** Go 1.21+
```bash ```bash
git clone https://github.com/yeniklas/terdut-server git clone https://git.ryuvia.com/niklas/terdut-server
cd terdut-server cd terdut-server
go run ./cmd/terdut go run ./cmd/terdut
``` ```
@@ -52,11 +52,12 @@ docker run -p 8080:8080 -v $(pwd)/data:/data \
### Kubernetes ### Kubernetes
A Helm chart is published from this repository: A Helm chart is published from this repository as an OCI artifact, versioned in lockstep
with the app — chart `x.y.z` is always app `vx.y.z`:
```bash ```bash
helm repo add terdut-server https://yeniklas.github.io/terdut-server helm upgrade --install terdut-server oci://git.ryuvia.com/niklas/terdut-server \
helm upgrade --install terdut-server terdut-server/terdut-server \ --version 0.9.0 \
--namespace terdut-server --create-namespace \ --namespace terdut-server --create-namespace \
--set networking.hostname=terdut.example.com --set networking.hostname=terdut.example.com
``` ```
+4 -4
View File
@@ -2,10 +2,10 @@ apiVersion: v2
name: terdut-server name: terdut-server
description: A Helm chart for Terminal Duty — on-call alert management server description: A Helm chart for Terminal Duty — on-call alert management server
type: application type: application
# These two are placeholders for a local `helm install ./charts/terdut-server`, # These two are placeholders for a local `helm install ./charts/terdut-server`, not the
# not the released values. release.yml rewrites both from the git tag when it # released values. .gitea/workflows/release.yaml rewrites both from the git tag when it
# publishes, so the chart version always equals the app version. Bumping them by # publishes, so the chart version always equals the app version. Bumping them by hand
# hand does nothing for a release and is not needed before tagging. # does nothing for a release and is not needed before tagging.
# "latest" is honest here: it matches image.tag in values.yaml. # "latest" is honest here: it matches image.tag in values.yaml.
version: 0.9.0 version: 0.9.0
appVersion: "latest" appVersion: "latest"
+1 -1
View File
@@ -7,7 +7,7 @@ networking:
listener: "" listener: ""
image: image:
repository: ghcr.io/yeniklas/terdut-server repository: git.ryuvia.com/niklas/terdut-server
tag: "latest" tag: "latest"
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
+3 -3
View File
@@ -8,9 +8,9 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/yeniklas/terdut-server/internal/api" "git.ryuvia.com/niklas/terdut-server/internal/api"
"github.com/yeniklas/terdut-server/internal/config" "git.ryuvia.com/niklas/terdut-server/internal/config"
"github.com/yeniklas/terdut-server/internal/db" "git.ryuvia.com/niklas/terdut-server/internal/db"
) )
var version = "dev" var version = "dev"
+1 -1
View File
@@ -1,4 +1,4 @@
module github.com/yeniklas/terdut-server module git.ryuvia.com/niklas/terdut-server
go 1.25.9 go 1.25.9
+1 -1
View File
@@ -11,7 +11,7 @@ import (
"time" "time"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/yeniklas/terdut-server/internal/models" "git.ryuvia.com/niklas/terdut-server/internal/models"
) )
// alertSelectFrom is the shared SELECT … FROM … clause used by all alert queries. // alertSelectFrom is the shared SELECT … FROM … clause used by all alert queries.
+2 -2
View File
@@ -12,8 +12,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/yeniklas/terdut-server/internal/api" "git.ryuvia.com/niklas/terdut-server/internal/api"
"github.com/yeniklas/terdut-server/internal/db" "git.ryuvia.com/niklas/terdut-server/internal/db"
) )
// ts wraps httptest.Server with a pre-bootstrapped API key. db is exposed so // ts wraps httptest.Server with a pre-bootstrapped API key. db is exposed so
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/yeniklas/terdut-server/internal/api" "git.ryuvia.com/niklas/terdut-server/internal/api"
) )
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/yeniklas/terdut-server/internal/models" "git.ryuvia.com/niklas/terdut-server/internal/models"
) )
// Values for incidents.resolution_source, recording who closed the incident: // Values for incidents.resolution_source, recording who closed the incident:
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"time" "time"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/yeniklas/terdut-server/internal/models" "git.ryuvia.com/niklas/terdut-server/internal/models"
) )
func handleListIncidents(db *sql.DB) http.HandlerFunc { func handleListIncidents(db *sql.DB) http.HandlerFunc {
+2 -2
View File
@@ -10,8 +10,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/yeniklas/terdut-server/internal/api" "git.ryuvia.com/niklas/terdut-server/internal/api"
"github.com/yeniklas/terdut-server/internal/db" "git.ryuvia.com/niklas/terdut-server/internal/db"
) )
// amAlert builds one alert of a webhook payload. // amAlert builds one alert of a webhook payload.
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/yeniklas/terdut-server/internal/models" "git.ryuvia.com/niklas/terdut-server/internal/models"
) )
type contextKey string type contextKey string
+1 -1
View File
@@ -11,7 +11,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/yeniklas/terdut-server/internal/models" "git.ryuvia.com/niklas/terdut-server/internal/models"
) )
const ( const (
+1 -1
View File
@@ -11,7 +11,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/yeniklas/terdut-server/internal/api" "git.ryuvia.com/niklas/terdut-server/internal/api"
) )
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"time" "time"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/yeniklas/terdut-server/internal/models" "git.ryuvia.com/niklas/terdut-server/internal/models"
) )
func handleCreateSchedule(db *sql.DB) http.HandlerFunc { func handleCreateSchedule(db *sql.DB) http.HandlerFunc {
+1 -1
View File
@@ -12,7 +12,7 @@ import (
"time" "time"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/yeniklas/terdut-server/internal/models" "git.ryuvia.com/niklas/terdut-server/internal/models"
) )
func handleBootstrap(db *sql.DB) http.HandlerFunc { func handleBootstrap(db *sql.DB) http.HandlerFunc {