Build Mix release with Nix (#2)

* Add initial Nix flake

* Fix `pkgs/live-beats`

Note: Tailwind and ESBuild are omitted for now, as they throw unexpected
Bash errors.

* Build app in CI

* Pin Elixir version

* Add OAuth client secrets to CI

* Add Hex to dev dependencies

* Allow `mix compile` error in CI
This commit is contained in:
Garrett George 2023-03-15 09:57:23 -05:00 committed by GitHub
parent 34e19c187c
commit 34507735a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 822 additions and 1 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
use flake

45
.github/workflows/build.yml vendored Normal file
View file

@ -0,0 +1,45 @@
name: Build
on:
pull_request:
branches:
- '*'
jobs:
build:
name: Build
runs-on: ubuntu-latest
env:
LIVE_BEATS_GITHUB_CLIENT_ID: ${{ secrets.LIVE_BEATS_GITHUB_CLIENT_ID }}
LIVE_BEATS_GITHUB_CLIENT_SECRET: ${{ secrets.LIVE_BEATS_GITHUB_CLIENT_SECRET }}
steps:
- name: Check out repository
uses: actions/checkout@v2
- name: Install Nix
uses: cachix/install-nix-action@v17
with:
# Mostly to avoid GitHub rate limiting
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
# FIXME: results in error: file 'nixpkgs' was not found in the Nix search path (add it using $NIX_PATH or -I)
# - name: Print nixpkgs version
# run: nix-instantiate --eval -E '(import <nixpkgs> {}).lib.version'
- name: Cache Nix derivations
uses: cachix/cachix-action@v12
with:
name: garrettmichaelgeorge-public
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
extraPullNames: nix-community
# FIXME: requires mix deps.get to be run first to avoid the error:
# "the dependency is not available, run "mix deps.get""
# NOTE: this would only work if Elixir is included in the Nix shell
# - run: nix develop --command mix compile
# continue-on-error: true
- run: nix build

11
.gitignore vendored
View file

@ -30,4 +30,13 @@ npm-debug.log
/assets/node_modules/
/priv/uploads
/tmp
/tmp
# Ignore direnv
/.direnv/
# Ignore Nix artifacts
/postgres_data
.nix-mix
.nix-hex
result

43
flake.lock Normal file
View file

@ -0,0 +1,43 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1676283394,
"narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1678449012,
"narHash": "sha256-odpQq99OCjHmWeXk70dWdgphb4cb5stvYlX7YVgAbag=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "b9c00c1d41ccd6385da243415299b39aa73357be",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

54
flake.nix Normal file
View file

@ -0,0 +1,54 @@
{
description = "LiveBeats";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
# pkgs = nixpkgs.legacyPackages.${system};
pkgs = import nixpkgs { inherit system; };
in
rec {
packages = {
live-beats = pkgs.callPackage ./pkgs/live-beats { inherit pkgs self; };
default = packages.live-beats;
};
devShells = {
default = devShells.dev;
dev = import ./pkgs/dev-shell {
inherit pkgs;
db_name = "db_dev";
# MIX_ENV = "dev";
};
# test = import .pkgs/dev-shell {
# inherit pkgs;
# db_name = "db_test";
# MIX_ENV = "test";
# };
# prod = import .pkgs/dev-shell {
# inherit pkgs;
# db_name = "db_prod";
# MIX_ENV = "prod";
# };
};
checks = {
flake-build = packages.default;
test = pkgs.runCommandLocal "test-hello" { } ''
# ${packages.default}/bin/${packages.default.name} > $out
mix test
'';
};
formatter = pkgs.nixpkgs-fmt;
});
}

572
pkgs/deps/default.nix Normal file
View file

