Skip to content

Commit 2e4eedb

Browse files
committed
ci: define behaviour to build and push docker image
1 parent 9d577e8 commit 2e4eedb

File tree

3 files changed

+177
-8
lines changed

3 files changed

+177
-8
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
name: Release Build and Publish Docker image
2+
3+
permissions:
4+
contents: write
5+
pull-requests: read
6+
packages: write
7+
8+
on:
9+
push:
10+
paths:
11+
- "**/*.rs"
12+
- "**/Cargo.toml"
13+
- "Cargo.lock"
14+
- "flake.nix"
15+
workflow_dispatch:
16+
17+
jobs:
18+
generate-matrix:
19+
runs-on: ubuntu-latest
20+
outputs:
21+
arch_list: ${{ steps.generate-arch-list.outputs.arch_list }}
22+
steps:
23+
- uses: actions/checkout@v4
24+
25+
- name: Install Nix
26+
uses: cachix/install-nix-action@v30
27+
with:
28+
nix_path: nixpkgs=channel:nixos-unstable
29+
github_access_token: ${{ secrets.GITHUB_TOKEN }}
30+
extra_nix_config: |
31+
experimental-features = nix-command flakes
32+
33+
- name: Generate Arch List
34+
id: generate-arch-list
35+
run: |
36+
ARCH_LIST=$(nix run .#matrix--quiet)
37+
echo "Generated Archs:"
38+
echo "$ARCH_LIST"
39+
echo "arch_list=$ARCH_LIST" >> $GITHUB_OUTPUT
40+
41+
docker-build:
42+
runs-on: ubuntu-latest
43+
needs: [generate-matrix]
44+
strategy:
45+
fail-fast: false
46+
matrix:
47+
include: ${{ fromJson(needs.generate-matrix.outputs.arch_list) }}
48+
steps:
49+
- uses: actions/checkout@v4
50+
- name: Set Repository Lowercase
51+
run: echo "REPOSITORY=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV
52+
53+
- name: Install Nix
54+
uses: cachix/install-nix-action@v30
55+
with:
56+
nix_path: nixpkgs=channel:nixos-unstable
57+
github_access_token: ${{ secrets.GITHUB_TOKEN }}
58+
extra_nix_config: |
59+
experimental-features = nix-command flakes
60+
61+
- name: Log in to GHCR
62+
uses: docker/login-action@v3
63+
with:
64+
registry: ghcr.io
65+
username: ${{ github.actor }}
66+
password: ${{ secrets.GITHUB_TOKEN }}
67+
68+
- name: Build individual images with Nix
69+
run: |
70+
nix build .#image-${{ matrix.os }}-${{ matrix.arch }}
71+
docker load < ./result
72+
docker tag rsground:${{ matrix.version }} ghcr.io/${{ env.REPOSITORY }}:${{ matrix.version }}-${{ matrix.os }}-${{ matrix.arch }}
73+
74+
docker-manifest:
75+
runs-on: ubuntu-latest
76+
needs: [docker-build]
77+
steps:
78+
- uses: actions/checkout@v4
79+
- name: Install Nix
80+
uses: cachix/install-nix-action@v30
81+
with:
82+
nix_path: nixpkgs=channel:nixos-unstable
83+
extra_nix_config: |
84+
experimental-features = nix-command flakes
85+
- name: Log in to GHCR
86+
uses: docker/login-action@v3
87+
with:
88+
registry: ghcr.io
89+
username: ${{ github.actor }}
90+
password: ${{ secrets.GITHUB_TOKEN }}
91+
- name: Push manifest
92+
run: nix run .#docker-manifest

architectures.nix

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[
2+
# Linux
3+
{ arch = "x86_64"; os = "linux"; }
4+
{ arch = "aarch64"; os = "linux"; }
5+
{ arch = "armv7l"; os = "linux"; }
6+
{ arch = "armv6l"; os = "linux"; }
7+
# { arch = "riscv32"; os = "linux"; }
8+
# { arch = "riscv64"; os = "linux"; }
9+
# MacOS
10+
{ arch = "x86_64"; os = "macos"; }
11+
{ arch = "aarch64"; os = "macos"; }
12+
# Windows
13+
{ arch = "x86_64"; os = "windows"; }
14+
# { arch = "i686"; os = "windows"; }
15+
]

flake.nix

Lines changed: 70 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
pkgs = import nixpkgs {inherit system;};
1717
lib = pkgs.lib;
1818
fenix = fenix-pkg.packages.${system};
19+
architectures = import ./architectures.nix;
1920

2021
rustToolchainDef = {
2122
channel = "1.88.0";
@@ -49,7 +50,9 @@
4950
wasm-pack
5051
];
5152

52-
appPkg = (pkgs.makeRustPlatform {
53+
mkPackage = { os, ... } @ variant: let
54+
crossPkgs = mkCrossPkgs variant;
55+
in (pkgs.makeRustPlatform {
5356
inherit (toolchain) cargo rustc;
5457
}).buildRustPackage (finalAttrs: {
5558
doCheck = false;
@@ -61,7 +64,11 @@
6164
src = ./.;
6265
cargoLock.lockFile = ./Cargo.lock;
6366

64-
env.OPENSSL_NO_VENDOR = 1;
67+
env = {
68+
OPENSSL_NO_VENDOR = 1;
69+
HOST_CC = lib.optionalString (os != "windows") "${pkgs.stdenv.cc.nativePrefix}cc";
70+
TARGET_CC = lib.optionalString (os != "windows") "${crossPkgs.stdenv.cc.targetPrefix}cc";
71+
};
6572

6673
nativeBuildInputs = [pkgs.pkg-config];
6774

@@ -73,20 +80,75 @@
7380
];
7481
});
7582

76-
containerPkg = pkgs.dockerTools.buildLayeredImage {
83+
mkCrossPkgs = { arch, os, ... }: let
84+
cross = arch + "-" + os;
85+
crossSystem = lib.systems.elaborate cross;
86+
in import nixpkgs {
87+
crossSystem = if cross != "x86_64-linux" then crossSystem else null;
88+
localSystem = system;
89+
};
90+
91+
containerPkg = { arch, os, ... } @ variant: let
92+
appPkg = mkPackage variant;
93+
dockerPlatform =
94+
if arch == "x86_64" then "amd64"
95+
else if arch == "aarch64" then "arm64"
96+
else if arch == "armv7l" then "arm"
97+
else if arch == "armv6l" then "arm"
98+
else if arch == "i686" then "386"
99+
else throw "Unsupported arch: ${arch}";
100+
in pkgs.dockerTools.buildLayeredImage {
101+
inherit os;
102+
created = "now";
77103
name = "rsground";
78104
tag = cargoManifest.package.version;
79-
created = "now";
80-
architecture = "amd64";
105+
architecture = dockerPlatform;
81106

82107
contents = [ appPkg ];
83108
config.Cmd = ["/bin/backend"];
84109
};
110+
111+
generatedMatrixJson = builtins.toJSON (lib.flatten (map ({ arch, os, ... }: {
112+
inherit os arch;
113+
package = "${os}-${arch}";
114+
version = cargoManifest.package.version;
115+
}) architectures));
85116
in {
86-
packages.${system} = {
87-
default = appPkg;
88-
image = containerPkg;
117+
apps.${system}.matrix = {
118+
type = "app";
119+
program = toString (pkgs.writeScript "generate-matrix" ''
120+
#!/bin/sh
121+
echo '${generatedMatrixJson}'
122+
'');
89123
};
124+
125+
packages.${system} =
126+
let
127+
perArch =
128+
lib.listToAttrs (map (variant: {
129+
name = "image-${variant.os}-${variant.arch}";
130+
value = containerPkg variant;
131+
}) architectures);
132+
133+
perArchPkgs =
134+
lib.listToAttrs (map (variant: {
135+
name = "backend-${variant.os}-${variant.arch}";
136+
value = mkPackage variant;
137+
}) architectures);
138+
in
139+
perArch // perArchPkgs // {
140+
docker-manifest = pkgs.writeShellScriptBin "docker-manifest" ''
141+
set -euo pipefail
142+
VERSION=${cargoManifest.package.version}
143+
IMAGE="ghcr.io/$REPOSITORY:$VERSION"
144+
145+
docker manifest create "$IMAGE" ${lib.concatMapStringsSep " " (variant:
146+
"--amend ghcr.io/$REPOSITORY:$VERSION-${variant.os}-${variant.arch}"
147+
) architectures}
148+
docker manifest push "$IMAGE"
149+
'';
150+
};
151+
90152
devShells.${system}.default = pkgs.mkShell {
91153
buildInputs =
92154
commonBuildInputs

0 commit comments

Comments
 (0)