Skip to content

Commit 820b84b

Browse files
committed
Cleanup Dockerfile
This adds 2 new settings: GITDIR_ADMIN_USER, and GITDIR_ADMIN_PUBLIC_KEY, which allow gitdir to auto-add a public key to the config on startup. This greatly simplifies the setup process and lines up with how many services are run in docker. Unfortunately, between the last commit and now, travis-ci dropped their free option, so the CI is also being migrated to Github Actions. Finally, all packages and linters have been updated to their latest versions.
1 parent 708eabd commit 820b84b

38 files changed

+534
-273
lines changed

.dockerignore

+3
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
**/node_modules
44
Dockerfile
55
docker-compose.yaml
6+
.env
7+
gitdir
8+
tmp

.github/workflows/test.yml

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Test
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v2
14+
15+
- name: Set up Go
16+
uses: actions/setup-go@v2
17+
with:
18+
go-version: 1.17
19+
20+
- name: Build
21+
run: go build -v ./...
22+
23+
- name: Test
24+
run: go test -v ./...
25+
26+
lint:
27+
runs-on: ubuntu-latest
28+
steps:
29+
- uses: actions/checkout@v2
30+
- name: golangci-lint
31+
uses: golangci/golangci-lint-action@v2
32+
with:
33+
version: v1.42.1

.gitignore

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# Output of the go coverage tool, specifically when used with LiteIDE
1313
*.out
1414

15-
# Temporary folder for the repo storage.
16-
# TODO: remove this.
17-
tmp
15+
/tmp
1816
admin-clone
17+
.env
18+
/gitdir

.golangci.yml

+19-1
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,28 @@ linters:
33
disable:
44
- godox
55
- gomnd
6-
- prealloc
76
- unparam
87
- gochecknoglobals
8+
- goerr113
9+
- exhaustivestruct
10+
- nestif
11+
- wrapcheck
12+
- nlreturn
13+
- testpackage
14+
- exhaustive
15+
16+
# Deprecated linters
17+
- interfacer
18+
- maligned
19+
- scopelint
20+
- golint
921

1022
linters-settings:
1123
govet:
1224
check-shadowing: true
25+
gci:
26+
local-prefixes: github.com/belak/go-gitdir
27+
tagliatelle:
28+
case:
29+
rules:
30+
yaml: snake

.travis.yml

-20
This file was deleted.

Dockerfile