@ -0,0 +1,572 @@
{ lib, beamPackages, overrides ? (x: y: { }) }:
let
buildRebar3 = lib.makeOverridable beamPackages.buildRebar3;
buildMix = lib.makeOverridable beamPackages.buildMix;
buildErlangMk = lib.makeOverridable beamPackages.buildErlangMk;
self = packages // (overrides self packages);
packages = with beamPackages; with self; {
castore = buildMix rec {
name = "castore";
version = "0.1.19";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0291pdk3x7qzbv8laris1y90vi7g9akmykd23m2fz0nwlmhh2vp9";
};
beamDeps = [ ];
};
connection = buildMix rec {
name = "connection";
version = "1.1.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1746n8ba11amp1xhwzp38yfii2h051za8ndxlwdykyqqljq1wb3j";
};
beamDeps = [ ];
};
cowboy = buildErlangMk rec {
name = "cowboy";
version = "2.9.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1phv0a1zbgk7imfgcm0dlacm7hbjcdygb0pqmx4s26jf9f9rywic";
};
beamDeps = [ cowlib ranch ];
};
cowboy_telemetry = buildRebar3 rec {
name = "cowboy_telemetry";
version = "0.4.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1pn90is3k9dq64wbijvzkqb6ldfqvwiqi7ymc8dx6ra5xv0vm63x";
};
beamDeps = [ cowboy telemetry ];
};
cowlib = buildRebar3 rec {
name = "cowlib";
version = "2.11.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1ac6pj3x4vdbsa8hvmbzpdfc4k0v1p102jbd39snai8wnah9sgib";
};
beamDeps = [ ];
};
db_connection = buildMix rec {
name = "db_connection";
version = "2.4.2";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0s1nx1gi96r8g7x8y7cklz8z823a6llh4fk996i5xxcr3flkrrag";
};
beamDeps = [ connection telemetry ];
};
decimal = buildMix rec {
name = "decimal";
version = "2.0.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0xzm8hfhn8q02rmg8cpgs68n5jz61wvqg7bxww9i1a6yanf6wril";
};
beamDeps = [ ];
};
ecto = buildMix rec {
name = "ecto";
version = "3.9.1";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "015k9vsngl01zzj5p9iw439rsbcjdjrq2bzryy8gg3b46vbv62y8";
};
beamDeps = [ decimal jason telemetry ];
};
ecto_network = buildMix rec {
name = "ecto_network";
version = "1.3.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1gb550dz319wcr77dpgd1696k52l1zx84z59bvmfhdr8xx35wfh5";
};
beamDeps = [ ecto_sql phoenix_html postgrex ];
};
ecto_sql = buildMix rec {
name = "ecto_sql";
version = "3.9.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0lv4b45j0bja98q0qhlp97a7zvb0g7x2bgkqr721m2rv0whggwx8";
};
beamDeps = [ db_connection ecto postgrex telemetry ];
};
esbuild = buildMix rec {
name = "esbuild";
version = "0.5.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1rgzjjb0j3m0xz8gs112dydfz7m5brlpfm2qmz7w8qyr6ars10zi";
};
beamDeps = [ castore ];
};
file_system = buildMix rec {
name = "file_system";
version = "0.2.10";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1p0myxmnjjds8bbg69dd6fvhk8q3n7lb78zd4qvmjajnzgdmw6a1";
};
beamDeps = [ ];
};
finch = buildMix rec {
name = "finch";
version = "0.13.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1k56zfbadpppn8flavb4aczq0npcqnlhg993l51c1k8dw76pv5a9";
};
beamDeps = [ castore mime mint nimble_options nimble_pool telemetry ];
};
floki = buildMix rec {
name = "floki";
version = "0.34.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1769xg2sqdh6s1j06l7gi98iy35ri79xk6sq58rh1phdyi1ryflw";
};
beamDeps = [ ];
};
gettext = buildMix rec {
name = "gettext";
version = "0.20.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0ggb458h60ch3inndqp9xhbailhb0jkq3xnp85sa94sy8dvv20qw";
};
beamDeps = [ ];
};
heroicons = buildMix rec {
name = "heroicons";
version = "0.2.4";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0a414v11xmjv37q4qgx2g6sgdwzvq8zahz948dwv7bfaivf52v3x";
};
beamDeps = [ phoenix_html ];
};
hpax = buildMix rec {
name = "hpax";
version = "0.1.2";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "04wci9ifsfyd2pbcrnpgh2aq0a8fi1lpkrzb91kz3x93b8yq91rc";
};
beamDeps = [ ];
};
jason = buildMix rec {
name = "jason";
version = "1.4.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0891p2yrg3ri04p302cxfww3fi16pvvw1kh4r91zg85jhl87k8vr";
};
beamDeps = [ decimal ];
};
libcluster = buildMix rec {
name = "libcluster";
version = "3.3.1";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "162kkrg0g6grvqrisi4dmvkiwp4lxgk4bz507wgy116dq5iwlxdm";
};
beamDeps = [ jason ];
};
mime = buildMix rec {
name = "mime";
version = "2.0.3";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0szzdfalafpawjrrwbrplhkgxjv8837mlxbkpbn5xlj4vgq0p8r7";
};
beamDeps = [ ];
};
mint = buildMix rec {
name = "mint";
version = "1.4.2";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "106x9nmzi4ji5cqaddn76pxiyxdihk12z2qgszcdgd2rrjxsaxff";
};
beamDeps = [ castore hpax ];
};
nimble_options = buildMix rec {
name = "nimble_options";
version = "0.4.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0bd0pi3sij9vxhiilv25x6n3jls75g3b38rljvm1x896ycd1qw76";
};
beamDeps = [ ];
};
nimble_pool = buildMix rec {
name = "nimble_pool";
version = "0.2.6";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0gv59waa505mz2gi956sj1aa6844c65w2dp2qh2jfgsx15am0w8w";
};
beamDeps = [ ];
};
phoenix = buildMix rec {
name = "phoenix";
version = "1.7.0-rc.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0n98z312xigx2cinipbzkgsi9w095amyci1y8l5gqjhqamn3yl7d";
};
beamDeps = [ castore jason phoenix_pubsub phoenix_template plug plug_cowboy plug_crypto telemetry websock_adapter ];
};
phoenix_ecto = buildMix rec {
name = "phoenix_ecto";
version = "4.4.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1h9wnjmxns8y8dsr0r41ks66gscaqm7ivk4gsh5y07nkiralx1h9";
};
beamDeps = [ ecto phoenix_html plug ];
};
phoenix_html = buildMix rec {
name = "phoenix_html";
version = "3.2.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0ky5idgid1psz6hmh2b2kmj6n974axww74hrxwv02p6jasx9gv1n";
};
beamDeps = [ plug ];
};
phoenix_live_dashboard = buildMix rec {
name = "phoenix_live_dashboard";
version = "0.7.2";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1dq5vj1a6fzclr3fwj7y8rg2xq3yigvgqc3aaq664fvs7h3dypqf";
};
beamDeps = [ ecto mime phoenix_live_view telemetry_metrics ];
};
phoenix_live_reload = buildMix rec {
name = "phoenix_live_reload";
version = "1.4.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0vxfv9ndrcmlwwfnjgcn3p1b9drlf8v8bxb8b75n2fqisb10zgxy";
};
beamDeps = [ file_system phoenix ];
};
phoenix_live_view = buildMix rec {
name = "phoenix_live_view";
version = "0.18.3";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1cl1rsfhg4aqazd2nswb3c3an04g7hwnacq8nzf1gq36m1vm3168";
};
beamDeps = [ jason phoenix phoenix_html phoenix_template telemetry ];
};
phoenix_pubsub = buildMix rec {
name = "phoenix_pubsub";
version = "2.1.1";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1nfqrmbrq45if9pgk6g6vqiply2sxc40is3bfanphn7a3rnpqdl1";
};
beamDeps = [ ];
};
phoenix_template = buildMix rec {
name = "phoenix_template";
version = "1.0.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0ms39n5s6kh532s20yxzj7sh0rz5lslh09ibq5j21lkglacny1hv";
};
beamDeps = [ phoenix_html ];
};
plug = buildMix rec {
name = "plug";
version = "1.14.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "056wkb1b17mh5h9ncs2vbswvpjsm2iqc580nmyrvgznlqwr080mz";
};
beamDeps = [ mime plug_crypto telemetry ];
};
plug_cowboy = buildMix rec {
name = "plug_cowboy";
version = "2.6.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "19jgv5dm53hv5aqgxxzr3fnrpgfll9ics199swp6iriwfl5z4g07";
};
beamDeps = [ cowboy cowboy_telemetry plug ];
};
plug_crypto = buildMix rec {
name = "plug_crypto";
version = "1.2.3";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "18plj2idhp3f0nmqyjjf2rzj849l3br0797m8ln20p5dqscj0rxm";
};
beamDeps = [ ];
};
postgrex = buildMix rec {
name = "postgrex";
version = "0.16.5";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1s5jbwfzsdsyvlwgx3bqlfwilj2c468wi3qxq0c2d23fvhwxdspd";
};
beamDeps = [ connection db_connection decimal jason ];
};
ranch = buildRebar3 rec {
name = "ranch";
version = "1.8.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1rfz5ld54pkd2w25jadyznia2vb7aw9bclck21fizargd39wzys9";
};
beamDeps = [ ];
};
swoosh = buildMix rec {
name = "swoosh";
version = "1.8.2";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1nxpcwq7ynvqjp65z544dvdfw7jx9k0m58w4kb0bdbdg1rsvln6h";
};
beamDeps = [ cowboy finch jason mime plug_cowboy telemetry ];
};
tailwind = buildMix rec {
name = "tailwind";
version = "0.1.9";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "02vdlm3lrigk3f1axr1hnv1fsb2d5ggz5d9v67naln6415vzh4wj";
};
beamDeps = [ castore ];
};
telemetry = buildRebar3 rec {
name = "telemetry";
version = "1.1.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0j6zq3y7xz768djz25x55gampyhd9nv6ax9dzx67f52nyyhv49xp";
};
beamDeps = [ ];
};
telemetry_metrics = buildMix rec {
name = "telemetry_metrics";
version = "0.6.1";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1iilk2n75kn9i95fdp8mpxvn3rcn3ghln7p77cijqws13j3y1sbv";
};
beamDeps = [ telemetry ];
};
telemetry_poller = buildRebar3 rec {
name = "telemetry_poller";
version = "1.0.0";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "0vjgxkxn9ll1gc6xd8jh4b0ldmg9l7fsfg7w63d44gvcssplx8mk";
};
beamDeps = [ telemetry ];
};
websock = buildMix rec {
name = "websock";
version = "0.4.3";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1krralrzzpcf5l3kn3qgsvz8s8j59bn0pmr57qyzshsz61gxhkay";
};
beamDeps = [ ];
};
websock_adapter = buildMix rec {
name = "websock_adapter";
version = "0.4.5";
src = fetchHex {
pkg = "${name}";
version = "${version}";
sha256 = "1j74my5zd5nwafg0j6zr4nl4g8jj13zd8vs295820g3hgvf1560x";
};
beamDeps = [ plug plug_cowboy websock ];
};
};
in
self

