From 90ad9d652f009a53b57115c924446baf6f1d3b7b Mon Sep 17 00:00:00 2001 From: seth Date: Sun, 7 Jan 2024 20:42:07 -0500 Subject: [PATCH] feat: use nix to build images this should result in smaller images, as well as safer updates --- .github/dependabot.yml | 8 +++ .github/workflows/check-commit.yml | 31 ---------- .github/workflows/docker-publish.yml | 63 -------------------- .github/workflows/docker.yaml | 87 ++++++++++++++++++++++++++++ .gitignore | 4 ++ Dockerfile | 21 ------- container.nix | 51 ++++++++++++++++ current_commit.txt | 1 - flake.lock | 26 +++++++++ flake.nix | 34 +++++++++++ 10 files changed, 210 insertions(+), 116 deletions(-) create mode 100644 .github/dependabot.yml delete mode 100644 .github/workflows/check-commit.yml delete mode 100644 .github/workflows/docker-publish.yml create mode 100644 .github/workflows/docker.yaml create mode 100644 .gitignore delete mode 100644 Dockerfile create mode 100644 container.nix delete mode 100644 current_commit.txt create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..8db6eb5 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + commit-message: + prefix: "deps(actions)" diff --git a/.github/workflows/check-commit.yml b/.github/workflows/check-commit.yml deleted file mode 100644 index 87d00a0..0000000 --- a/.github/workflows/check-commit.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Get latest commit -on: - workflow_dispatch: - schedule: - - cron: '0 0 * * *' - -jobs: - get-commit: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3.3.0 - - name: Fetch packwiz commit - run: | - curl -sL https://api.github.com/repos/packwiz/packwiz/commits | jq .[0].sha > current_commit.txt - - name: Check for new commit - id: git-check - run: | - echo ::set-output name=modified::$([ -z "`git status --porcelain`" ] && echo "false" || echo "true") - - name: Update cached commit - if: steps.git-check.outputs.modified == 'true' - run: | - git config --global user.name 'github-actions' - git config --global user.email 'github-actions@github.com' - git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }} - - git add current_commit.txt - - git commit -m "chore: update packwiz commit" - git tag -a "$(date '+%Y%m%d')" -m "scheduled release" - - git push --follow-tags diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml deleted file mode 100644 index 1e19120..0000000 --- a/.github/workflows/docker-publish.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: Publish Docker Image - -on: - push: - tags: - - '*' - pull_request: - branches: - - 'main' - -env: - IMAGE_NAME: ${{ github.repository }} - - -jobs: - build: - - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - id-token: write - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Install cosign - if: github.event_name != 'pull_request' - uses: sigstore/cosign-installer@main - - - name: Setup Docker buildx - uses: docker/setup-buildx-action@v2 - - - name: Log into docker hub - if: github.event_name != 'pull_request' - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_TOKEN }} - - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.IMAGE_NAME }} - - - name: Build and push Docker image - id: build-and-push - uses: docker/build-push-action@v3 - with: - context: . - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: Sign the published Docker image - if: ${{ github.event_name != 'pull_request' }} - env: - COSIGN_EXPERIMENTAL: "true" - run: echo "${{ steps.meta.outputs.tags }}" | xargs -I {} cosign sign {}@${{ steps.build-and-push.outputs.digest }} diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml new file mode 100644 index 0000000..b90999a --- /dev/null +++ b/.github/workflows/docker.yaml @@ -0,0 +1,87 @@ +name: Publish Docker Image + +on: + push: + branches: [main] + pull_request: + +jobs: + build: + name: Build image + runs-on: ubuntu-latest + + strategy: + matrix: + arch: [x86_64, aarch64] + + permissions: + contents: read + + steps: + - uses: actions/checkout@v4 + + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@v9 + + - name: Setup Nix cache + uses: DeterminateSystems/magic-nix-cache-action@v2 + + - name: Build Docker image + id: build + run: | + nix build -L .#container-${{ matrix.arch }} + [ ! -L result ] && exit 1 + echo "path=$(realpath result)" >> "$GITHUB_OUTPUT" + + - name: Upload image + uses: actions/upload-artifact@v4 + with: + name: container-${{ matrix.arch }} + path: ${{ steps.build.outputs.path }} + if-no-files-found: error + retention-days: 12 + + push: + name: Push image + runs-on: ubuntu-latest + needs: build + + permissions: + contents: read + packages: write + + if: github.event_name == 'push' + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Download images + uses: actions/download-artifact@v4 + with: + path: images + + - name: Login to registry + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Push to registry + env: + TAG: docker.io/getchoo/packwiz-serve:latest + run: | + set -euo pipefail + + architectures=("x86_64" "aarch64") + for arch in "${architectures[@]}"; do + docker load < images/container-"$arch"/*.tar.gz + docker tag packwiz-serve:latest-"$arch" ${{ env.TAG }}-"$arch" + docker push ${{ env.TAG }}-"$arch" + done + + docker manifest create ${{ env.TAG }} \ + --amend ${{ env.TAG }}-x86_64 \ + --amend ${{ env.TAG }}-aarch64 + + docker manifest push ${{ env.TAG }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b94215f --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# nix build artifacts +result* +repl-result-out* + diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index dfec610..0000000 --- a/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM docker.io/golang:alpine3.17 AS build - -RUN apk add --no-cache git=2.38.3-r1 - -RUN git clone https://github.com/packwiz/packwiz.git /build - -WORKDIR /build -RUN go mod download -RUN go build - -FROM docker.io/alpine:3.17 - -RUN mkdir /app -COPY --from=build /build/packwiz /app/ - -WORKDIR /data -VOLUME /data - -EXPOSE 8080 - -CMD [ "/app/packwiz", "serve" ] diff --git a/container.nix b/container.nix new file mode 100644 index 0000000..79d7c5c --- /dev/null +++ b/container.nix @@ -0,0 +1,51 @@ +{ + lib, + pkgs, + system, + ... +}: arch: let + crossPkgs = + { + "x86_64-linux" = { + "x86_64" = pkgs.pkgsStatic; + "aarch64" = pkgs.pkgsCross.aarch64-multiplatform.pkgsStatic; + }; + + "aarch64-linux" = { + "x86_64" = pkgs.pkgsCross.musl64; + "aarch64" = pkgs.pkgsStatic; + }; + } + .${system} + .${arch}; + + packwiz = crossPkgs.packwiz.overrideAttrs (oldAttrs: { + ldflags = [ + "-linkmode external" + "-extldflags '-static -L${crossPkgs.musl}/lib'" + "-s -w -X github.com/packwiz/packwiz.version=${oldAttrs.version}" + ]; + + postInstall = ""; + + CGO_ENABLED = 0; + }); +in + pkgs.dockerTools.buildLayeredImage { + name = "packwiz-serve"; + tag = "latest-${arch}"; + + contents = [packwiz]; + + config = { + Cmd = ["/bin/packwiz" "serve"]; + Env = [ + "HOME=/home" # why exactly does packwiz need a home dir? :shrug: + ]; + WorkingDir = "/data"; + Volumes = {"/data" = {};}; + ExposedPorts = {"8080" = {};}; + }; + + architecture = crossPkgs.go.GOARCH; + } diff --git a/current_commit.txt b/current_commit.txt deleted file mode 100644 index 4d03402..0000000 --- a/current_commit.txt +++ /dev/null @@ -1 +0,0 @@ -"7e3ca8d9d54ec56d0ceaaca293e502c39d824422" diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..d30663e --- /dev/null +++ b/flake.lock @@ -0,0 +1,26 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1704161960, + "narHash": "sha256-QGua89Pmq+FBAro8NriTuoO/wNaUtugt29/qqA8zeeM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "63143ac2c9186be6d9da6035fa22620018c85932", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixpkgs-unstable", + "type": "indirect" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..8008d76 --- /dev/null +++ b/flake.nix @@ -0,0 +1,34 @@ +{ + description = "a docker image to serve packwiz modpacks"; + + inputs.nixpkgs.url = "nixpkgs/nixpkgs-unstable"; + + outputs = { + self, + nixpkgs, + ... + }: let + systems = [ + "x86_64-linux" + "aarch64-linux" + ]; + + forAllSystems = fn: nixpkgs.lib.genAttrs systems (sys: fn nixpkgs.legacyPackages.${sys}); + in { + formatter = forAllSystems (pkgs: pkgs.alejandra); + + packages = forAllSystems ({ + pkgs, + system, + ... + }: let + containerFor = import ./container.nix pkgs; + arch = pkgs.stdenv.hostPlatform.uname.processor; + in { + container-x86_64 = containerFor "x86_64"; + container-aarch64 = containerFor "aarch64"; + + default = self.packages.${system}."container-${arch}"; + }); + }; +}