Skip to content

Commit

Permalink
1.6.0: support for actions artifact-v4, Nix docker builds (#65)
Browse files Browse the repository at this point in the history
This fixes a breaking change in GHA's upload-artifact v4, which CI
relied upon in order to merge Docker manifests.

To make the CI easier for me to maintain, the Dockerfile-based builds
are gone in favour of a single Nix-based container build. This has the
breaking change of dropping support for 32-bit ARM, and the benefit of
bringing reproducible builds to container images. Given the armv6 images
had practically no downloads, few if any existing users should be
accepted (do please open an issue if this is you!).

This in turn makes leng practically a `FROM SCRACH` image, which reduces
the image attack surface. Image size remains about the same (pretty
small at 7MB).

Because of the breaking changes above, this makes release 1.6
  • Loading branch information
cottand authored Sep 30, 2024
1 parent de5e392 commit c4063e9
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 119 deletions.
137 changes: 65 additions & 72 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,92 +16,90 @@ env:


jobs:
docker:
publish-nix-container:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm/v6
- linux/arm/v7
- linux/arm64
system:
- aarch64-linux
- x86_64-linux
steps:
- name: Checkout
uses: actions/checkout@v3
- uses: actions/checkout@v3

- name: Set up QEMU
uses: docker/setup-qemu-action@v2

- uses: actions/setup-go@v4
- name: Login to GitHub Container Registry
uses: docker/[email protected]
with:
go-version-file: 'go.mod'

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
with:
driver-opts: |
image=moby/buildkit:v0.10.6
- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Docker meta
id: meta
uses: docker/metadata-action@v5
- uses: cachix/install-nix-action@v29
with:
# list of Docker images to use as base name for tags
images: ${{ env.REGISTRY_IMAGE }}
tags: |
type=sha,enable=false
github_access_token: ${{ secrets.GITHUB_TOKEN }}
extra_nix_config: |
extra-platforms = ${{ matrix.system }}
- name: Build and push (by digest)
uses: docker/build-push-action@v4
id: build
with:
push: true
context: .
file: docker/slim.Dockerfile
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: ${{ matrix.platform }}
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Export digest
- uses: DeterminateSystems/magic-nix-cache-action@main

- uses: docker/setup-qemu-action@v1

# build in parallel
- run: nix build .#packages.${{ matrix.system }}.leng-container-image -L

- name: Tag and push image
run: |
git_sha=$(git rev-parse --short "$GITHUB_SHA")
label=$git_sha-${{ matrix.system }}
docker load < result
docker tag leng:nix ${{ env.REGISTRY_IMAGE }}:$label
docker push ${{ env.REGISTRY_IMAGE }}:$label
# export digest
docker pull ${{ env.REGISTRY_IMAGE }}:$label
full=$(docker image inspect ${{ env.REGISTRY_IMAGE }}:$label --format "{{index .RepoDigests 0}}")
digest=${full#${{ env.REGISTRY_IMAGE }}@}
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge-docker:
runs-on: ubuntu-latest
needs: [docker]
needs: [ publish-nix-container ]
steps:
- name: Download digests
uses: actions/download-artifact@v4
- name: Login to GitHub Container Registry
uses: docker/[email protected]
with:
name: digests
path: /tmp/digests
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: digest for x86
run: |
system=x86_64-linux
git_sha=${GITHUB_SHA::7}
label="${git_sha}-${system}"
# export digest x86
docker pull ${{ env.REGISTRY_IMAGE }}:$label
full=$(docker image inspect ${{ env.REGISTRY_IMAGE }}:$label --format "{{index .RepoDigests 0}}")
digest=${full#${{ env.REGISTRY_IMAGE }}@}
mkdir -p /tmp/digests
touch "/tmp/digests/${digest#sha256:}"
- name: digest for aarch64
run: |
system=aarch64-linux
git_sha=${GITHUB_SHA::7}
label="${git_sha}-${system}"
# export digest x86
docker pull ${{ env.REGISTRY_IMAGE }}:$label
full=$(docker image inspect ${{ env.REGISTRY_IMAGE }}:$label --format "{{index .RepoDigests 0}}")
digest=${full#${{ env.REGISTRY_IMAGE }}@}
mkdir -p /tmp/digests
touch "/tmp/digests/${digest#sha256:}"
- name: Docker meta
id: meta
Expand All @@ -110,19 +108,14 @@ jobs:
# list of Docker images to use as base name for tags
images: ${{ env.REGISTRY_IMAGE }}
tags: |
type=schedule
# tag event
type=ref,event=tag
type=sha,event=tag
# pull request event
type=sha,event=pr
type=sha,event=push
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}
Expand Down
4 changes: 2 additions & 2 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import (
)

// BuildVersion returns the build version of leng, this should be incremented every new release
var BuildVersion = "1.5.3"
var BuildVersion = "1.6.0"

// ConfigVersion returns the version of leng, this should be incremented every time the config changes so leng presents a warning
var ConfigVersion = "1.5.3"
var ConfigVersion = "1.6.0"

// Config holds the configuration parameters
type Config struct {
Expand Down
4 changes: 2 additions & 2 deletions doc/src/Nix.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Please refer to [Configuration](./Configuration.md) for the options you can use
{
inputs = {
# pinned version for safety
leng.url = "github:cottand/leng/v1.5.3";
leng.url = "github:cottand/leng/v1.6.0";
leng.nixpkgs.follows = "nixpkgs";
};
Expand Down Expand Up @@ -52,7 +52,7 @@ Add the following inside your configuration.nix:
{pkgs, lib, ... }: {
imports = [
# import leng module
(builtins.getFlake "github:cottand/leng/v1.5.3").nixosModules.default
(builtins.getFlake "github:cottand/leng/v1.6.0").nixosModules.default
];
# now you can use services.leng!
Expand Down
18 changes: 0 additions & 18 deletions docker/alpine.Dockerfile

This file was deleted.

21 changes: 0 additions & 21 deletions docker/slim.Dockerfile

This file was deleted.

27 changes: 23 additions & 4 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,31 @@
# Build & packaging
## use with `nix build`
packages = rec {
leng = pkgs.buildGo122Module {
leng = pkgs.buildGoModule {
inherit system;
vendorHash = null;
pname = "leng";
version = "1.5.3";
version = "1.6.0";
src = nixpkgs.lib.sources.cleanSource ./.;
ldflags = [ "-s -w" ];
CGO_ENABLED = "0";
# upx does not support darwin
postInstall = if pkgs.lib.strings.hasSuffix "darwin" system then "" else ''
cd $out/bin
${pkgs.upx}/bin/upx -9 -o leng.mini leng
rm leng
mv leng.mini leng
'';
};
leng-container-image = pkgs.dockerTools.buildImage {
name = "leng";
created = "now";
tag = "nix";
copyToRoot = pkgs.buildEnv {
name = "files";
paths = [ leng pkgs.cacert ];
};
config.Entrypoint = [ "${leng}/bin/leng" ];
};
default = leng;
};
Expand All @@ -28,7 +47,7 @@
devShells = rec {
# main development shell
leng = with pkgs; mkShell {
packages = [ fish go_1_21 mdbook ];
packages = [ fish go mdbook ];
# Note that `shellHook` still uses bash syntax. This starts fish, then exists the bash shell when fish exits.
shellHook = "fish && exit";
};
Expand Down Expand Up @@ -98,7 +117,7 @@
## implementation
config = mkIf cfg.enable {
environment = {
etc."leng.toml".source = { blocking.sourcesStore = "/var/lib/leng-sources";} // (toml.generate "leng.toml" cfg.configuration);
etc."leng.toml".source = { blocking.sourcesStore = "/var/lib/leng-sources"; } // (toml.generate "leng.toml" cfg.configuration);
systemPackages = [ cfg.package ];
};

Expand Down
2 changes: 2 additions & 0 deletions logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
Expand Down Expand Up @@ -95,6 +96,7 @@ func parseLogConfig(logConfigString string) (*logConfig, error) {
}

func createLogFile(fileName string) (*os.File, error) {
fileName = filepath.Clean(fileName)
if _, err := os.Stat(fileName); os.IsNotExist(err) {
if _, err := os.Create(fileName); err != nil {
return nil, fmt.Errorf("error creating log file '%s': %s", fileName, err)
Expand Down

0 comments on commit c4063e9

Please sign in to comment.