Skip to content

CI (nix)

CI (nix) #16029

Workflow file for this run

# This is a basic workflow to help you get started with Actions
name: "CI (nix)"
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the "main" branch and release tags
push:
branches: [ "main", "master", "devel", "releases/v*" ]
tags:
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
pull_request:
branches: [ "main", "master", "devel", "releases/v*" ]
merge_group:
branches: [ "main", "master", "devel", "releases/v*" ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# https://stackoverflow.com/questions/66335225/how-to-cancel-previous-runs-in-the-pr-when-you-push-new-commitsupdate-the-curre
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
self-care:
name: Flake self-check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check Nix flake inputs
uses: DeterminateSystems/flake-checker-action@v7
with:
fail-mode: true
nixpkgs-keys: nixpkgs
lint:
name: "Lint"
runs-on: [self-hosted, linux]
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v26
with:
nix_path: nixpkgs=channel:nixos-23.11
extra_nix_config: |
connect-timeout = 15
stalled-download-timeout = 15
- uses: cachix/cachix-action@v14
with:
name: fedimint
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
continue-on-error: true
# run the same check that git `pre-commit` hook would, just in case
- name: Commit check
run: nix develop --ignore-environment .#lint --command ./misc/git-hooks/pre-commit
- name: Check udeps
run: nix build -L .#nightly.test.workspaceCargoUdeps
- name: Check `nix flake show`
run: nix flake show .#
shell:
if: github.repository == 'fedimint/fedimint'
strategy:
matrix:
host:
- linux
- macos
include:
- host: linux
runs-on: [self-hosted, linux]
build-in-pr: false
timeout: 30
- host: macos
runs-on: macos-14
build-in-pr: false
timeout: 30
name: "Dev Shell on ${{ matrix.host }}"
runs-on: ${{ matrix.runs-on }}
timeout-minutes: ${{ matrix.timeout }}
steps:
- uses: actions/checkout@v4
if: github.event_name != 'pull_request' || matrix.build-in-pr
- uses: cachix/install-nix-action@v26
if: github.event_name != 'pull_request' || matrix.build-in-pr
with:
nix_path: nixpkgs=channel:nixos-23.11
extra_nix_config: |
connect-timeout = 15
stalled-download-timeout = 15
- uses: cachix/cachix-action@v14
if: github.event_name != 'pull_request' || matrix.build-in-pr
with:
name: fedimint
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
continue-on-error: true
- name: Build dev shell
if: github.event_name != 'pull_request' || matrix.build-in-pr
run: nix develop -L -c true
build:
if: github.repository == 'fedimint/fedimint'
strategy:
matrix:
host:
- linux
- macos
include:
- host: linux
runs-on: [self-hosted, linux]
build-in-pr: true
timeout: 90
run-tests: true
- host: macos
runs-on: macos-14
build-in-pr: false
# TODO: Too slow; see https://github.com/actions/runner-images/issues/1336
timeout: 75
run-tests: false
name: "Build on ${{ matrix.host }}"
runs-on: ${{ matrix.runs-on }}
timeout-minutes: ${{ matrix.timeout }}
steps:
- uses: actions/checkout@v4
if: github.event_name != 'pull_request' || matrix.build-in-pr
- uses: cachix/install-nix-action@v26
if: github.event_name != 'pull_request' || matrix.build-in-pr
with:
nix_path: nixpkgs=channel:nixos-23.11
extra_nix_config: |
connect-timeout = 15
stalled-download-timeout = 15
- uses: cachix/cachix-action@v14
if: github.event_name != 'pull_request' || matrix.build-in-pr
with:
name: fedimint
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
continue-on-error: true
- name: Build workspace
if: github.event_name != 'pull_request' || matrix.build-in-pr
run: nix build -L .#ci.workspaceBuild
- name: Clippy workspace
if: github.event_name != 'pull_request' || matrix.build-in-pr
run: nix build -L .#ci.workspaceClippy
- name: Run cargo doc
if: (github.event_name != 'pull_request' || matrix.build-in-pr) && (matrix.host != 'macos')
run: nix build -L .#ci.workspaceDoc
- name: Test docs
if: (github.event_name != 'pull_request' || matrix.build-in-pr) && (matrix.host != 'macos')
run: nix build -L .#ci.workspaceTestDoc
- name: Tests
if: (github.event_name != 'pull_request' || matrix.build-in-pr) && matrix.run-tests
run: |
nix build -L .#wasm32-unknown.ci.ciTestAll
- name: Tests (5 times more)
if: github.event_name == 'merge_group' && matrix.run-tests
run: |
nix build -L .#wasm32-unknown.ci.ciTestAll5Times
- name: Wasm Tests
if: (github.event_name != 'pull_request' || matrix.build-in-pr) && matrix.run-tests && (matrix.host != 'macos')
run: nix build -L .#wasm32-unknown.ci.wasmTest
audit:
if: github.repository == 'fedimint/fedimint'
name: "Audit"
runs-on: [self-hosted, linux]
timeout-minutes: 10
# sometimes we can't fix these immediately, yet
# we don't want to stop the world because of it
continue-on-error: true
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v26
with:
nix_path: nixpkgs=channel:nixos-23.11
extra_nix_config: |
connect-timeout = 15
stalled-download-timeout = 15
- uses: cachix/cachix-action@v14
with:
name: fedimint
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
continue-on-error: true
- name: Run cargo audit
run: |
nix flake update advisory-db
nix build -L .#ci.cargoAudit
- name: Run cargo deny
run: |
nix build -L .#ci.cargoDeny
# Code Coverage will build using a completely different profile (neither debug/release)
# Which means we can not reuse much from `build` job. Might as well run it as another
# build in parallel
ccov:
if: github.repository == 'fedimint/fedimint'
name: "Code coverage"
runs-on: [self-hosted, linux]
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v26
with:
nix_path: nixpkgs=channel:nixos-23.11
extra_nix_config: |
connect-timeout = 15
stalled-download-timeout = 15
- uses: cachix/cachix-action@v14
with:
name: fedimint
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
continue-on-error: true
- name: Validate codecov.yaml configuration
run: nix run nixpkgs#curl -- --fail-with-body -X POST --data-binary @.codecov.yml https://codecov.io/validate
- name: Build and run tests with Code Coverage
run: nix build -L .#ci.workspaceTestCov
- name: Ensure lcov.info exists
run: test -f result/lcov.info
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: result/lcov.info
- name: Build and run tests with Code Coverage (5 times more)
if: github.event_name == 'merge_group'
run: nix build -L .#ci.workspaceTest5TimesCov
cross:
name: "Cross-compile on ${{ matrix.host }} to ${{ matrix.toolchain }}"
needs: [lint, shell]
strategy:
matrix:
host:
- linux
- macos
toolchain:
- aarch64-android
- armv7-android
- x86_64-android
- wasm32-unknown
include:
- host: linux
runs-on: [self-hosted, linux]
build-in-pr: true
# TODO: debugging network issues, should reduce to 20 minutes
# https://github.com/fedimint/fedimint/issues/4488
timeout: 60
- host: macos
runs-on: macos-14
build-in-pr: false
# TODO: Too slow; see https://github.com/actions/runner-images/issues/1336
timeout: 120
exclude:
# there's not enough macos runners available for our CI, so test only the more important cross-compilation toolchains
# if they work, rest probably works as well
- host: macos
toolchain: armv7-android
- host: macos
toolchain: x86_64-android
runs-on: ${{ matrix.runs-on }}
timeout-minutes: ${{ matrix.timeout }}
steps:
- uses: actions/checkout@v4
if: github.event_name != 'pull_request' || matrix.build-in-pr
- uses: cachix/install-nix-action@v26
if: github.event_name != 'pull_request' || matrix.build-in-pr
with:
nix_path: nixpkgs=channel:nixos-23.11
extra_nix_config: |
connect-timeout = 15
stalled-download-timeout = 15
- uses: cachix/cachix-action@v14
if: github.event_name != 'pull_request' || matrix.build-in-pr
with:
name: fedimint
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
continue-on-error: true
- name: Build client packages for ${{ matrix.toolchain }}
if: github.event_name != 'pull_request' || matrix.build-in-pr
run: |
nix build -L .#ci.client-pkgs
containers:
if: github.repository == 'fedimint/fedimint'
name: "Containers"
runs-on: [self-hosted, linux]
timeout-minutes: 60
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Prepare
uses: ./.github/actions/prepare
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v26
with:
nix_path: nixpkgs=channel:nixos-23.11
extra_nix_config: |
connect-timeout = 15
stalled-download-timeout = 15
- uses: cachix/cachix-action@v14
with:
name: fedimint
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
continue-on-error: true
- name: Build fedimintd container
run: |
if [ "$GITHUB_EVENT_NAME" == "pull_request" ] || [ "$GITHUB_EVENT_NAME" == "merge_group" ]; then
nix build -L .#ci.container.fedimintd
else
nix build -L .#container.fedimintd
fi
echo "fedimintd_container_tag=$(docker load < result | awk '{ print $3 }')" >> $GITHUB_ENV
- name: Build fedimint-cli container
run: |
if [ "$GITHUB_EVENT_NAME" == "pull_request" ] || [ "$GITHUB_EVENT_NAME" == "merge_group" ]; then
nix build -L .#ci.container.fedimint-cli
else
nix build -L .#container.fedimint-cli
fi
echo "fedimint_cli_container_tag=$(docker load < result | awk '{ print $3 }')" >> $GITHUB_ENV
- name: Build gatewayd container
run: |
if [ "$GITHUB_EVENT_NAME" == "pull_request" ] || [ "$GITHUB_EVENT_NAME" == "merge_group" ]; then
nix build -L .#ci.container.gatewayd
else
nix build -L .#container.gatewayd
fi
echo "gatewayd_container_tag=$(docker load < result | awk '{ print $3 }')" >> $GITHUB_ENV
- name: Build gateway-cli container
run: |
if [ "$GITHUB_EVENT_NAME" == "pull_request" ] || [ "$GITHUB_EVENT_NAME" == "merge_group" ]; then
nix build -L .#ci.container.gateway-cli
else
nix build -L .#container.gateway-cli
fi
echo "gateway-cli_container_tag=$(docker load < result | awk '{ print $3 }')" >> $GITHUB_ENV
- name: Build devtools container
run: |
if [ "$GITHUB_EVENT_NAME" == "pull_request" ] || [ "$GITHUB_EVENT_NAME" == "merge_group" ]; then
nix build -L .#ci.container.devtools
else
nix build -L .#container.devtools
fi
echo "devtools_container_tag=$(docker load < result | awk '{ print $3 }')" >> $GITHUB_ENV
- name: Login to Docker Hub
if: github.ref == 'refs/heads/master' || github.ref_type == 'tag'
uses: docker/login-action@v3
with:
username: fedimint
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Publish
if: github.ref == 'refs/heads/master'
run: |
nix_tag=${{ env.fedimintd_container_tag }} && hub_tag="fedimint/fedimintd:${LAST_COMMIT_SHA}" && docker tag "$nix_tag" "$hub_tag" && docker push "$hub_tag"
nix_tag=${{ env.fedimint_cli_container_tag }} && hub_tag="fedimint/fedimint-cli:${LAST_COMMIT_SHA}" && docker tag "$nix_tag" "$hub_tag" && docker push "$hub_tag"
nix_tag=${{ env.gatewayd_container_tag }} && hub_tag="fedimint/gatewayd:${LAST_COMMIT_SHA}" && docker tag "$nix_tag" "$hub_tag" && docker push "$hub_tag"
nix_tag=${{ env.gateway-cli_container_tag }} && hub_tag="fedimint/gateway-cli:${LAST_COMMIT_SHA}" && docker tag "$nix_tag" "$hub_tag" && docker push "$hub_tag"
nix_tag=${{ env.devtools_container_tag }} && hub_tag="fedimint/devtools:${LAST_COMMIT_SHA}" && docker tag "$nix_tag" "$hub_tag" && docker push "$hub_tag"
- name: Publish master tag
if: github.ref == 'refs/heads/master'
run: |
nix_tag=${{ env.fedimintd_container_tag }} && hub_tag="fedimint/fedimintd:master" && docker tag "$nix_tag" "$hub_tag" && docker push "$hub_tag"
nix_tag=${{ env.fedimint_cli_container_tag }} && hub_tag="fedimint/fedimint-cli:master" && docker tag "$nix_tag" "$hub_tag" && docker push "$hub_tag"
nix_tag=${{ env.gatewayd_container_tag }} && hub_tag="fedimint/gatewayd:master" && docker tag "$nix_tag" "$hub_tag" && docker push "$hub_tag"
nix_tag=${{ env.gateway-cli_container_tag }} && hub_tag="fedimint/gateway-cli:master" && docker tag "$nix_tag" "$hub_tag" && docker push "$hub_tag"
nix_tag=${{ env.devtools_container_tag }} && hub_tag="fedimint/devtools:master" && docker tag "$nix_tag" "$hub_tag" && docker push "$hub_tag"
- name: Publish tagged release
if: github.ref_type == 'tag'
run: |
nix_tag=${{ env.fedimintd_container_tag }} && hub_tag="fedimint/fedimintd:${GITHUB_REF_NAME}" && docker tag "$nix_tag" "$hub_tag" && docker push "$hub_tag"
nix_tag=${{ env.fedimint_cli_container_tag }} && hub_tag="fedimint/fedimint-cli:${GITHUB_REF_NAME}" && docker tag "$nix_tag" "$hub_tag" && docker push "$hub_tag"
nix_tag=${{ env.gatewayd_container_tag }} && hub_tag="fedimint/gatewayd:${GITHUB_REF_NAME}" && docker tag "$nix_tag" "$hub_tag" && docker push "$hub_tag"
nix_tag=${{ env.gateway-cli_container_tag }} && hub_tag="fedimint/gateway-cli:${GITHUB_REF_NAME}" && docker tag "$nix_tag" "$hub_tag" && docker push "$hub_tag"
nix_tag=${{ env.devtools_container_tag }} && hub_tag="fedimint/devtools:${GITHUB_REF_NAME}" && docker tag "$nix_tag" "$hub_tag" && docker push "$hub_tag"
pkgs:
if: github.repository == 'fedimint/fedimint' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/releases') || github.ref_type == 'tag')
name: "Release packages: ${{ matrix.build.flake-output }}"
strategy:
matrix:
build:
- flake-output: fedimint-pkgs
bins: fedimintd,fedimint-cli,fedimint-dbtool
deb: fedimint
- flake-output: gateway-pkgs
bins: gateway-cli,gatewayd,gateway-cln-extension
deb: fedimint-gateway
runs-on: [self-hosted, linux]
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v26
with:
nix_path: nixpkgs=channel:nixos-23.11
extra_nix_config: |
connect-timeout = 15
stalled-download-timeout = 15
- uses: cachix/cachix-action@v14
with:
name: fedimint
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
continue-on-error: true
- name: Set BUILD_ID to tag or commit hash
run: |
if [[ $GITHUB_REF_TYPE == "tag" ]]; then
echo "BUILD_ID=${GITHUB_REF_NAME}" >> $GITHUB_ENV
else
echo "BUILD_ID=${GITHUB_SHA}" >> $GITHUB_ENV
fi
- name: Build ${{ matrix.build.flake-output }}
run: |
nix build -L .#${{ matrix.build.flake-output }}
mkdir -p bins
bins="${{ matrix.build.bins }}"
for bin in ${bins//,/ } ; do
if [[ $GITHUB_REF_TYPE == "tag" ]]; then
nix build -L .#$bin
cachix push fedimint -c 8 -j 8 $(nix-store --query --references $(readlink -f result)) $(readlink -f result)
cachix pin fedimint "fedimint-release-$bin:$BUILD_ID" $(readlink -f result)
fi
nix bundle --bundler .# .#$bin -o "bins/$bin-$BUILD_ID" && sha256sum "bins/$bin-$BUILD_ID"
done
- name: Check version ${{ matrix.build.bins }}
run: |
bins="${{ matrix.build.bins }}"
for bin in ${bins//,/ } ; do
nix run .#$bin version-hash && echo "$GITHUB_SHA" && test "$(nix run .#$bin version-hash)" = "${GITHUB_SHA}"
done
- name: Check sha256sum ${{ matrix.build.bins }}
run: |
bins="${{ matrix.build.bins }}"
for bin in ${bins//,/ } ; do
nix build -L .#$bin && sha256sum "./result/bin/$bin"
done
- name: Upload Binaries
uses: actions/upload-artifact@v4
with:
name: "${{ matrix.build.flake-output}}-linux-x86_64"
path: "bins/**"
- name: Release Binaries
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: "bins/**"
- name: Build DEB package
run: |
bins="${{ matrix.build.bins }}"
for bin in ${bins//,/ } ; do
nix bundle -L --bundler .#toDEB --accept-flake-config -o debs/$bin .#$bin
# workaround: https://github.com/actions/upload-artifact/issues/92
cp -a debs/$bin/*.deb debs/
done
- name: Build RPM package
run: |
bins="${{ matrix.build.bins }}"
for bin in ${bins//,/ } ; do
nix bundle -L --bundler .#toRPM --accept-flake-config -o rpms/$bin .#$bin
# workaround: https://github.com/actions/upload-artifact/issues/92
cp -a rpms/$bin/*.rpm rpms/
done
- name: Upload DEB packages
uses: actions/upload-artifact@v4
with:
name: "${{ matrix.build.flake-output }}-deb-bundle"
path: "debs/**.deb"
- name: Release DEB packages
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: "debs/**.deb"
- name: Upload RPM packages
uses: actions/upload-artifact@v4
with:
name: "${{ matrix.build.flake-output }}-rpm-bundle"
path: "rpms/**.rpm"
- name: Release RPM packages
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: "rpms/**.rpm"
status:
name: Status
needs: [lint, shell, build, cross, ccov, containers, pkgs]
if: ${{ always() }}
runs-on: [self-hosted, linux]
steps:
- name: Check status of all jobs
if: >-
${{
contains(needs.*.result, 'failure') ||
contains(needs.*.result, 'cancelled')
}}
run: exit 1
notifications:
if: always() && github.repository == 'fedimint/fedimint' && github.event_name != 'merge_group'
name: "Notifications"
timeout-minutes: 1
runs-on: [self-hosted, linux]
# note: we don't depend on `audit` because it will
# be often broken, and we can't fix it immediately
needs: [ lint, build, shell, cross, ccov, containers, pkgs ]
steps:
- name: Discord notifications on failure
# https://stackoverflow.com/a/74562058/134409
if: ${{ always() && contains(needs.*.result, 'failure') }}
# https://github.com/marketplace/actions/actions-status-discord
uses: sarisia/actions-status-discord@v1
with:
webhook: ${{ secrets.DISCORD_WEBHOOK }}
# current job is a success, but that's not what we're interested in
status: failure