View file

@ -0,0 +1,53 @@
{ pkgs, db_name }:
let
erlang = pkgs.beam.packages.erlangR24;
elixir = erlang.elixir.override {
version = "1.12.3";
sha256 = "Jo9ZC5cSBVpjVnGZ8tEIUKOhW9uvJM/h84+VcnrT0R0=";
};
in
pkgs.mkShell {
name = "live-beats-shell";
# inherit MIX_ENV;
buildInputs = [
elixir
erlang.elixir_ls
erlang.hex
pkgs.mix2nix
pkgs.postgresql_14
pkgs.nixpkgs-fmt
pkgs.nixpkgs-lint
pkgs.rnix-lsp
pkgs.overmind
pkgs.nodePackages.tailwindcss
] ++ pkgs.lib.optional pkgs.stdenv.isLinux pkgs.inotify-tools
++ pkgs.lib.optionals pkgs.stdenv.isDarwin
(with pkgs.darwin.apple_sdk.frameworks; [
CoreFoundation
CoreServices
]);
shellHook = ''
# Generic shell variables
export LANG=en_US.utf-8
export ERL_AFLAGS="-kernel shell_history enabled"
export PHX_HOST=localhost
export FLY_APP_NAME=live_beats
export RELEASE_COOKIE=UnsecureTestOnlyCookie
# Postgres
export DATABASE_URL="ecto://postgres:postgres@localhost:5432/live_beats_prod"
export POOL_SIZE=15
# Scope Mix and Hex to the project directory
mkdir -p .nix-mix
mkdir -p .nix-hex
export MIX_HOME=$PWD/.nix-mix
export HEX_HOME=$PWD/.nix-hex
export PATH=$MIX_HOME/bin:$PATH
export PATH=$HEX_HOME/bin:$PATH
'';
}

