Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: CI

# Trigger the workflow on all pushes
on:
push:
branches:
- main

concurrency:
group: ${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
packages:
name: Push package to local cache
runs-on: self-hosted
strategy:
matrix:
ghc-version: [ "ghc9101", "ghc982", "ghc964" ]
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Build & test
run: |
# The -L flag outputs build logs to stderr
nix build -L .#${{ matrix.ghc-version }}
- name: Push package to cache
env:
ATTIC_TOKEN: ${{ secrets.ATTIC_SECRET }}
run: |
attic login --set-default public http://192.168.102.136:9200/ "$ATTIC_TOKEN"
attic push public $(nix path-info .#${{ matrix.ghc-version }})
- name: Push package to cachix
# if: github.ref == 'refs/heads/main'
env:
CACHIX_TOKEN: ${{ secrets.CACHIX_SECRET }}
run: |
cachix authtoken $CACHIX_TOKEN
nix path-info .#${{ matrix.ghc-version }} | cachix push clash-lang
devshells:
name: Push Nix developer shell to local cache
runs-on: self-hosted
strategy:
matrix:
ghc-version: [ "ghc9101", "ghc982", "ghc964" ]
steps:
# There's no need to configure Nix, the dockerfile handling the GHA has it done for us!
# If a dependencies are already cached, we can simply re-use them!

- name: Checkout
uses: actions/checkout@v4

- name: Build devshell
run: |
# Since the server is x86_64-linux, we can only build the devshell
# for that
nix build .#devShells.x86_64-linux.${{ matrix.ghc-version }}-full
# Pushes the binaries to the local network
# url: http://192.168.102.136:9200/public
# public key: public:PGGlJMx1gGmU069blMqve8tS1ndzBuriUAwGBHGOo4g=
- name: Push devshell to cache
env:
ATTIC_TOKEN: ${{ secrets.ATTIC_SECRET }}
run: |
attic login --set-default public http://192.168.102.136:9200/ "$ATTIC_TOKEN"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This way, the secret shows up in the process list if you time it right. While the risk of leakage is small, it is poor form. Does attic also accept a token from stdin? Because you might be able to do

attic login --set-default public http://192.168.102.136:9200/ - <<<"$ATTIC_TOKEN"

which, as far as I know, does not leak the token via the process list. My assumption was that a - argument would be interpreted as "take it from stdin", this is pretty standard but not universal.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah it also seems possible without relying on bash features:

printenv ATTIC_TOKEN | attic login --set-default public http://192.168.102.136:9200/ -

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! I wasn't aware that it could leak like that. Sadly it does not support reading from stdin, but we can write to ~/.config/attic/config.toml directly for the meantime.

I have written a small bash script which writes the config file and the CI invokes the bash script. Would that be leak proof?

I have also made the Cachix authentication use environment variables rather than a direct argument as well.

Related Attic PR: zhaofengli/attic#284

attic push public $(nix path-info .#devShells.x86_64-linux.${{ matrix.ghc-version }}-full)
# Pushes the binaries to Cachix
- name: Push devshell to cachix
env:
CACHIX_TOKEN: ${{ secrets.CACHIX_SECRET }}
run: |
cachix authtoken $CACHIX_TOKEN
nix path-info .#devShells.x86_64-linux.${{ matrix.ghc-version }}-full | cachix push clash-lang
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,37 @@ You can also look through Adam Walker's excellent list of [prebuilt Clash circui
# Nix
This project exposes several Nix flake outputs. Most notably the `clash-cores` package, exposed individually or as an overlay (which you need to apply on top of clash-compiler).

## Usage

Contributing to `clash-cores` can be done via the developer shell exposed by the Nix flake. Open a terminal and type: `nix develop`. Optionally a specific GHC version can be selected as well as a `-minimal` or `-full` version. The `-minimal` shell does **NOT** contain the Haskell Language Server, whilst the `-full` shell does. When using the developer shell, do not forget to remove the `cabal.project` file. This file contains a package source and Cabal prioritizes local package sources over Nix sources. Removing the `cabal.project` file should work fine when developing with Nix.

Compiling Clash and all dependencies related to it may take a long time. To remidy long compilation times, you can make use of the publically available cache on Cachix:

### Cachix (binary cache)

Cachix contains all commits on the main branch of `clash-cores` since the cache has been setup. It is recommended to add the publically available cachix cache to your project/computer to minimize the amount of time manually compiling Clash related dependencies.

You can either add user-wide on your local system via `nix.conf` (usually located under `~/.config/nix`, create it if it does not exist):
```conf
extra-substituters = https://clash-lang.cachix.org
extra-trusted-public-keys = clash-lang.cachix.org-1:/2N1uka38B/heaOAC+Ztd/EWLmF0RLfizWgC5tamCBg=
Comment on lines +48 to +49
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't

nix profile install nixpkgs#cachix
cachix use clash-lang

a bit less "intimidating"?

Copy link
Contributor Author

@jaschutte jaschutte Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get where you're coming from, but at the same time why make people install something when you can use Cachix just fine without having the CLI installed? Alternatively it can be listed as 'you can also do this'.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My preference would be to start out with the solution that is the simplest to perform, so cachix use clan-lang. And then make a note "It is not required to use the cachix package for this; alternatively, you can use the following configuration if you would like to avoid installing it:"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a funny divide here because I personally find it simpler not to install the tool at all (unless it's required somewhere else). I never used it, and always added substituters in my config files.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well I can just remember the instructions to install and use cachix, whereas with the other instructions, I'll really need to look up the instructions or an existing deployment and copy-paste. I'm considering "simple" as "an action that is simple to perform for the user", not "my system is reduced to its simplest state".

But I'm fine with any order; I do think it makes sense to document both so people can pick what most fits their life style.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do think it makes sense to document both so people can pick what most fits their life style.

Same!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've included both methods now

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I generally like "simple" instructions with @DigitalBrains1's definition of simple:

I'm considering "simple" as "an action that is simple to perform for the user", not "my system is reduced to its simplest state".

in READMEs. If it's a race between my desktop installing cachix and my slow ass doing a bunch of edits, I know who's going to win.

Anyway, having both is good. Just figured I'd share my POV.

```

Or as part of your `flake.nix` in your local project:
```nix
{
nixConfig = {
extra-substituters = [ "https://clash-lang.cachix.org" ];
extra-trusted-public-keys = [ "clash-lang.cachix.org-1:/2N1uka38B/heaOAC+Ztd/EWLmF0RLfizWgC5tamCBg=" ];
};
description = ...;
inputs = ...;
outputs = ...;
}
```

## As a dependency

You can also add this project as a Nix-dependency. This project depends on `clash-compiler`, the recommended way to add this to your project as a Nix dependency is as follows:

First add `clash-compiler` and `clash-cores` to your flake inputs:
Expand Down