Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
name: ci
# Validates every PR to main: builds the binary and
# the Docker image via Nix to catch broken build before merge.
name: "Pull Request Checks"

on:
pull_request:
branches: [main]
branches: [main] # Runs only on PRs to main branch to validate the build.
paths-ignore:
- 'README.md'
- 'wiki/**'
workflow_dispatch:

jobs:
# Runs on PRs only to validate the build.
# nixos/web.nix uses buildGoModule which compiles the Go binary (no separate build job needed)
# and runs `go test -short` via doCheck = true (no separate test job needed).
# and runs `go test -short` via doCheck = true (no separate test job needed).
# nixos/web.docker.nix builds the Docker image which includes the compiled binary.
build:
runs-on: ubuntu-latest
timeout-minutes: 15
Expand All @@ -34,5 +36,8 @@ jobs:
restore-prefixes-first-match: nix-${{ runner.os }}-
gc-max-store-size-linux: 5368709120 # 5 GB

- name: Build NixOS configuration
run: nix build
- name: Build binary
run: nix build .#default

- name: Build Docker image
run: nix build .#docker
80 changes: 80 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: release

on:
push:
tags:
- 'v*'
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read

steps:
- uses: actions/checkout@v7

- name: Install Nix
uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
experimental-features = nix-command flakes

- name: Cache Nix store
uses: nix-community/cache-nix-action@v7
with:
primary-key: nix-${{ runner.os }}-${{ hashFiles('flake.lock', '**/*.nix', '**/*.go') }}
restore-prefixes-first-match: nix-${{ runner.os }}-
gc-max-store-size-linux: 5368709120 # 5 GB

- name: Build Docker image
run: nix build .#docker

- name: Export Docker image as tar
run: cp --dereference result gearberg-docker.tar.gz

- name: Upload Docker image artifact
uses: actions/upload-artifact@v4
with:
name: gearberg-docker
path: gearberg-docker.tar.gz
retention-days: 1

release:
needs: build
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
packages: write

steps:
- uses: actions/checkout@v7

- name: Download Docker image artifact
uses: actions/download-artifact@v4
with:
name: gearberg-docker

- name: Login to ghcr.io
run: echo "${{ github.token }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin

- name: Push Docker image to ghcr.io
run: |
IMAGE_ID=$(docker load < gearberg-docker.tar.gz | grep "Loaded image" | awk '{print $NF}')
docker tag "$IMAGE_ID" ghcr.io/${{ github.repository }}:${{ github.ref_name }}
docker tag "$IMAGE_ID" ghcr.io/${{ github.repository }}:latest
docker push ghcr.io/${{ github.repository }}:${{ github.ref_name }}
docker push ghcr.io/${{ github.repository }}:latest

- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "${{ github.ref_name }}" \
--title "${{ github.ref_name }}" \
--generate-notes

4 changes: 2 additions & 2 deletions cmd/web/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func parseOptions(args []string) (*options, error) {
fs := flag.NewFlagSet("serve", flag.ContinueOnError)
fs.SetOutput(os.Stderr)
fs.Var(&cfg.LogLevel, "log-level", "log level (debug|info|warn|error)")
fs.StringVar(&cfg.DbDsn, "db-dsn", envOr("DB_DSN", "file:gearberg.db"), "database DSN")
fs.StringVar(&cfg.DbDsn, "db-dsn", envOr("DB_DSN", "file:/data/gearberg.db"), "database DSN")
fs.IntVar(&cfg.Port, "port", 8080, "port to listen on")
fs.StringVar(&cfg.BaseURL, "base-url", "localhost:8080", "base URL for link generation (e.g. https://example.com)")
fs.StringVar(&cfg.TLSMode, "tls-mode", "off", "TLS mode (off|local)")
Expand All @@ -56,7 +56,7 @@ func parseOptions(args []string) (*options, error) {
fs.IntVar(&cfg.MaxOrgCategories, "max-categories", 25, "maximum number of equipment categories per org")
fs.IntVar(&cfg.MaxOrgManufacturers, "max-manufacturers", 100, "maximum number of manufacturers per org")
fs.IntVar(&cfg.MaxOrgLocations, "max-locations", 100, "maximum number of locations per org")
fs.StringVar(&cfg.StorageDSN, "storage-dsn", envOr("STORAGE_DSN", "./var/data"), "storage backend DSN")
fs.StringVar(&cfg.StorageDSN, "storage-dsn", envOr("STORAGE_DSN", "file:///data/uploads"), "storage backend DSN")
fs.Int64Var(&cfg.MaxStorageBytes, "max-storage-bytes", 1<<30, "maximum storage bytes per org (default 1 GiB)")
fs.Var(&cfg.OIDCProviders, "oidc-provider", "OIDC provider: name,issuer=URL,client-id=ID,client-secret=SECRET (repeatable)")

Expand Down
12 changes: 6 additions & 6 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@

# Go binaries built with Nix for all systems.
# Docker image is only built for x86_64-linux.
packages =
forAllSystems (system: {
packages = forAllSystems (system:
{
default = import ./nixos/web.nix {
buildpkgs = nixpkgs-unstable.legacyPackages.${system};
version = self.rev or self.dirtyRev or "dev";
Expand All @@ -34,13 +34,13 @@
buildpkgs = nixpkgs-unstable.legacyPackages.${system};
version = self.rev or self.dirtyRev or "dev";
};
})
// {
x86_64-linux.docker = import ./nixos/web.docker.nix {
}
// nixpkgs.lib.optionalAttrs (system == "x86_64-linux") {
docker = import ./nixos/web.docker.nix {
pkgs = nixpkgs-unstable.legacyPackages.x86_64-linux;
pkgsTarget = nixpkgs-unstable.legacyPackages.x86_64-linux;
version = self.rev or self.dirtyRev or "dev";
};
};
});
};
}
25 changes: 24 additions & 1 deletion nixos/web.docker.nix
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,31 @@ in
pkgs.dockerTools.buildImage {
name = "gearberg";
tag = version;
# Required for outbound TLS: OIDC discovery and JWKS calls will fail without it.
copyToRoot = pkgs.buildEnv {
name = "image-root";
paths = [pkgsTarget.cacert];
};
config = {
Cmd = ["${gearberg}/bin/gearberg"];
# The gearberg binary has sane defaults and will start without environment variables but
# you can override them if you want to change the defaults. Environment variables can be set
# in the docker run command or in a docker-compose file.
Entrypoint = ["${gearberg}/bin/gearberg" "serve"];
# Any flag can be called that is exposed by gearberg binary.
# See `gearberg serve --help` for all available flags.
Cmd = [];
# curl is pulled in via the Nix closure this is why there is no need to add it to copyToRoot.
# Timing fields are in nanoseconds per the OCI config spec.
Healthcheck = {
Test = ["CMD" "${pkgsTarget.curl}/bin/curl" "-f" "http://localhost:8080/v1/healthz"];
Interval = 30 * 1000000000;
Timeout = 5 * 1000000000;
Retries = 3;
};
# By default, gearberg listens on port 8080 but this can be overridden by -port flag.
ExposedPorts = {"8080/tcp" = {};};
# Gearberg does save its data to /data, which is a volume in the image.
# When starting the image, you should mount a host directory to /data to persist the data.
Volumes = {"/data" = {};};
};
}