View file

@ -0,0 +1,44 @@
{ self, pkgs }:
with pkgs;
let
beamPackages = beam.packagesWith beam.interpreters.erlangR24;
in
beamPackages.mixRelease rec {
pname = "live-beats";
version = "0.0.0";
# "self" defaults to the root of your project.
# amend the path if it is non-standard with `self + "/src";`, for example
src = self;
MIX_ENV = "prod";
LANG = "en_US.UTF-8";
LANGUAGE = "en_US:en";
LC_ALL = "en_US.UTF-8";
ECTO_IPV6 = "true";
ERL_AFLAGS = "-proto_dist inet6_tcp";
mixNixDeps = import ./../deps { inherit lib beamPackages; };
buildInputs = [
esbuild
nodePackages.tailwindcss
];
MIX_ESBUILD_PATH = esbuild;
MIX_TAILWIND_PATH = nodePackages.tailwindcss;
# For phoenix framework you can uncomment the lines below.
# For external task you need a workaround for the no deps check flag.
# https://github.com/phoenixframework/phoenix/issues/2690
# You can also add any post-build steps here. It's just bash!
preBuild = ''
# TODO: fix tailwind and esbuild
# mix do deps.loadpaths --no-deps-check, tailwind default --minify
# mix do deps.loadpaths --no-deps-check, esbuild default --minify
mix phx.digest --no-deps-check
'';
}