+28-44
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,30 @@
1-
FROM golang:1 as builder
2-
ARG CGO_ENABLED=0\
3-
GO_LDFLAGS="-s -w"
4-
RUN mkdir -p /tmp/build
5-
COPY . /tmp/build
6-
WORKDIR /tmp/build/cmd/gitdir
7-
RUN set -ex && ls -la && export &&\
8-
until go get -v ./...; do sleep 1; done &&\
9-
go build -o /tmp/gitdir -ldflags="$GO_LDFLAGS" -x -v &&\
10-
chmod +x /tmp/gitdir
11-
12-
FROM alpine:3 as runner
13-
ENV GITDIR_BASE_DIR=/var/gitdir\
14-
GITDIR_BIND_ADDR=0.0.0.0:2222
15-
RUN until apk add --no-cache git curl openssh-keygen ca-certificates; do sleep 1; done &&\
16-
update-ca-certificates
17-
RUN adduser -D -H -s /bin/false gitdir gitdir
18-
COPY --from=builder /tmp/gitdir /usr/bin/gitdir
19-
RUN chmod +x /usr/bin/gitdir && ls -l /usr/bin/gitdir
20-
RUN rm -rf /{tmp,var,opt}/*
21-
RUN mkdir -p $GITDIR_BASE_DIR && chown -R gitdir:gitdir $GITDIR_BASE_DIR
22-
RUN echo -e '#!/bin/sh\n \
23-
( \
24-
set -x; \
25-
rm -rf $GITDIR_BASE_DIR/admin/unbared; \
26-
until [ -d "$GITDIR_BASE_DIR/admin/admin.git" ]; do echo "The admin repo is not ready"; sleep 1; done &&\
27-
cd $GITDIR_BASE_DIR/admin/admin.git &&\
28-
until git log >> /dev/null 2>&1; do echo "The admin repo is been initalized, waiting"; sleep 5; done; \
29-
mv $GITDIR_BASE_DIR/admin/admin.git/hooks $GITDIR_BASE_DIR/admin/admin.git/hooks.disabled &&\
30-
git clone $GITDIR_BASE_DIR/admin/admin.git $GITDIR_BASE_DIR/admin/unbared &&\
31-
cd $GITDIR_BASE_DIR/admin/unbared &&\
32-
git config user.name "gitdir Docker Helper Script" &&\
33-
git config user.email "[email protected]" &&\
34-
vi config.yml &&\
35-
git commit --no-verify config.yml &&\
36-
git push &&\
37-
rm -rf $GITDIR_BASE_DIR/admin/unbared &&\
38-
echo "Saved! You may need to restart the server to verify and apply the settings"; \
39-
mv $GITDIR_BASE_DIR/admin/admin.git/hooks.disabled $GITDIR_BASE_DIR/admin/admin.git/hooks \
40-
)' > /usr/bin/gitdir_config && chmod +x /usr/bin/gitdir_config
41-
WORKDIR $GITDIR_BASE_DIR
42-
USER gitdir:gitdir
1+
# Stage 1: Build the application
2+
FROM golang:1.17-bullseye as builder
3+
4+
# Get yq to use as a helper script in the debian image.
5+
6+
RUN mkdir /build && mkdir /usr/local/src/gitdir
7+
WORKDIR /usr/local/src/gitdir
8+
9+
ADD ./go.mod ./go.sum ./
10+
RUN go mod download
11+
ADD . ./
12+
13+
RUN go build -v -o /build/gitdir ./cmd/gitdir
14+
15+
# State 2: Copy files and configure what we need
16+
FROM debian:bullseye-slim as runner
17+
18+
ENV GITDIR_BASE_DIR=/var/lib/gitdir \
19+
GITDIR_BIND_ADDR=0.0.0.0:2222
20+
21+
VOLUME /var/lib/gitdir
22+
23+
# Install git so git-upload-pack and git-receive-pack work.
24+
RUN apt-get update && apt-get install -y git \
25+
&& rm -rf /var/lib/apt/lists/*
26+
27+
COPY --from=builder /build/gitdir /usr/bin/gitdir
4328

4429
EXPOSE 2222
45-
ENTRYPOINT ["gitdir"]
46-
CMD []
30+
CMD ["gitdir"]

README.md

+11-4
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ The following are optional:
6565
defaults to `:2222`.
6666
- `GITDIR_LOG_READABLE` - A true value if the log should be human readable
6767
- `GITDIR_LOG_DEBUG` - A true value if debug logging should be enabled
68+
- `GITDIR_ADMIN_USER` - The name of an admin user which the server will ensure
69+
exists on startup.
70+
- `GITHUB_ADMIN_PUBLIC_KEY` - The contents of a public key which will be added
71+
to the admin user on startup.
6872

6973
### Runtime Config
7074

@@ -89,14 +93,17 @@ which change the behavior of the server.
8993

9094
Simply run the built binary with `GITDIR_BASE_DIR` set and start using it!
9195

92-
On first run, go-git-dir will push a commit to the admin repo with a sample
96+
On first run, gitdir will push a commit to the admin repo with a sample
9397
config as well as generated server ssh keys. These can be updated at any time
9498
(even at runtime) but if the server restarts and the keys cannot be loaded, they
9599
will be re-generated.
96100

97-
Note that you will need to manually clone the admin repository (at
98-
`$GITDIR_BASE_DIR/admin/admin`) to add a user to `config.yml` and set them as an
99-
admin.
101+
If you set `GITDIR_ADMIN_USER` and `GITHUB_ADMIN_PUBLIC_KEY` an admin user will
102+
automatically be added to the config.
103+
104+
If you do not set those environment variables, you will need to manually clone
105+
the admin repository (at `$GITDIR_BASE_DIR/admin/admin`) to add a user to
106+
`config.yml` and set them as an admin.
100107

101108
## Sample Config
102109

cmd/gitdir/cmd_hook.go

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//nolint:forbidigo
12
package main
23

34
import (

cmd/gitdir/cmd_serve.go

+11
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ func cmdServe(c Config) {
1414
log.Fatal().Err(err).Msg("failed to load SSH server")
1515
}
1616

17+
// If both the AdminUser and AdminPublicKey were set, attempt to add that
18+
// user to the config.
19+
if c.AdminUser != "" && c.AdminPublicKey != nil {
20+
log.Info().Str("user", c.AdminUser).Msg("ensuring admin user exists")
21+
22+
err = serv.EnsureAdminUser(c.AdminUser, c.AdminPublicKey)
23+
if err != nil {
24+
log.Fatal().Err(err).Msg("failed to add admin user")
25+
}
26+
}
27+
1728
serv.Addr = c.BindAddr
1829

1930
err = serv.ListenAndServe()

cmd/gitdir/config.go

+35-13
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
11
package main
22

33
import (
4+
"errors"
5+
"fmt"
46
"os"
57
"path/filepath"
68
"strconv"
79

810
billy "github.com/go-git/go-billy/v5"
911
"github.com/go-git/go-billy/v5/osfs"
10-
"github.com/pkg/errors"
1112
"github.com/rs/zerolog"
1213
"github.com/rs/zerolog/log"
14+
15+
"github.com/belak/go-gitdir/models"
1316
)
1417

1518
// Config stores all the server-level settings. These cannot be changed at
1619
// runtime. They are only used by the binary and are passed to the proper
1720
// places.
1821
type Config struct {
19-
BindAddr string
20-
BasePath string
21-
LogFormat string
22-
LogDebug bool
22+
BindAddr string
23+
BasePath string
24+
LogFormat string
25+
LogDebug bool
26+
AdminUser string
27+
AdminPublicKey *models.PublicKey
2328
}
2429

2530
// FS returns the billy.Filesystem for this base path.
@@ -29,21 +34,24 @@ func (c Config) FS() billy.Filesystem {
2934

3035
// DefaultConfig is used as the base config.
3136
var DefaultConfig = Config{
32-
BindAddr: ":2222",
33-
BasePath: "./tmp",
34-
LogFormat: "json",
37+
BindAddr: ":2222",
38+
BasePath: "./tmp",
39+
LogFormat: "json",
40+
LogDebug: false,
41+
AdminUser: "",
42+
AdminPublicKey: nil,
3543
}
3644

3745
// NewEnvConfig returns a new Config based on environment variables.
38-
func NewEnvConfig() (Config, error) {
46+
func NewEnvConfig() (Config, error) { //nolint:cyclop,funlen
3947
var err error
4048

4149
c := DefaultConfig
4250

4351
if rawDebug, ok := os.LookupEnv("GITDIR_DEBUG"); ok {
4452
c.LogDebug, err = strconv.ParseBool(rawDebug)
4553
if err != nil {
46-
return c, errors.Wrap(err, "GITDIR_DEBUG")
54+
return c, fmt.Errorf("GITDIR_DEBUG: %w", err)
4755
}
4856
}
4957

@@ -69,21 +77,35 @@ func NewEnvConfig() (Config, error) {
6977
var ok bool
7078

7179
if c.BasePath, ok = os.LookupEnv("GITDIR_BASE_DIR"); !ok {
72-
return c, errors.New("GITDIR_BASE_DIR: not set")
80+
return c, fmt.Errorf("GITDIR_BASE_DIR: not set")
7381
}
7482

7583
if c.BasePath, err = filepath.Abs(c.BasePath); err != nil {
76-
return c, errors.Wrap(err, "GITDIR_BASE_DIR")
84+
return c, fmt.Errorf("GITDIR_BASE_DIR: %w", err)
7785
}
7886

7987
info, err := os.Stat(c.BasePath)
8088
if err != nil {
81-
return c, errors.Wrap(err, "GITDIR_BASE_DIR")
89+
return c, fmt.Errorf("GITDIR_BASE_DIR: %w", err)
8290
}
8391

8492
if !info.IsDir() {
8593
return c, errors.New("GITDIR_BASE_DIR: not a directory")
8694
}
8795

96+
// AdminUser and AdminPublicKey are allowed to not be set.
97+
if adminUser, ok := os.LookupEnv("GITDIR_ADMIN_USER"); ok {
98+
c.AdminUser = adminUser
99+
}
100+
101+
if adminPublicKeyRaw, ok := os.LookupEnv("GITDIR_ADMIN_PUBLIC_KEY"); ok {
102+
adminPublicKey, err := models.ParsePublicKey([]byte(adminPublicKeyRaw))
103+
if err != nil {
104+
return c, fmt.Errorf("GITDIR_ADMIN_PUBLIC_KEY: %w", err)
105+
}
106+
107+
c.AdminPublicKey = adminPublicKey
108+
}
109+
88110
return c, nil
89111
}

cmd/gitdir/main.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,26 @@ package main
33
import (
44
"os"
55

6+
"github.com/joho/godotenv"
67
"github.com/rs/zerolog/log"
78
)
89

910
func main() {
11+
_ = godotenv.Load()
12+
1013
c, err := NewEnvConfig()
1114
if err != nil {
1215
log.Fatal().Err(err).Msg("failed to load base config")
1316
}
1417

1518
if len(os.Args) > 1 {
16-
if os.Args[1] != "hook" {
19+
switch os.Args[1] {
20+
case "hook":
21+
cmdHook(c)
22+
default:
1723
log.Fatal().Msg("sub-command not found")
1824
}
1925

20-
cmdHook(c)
21-
2226
return
2327
}
2428

0 commit comments

Comments
 (0)