diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f53a359..59523b7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,9 @@ jobs: - uses: actions/setup-go@v5 with: go-version-file: go.mod - + - name: Log in to ghcr.io + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | podman login ghcr.io -u ${{ github.actor }} --password-stdin - uses: goreleaser/goreleaser-action@v6 with: distribution: goreleaser diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 82ae489..9da1304 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -55,6 +55,46 @@ changelog: - Merge pull request - Merge branch +dockers: + - image_templates: + - "ghcr.io/conallob/coding-interview-pattern-drill:{{ .Tag }}-amd64" + dockerfile: Dockerfile + use: podman + goos: linux + goarch: amd64 + build_flag_templates: + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + - "--label=org.opencontainers.image.source=https://github.com/conallob/coding-interview-pattern-drill" + - image_templates: + - "ghcr.io/conallob/coding-interview-pattern-drill:{{ .Tag }}-arm64" + dockerfile: Dockerfile + use: podman + goos: linux + goarch: arm64 + build_flag_templates: + - "--platform=linux/arm64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + - "--label=org.opencontainers.image.source=https://github.com/conallob/coding-interview-pattern-drill" + +docker_manifests: + - name_template: "ghcr.io/conallob/coding-interview-pattern-drill:{{ .Tag }}" + use: podman + image_templates: + - "ghcr.io/conallob/coding-interview-pattern-drill:{{ .Tag }}-amd64" + - "ghcr.io/conallob/coding-interview-pattern-drill:{{ .Tag }}-arm64" + - name_template: "ghcr.io/conallob/coding-interview-pattern-drill:latest" + use: podman + image_templates: + - "ghcr.io/conallob/coding-interview-pattern-drill:{{ .Tag }}-amd64" + - "ghcr.io/conallob/coding-interview-pattern-drill:{{ .Tag }}-arm64" + brews: - name: coding-interview-pattern-drill repository: diff --git a/Dockerfile b/Dockerfile index bee9bfc..e881527 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=linux/amd64 alpine:3 AS certs +FROM alpine:3 AS certs RUN apk add --no-cache ca-certificates FROM scratch diff --git a/cmd/coding-interview-pattern-drill/main.go b/cmd/coding-interview-pattern-drill/main.go index ff27b4d..1bc7e6f 100644 --- a/cmd/coding-interview-pattern-drill/main.go +++ b/cmd/coding-interview-pattern-drill/main.go @@ -1,16 +1,24 @@ package main import ( + "fmt" "os" "github.com/conallob/coding-interview-pattern-drill/cli" "github.com/conallob/coding-interview-pattern-drill/server" + "github.com/conallob/coding-interview-pattern-drill/version" ) func main() { - if len(os.Args) > 1 && os.Args[1] == "serve" { - server.Run(os.Args[2:]) - return + if len(os.Args) > 1 { + switch os.Args[1] { + case "--version", "-version", "version": + fmt.Println(version.Version) + return + case "serve": + server.Run(os.Args[2:]) + return + } } cli.Run(os.Args[1:]) } diff --git a/server/server.go b/server/server.go index e925fd9..b98838a 100644 --- a/server/server.go +++ b/server/server.go @@ -16,15 +16,16 @@ import ( "github.com/conallob/coding-interview-pattern-drill/leetcode" "github.com/conallob/coding-interview-pattern-drill/patterns" "github.com/conallob/coding-interview-pattern-drill/quiz" + "github.com/conallob/coding-interview-pattern-drill/version" ) // resultPayload is the JSON payload for a quiz answer result. type resultPayload struct { - Correct bool `json:"correct"` - ChoiceIndex int `json:"choiceIndex"` - AnswerIndex int `json:"answerIndex"` - PrimaryPattern patternInfo `json:"primaryPattern"` - SecondaryPatterns []patternInfo `json:"secondaryPatterns"` + Correct bool `json:"correct"` + ChoiceIndex int `json:"choiceIndex"` + AnswerIndex int `json:"answerIndex"` + PrimaryPattern patternInfo `json:"primaryPattern"` + SecondaryPatterns []patternInfo `json:"secondaryPatterns"` } type patternInfo struct { @@ -92,6 +93,7 @@ func Run(args []string) { mux.HandleFunc("/api/quiz/answer", app.handleQuizAnswer) mux.HandleFunc("/api/quiz/next", app.handleQuizNext) mux.HandleFunc("/api/cache/refresh", app.handleCacheRefresh) + mux.HandleFunc("/version", handleVersion) // Find a free port basePort := *port @@ -511,3 +513,12 @@ func (a *App) handleCacheRefresh(w http.ResponseWriter, r *http.Request) { writeJSON(w, http.StatusOK, map[string]bool{"ok": true}) } + +// GET /version → {"version": "v1.2.3"} +func handleVersion(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + writeError(w, http.StatusMethodNotAllowed, "method not allowed") + return + } + writeJSON(w, http.StatusOK, map[string]string{"version": version.Version}) +} diff --git a/version/version.go b/version/version.go new file mode 100644 index 0000000..e64fef5 --- /dev/null +++ b/version/version.go @@ -0,0 +1,5 @@ +package version + +// Version is set at build time via -ldflags "-X github.com/conallob/coding-interview-pattern-drill/version.Version=". +// Falls back to "dev" for local builds. +var Version = "dev"