adjust to attic

This commit is contained in:
Robin Appelman 2023-05-23 20:33:17 +02:00
commit 3902108104
11 changed files with 243 additions and 148 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
use flake

View file

@ -1,4 +1,4 @@
name: "cachix-action test"
name: "attic-action test"
on:
pull_request:
push:
@ -7,10 +7,7 @@ on:
jobs:
public-cache:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- run: yarn install --frozen-lockfile
@ -21,15 +18,13 @@ jobs:
- name: Test public cache
uses: ./
with:
name: cachix-action
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
name: attic-action
instance: https://cache.icewind.me
authToken: '${{ secrets.ATTIC_TOKEN }}'
- run: nix-build test.nix
public-cache-no-signing-key:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
public-cache-no-key:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- run: yarn install --frozen-lockfile
@ -38,15 +33,12 @@ jobs:
- name: Test public cache no signing key
uses: ./
with:
name: cachix-action
name: attic-action
instance: https://cache.icewind.me
- run: nix-build test.nix
private-cache:
if: ${{ github.ref == 'refs/heads/master' }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- run: yarn install --frozen-lockfile
@ -55,34 +47,13 @@ jobs:
- name: Test private cache
uses: ./
with:
name: cachix-action-private
signingKey: '${{ secrets.CACHIX_SIGNING_KEY_PRIVATE }}'
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- run: nix-build test.nix
installCommand:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- run: yarn install --frozen-lockfile
- run: yarn build
- uses: cachix/install-nix-action@v20
- name: Test private cache
uses: ./
with:
name: cachix-action
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
installCommand: 'nix-env -j8 -f https://cachix.org/api/v1/install -iA cachix'
name: attic-action-private
instance: https://cache.icewind.me
authToken: '${{ secrets.ATTIC_TOKEN }}'
- run: nix-build test.nix
nix-master:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Install Nix
@ -96,6 +67,7 @@ jobs:
- name: Test public cache
uses: ./
with:
name: cachix-action
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
name: attic-action
instance: https://cache.icewind.me
authToken: '${{ secrets.ATTIC_TOKEN }}'
- run: nix-build test.nix

2
.gitignore vendored
View file

@ -94,3 +94,5 @@ typings/
# Skip the lib folder
lib/
.direnv

View file

@ -1,52 +1,5 @@
# cachix-action
# attic-action
![github actions badge](https://github.com/cachix/cachix-action/workflows/cachix-action%20test/badge.svg)
![github actions badge](https://github.com/icewind1991/attic-action/workflows/attic-action%20test/badge.svg)
One nice benefit of Nix is that CI can build and cache developer environments for every project on every branch using binary caches.
Another important aspect of CI is the feedback loop of how many minutes does the build take to finish.
With a simple configuration using Cachix, youll never have to build any derivation twice and share them with all your developers.
After each job, just built derivations are pushed to your binary cache.
Before each job, derivations to be built are first substituted (if they exist) from your binary cache.
## Getting started
Follow [Continuous Integration with GitHub Actions](https://nix.dev/tutorials/nixos/build-and-deploy/continuous-integration-github-actions) tutorial.
See [action.yml](action.yml) for all options.
## Security
Cachix auth token and signing key need special care as they give read and write access to your caches.
[As per GitHub Actions' security model](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets#using-encrypted-secrets-in-a-workflow):
> Anyone with write access to a repository can create, read, and use secrets.
Which means all developers with write/push access can read your secrets and write to your cache.
Pull requests do not have access to secrets so read access to a public binary cache will work,
but pushing will be disabled since there is no signing key.
Note that malicious code submitted via a pull request can, once merged into `master`, reveal the tokens.
## Hacking
Install the dependencies
```bash
$ yarn install
```
Build the typescript
```bash
$ yarn build
```
Run the tests :heavy_check_mark:
```bash
$ yarn test
```
Github action to use [attic](https://github.com/zhaofengli/attic) for caching.

View file

@ -1,26 +1,27 @@
name: 'Cachix'
description: 'nix-build with the help of caching to Cachix'
author: 'Domen Kožar'
name: 'Attic'
description: 'nix-build with the help of caching to Attic'
author: 'Robin Appelman'
inputs:
name:
description: 'Name of a cachix cache to push and pull/substitute'
description: 'Name of a attic cache to push and pull/substitute'
required: true
instance:
description: 'Url of a attic instance to push and pull/substitute'
required: true
extraPullNames:
description: 'Comma-separated list of names for extra cachix caches to pull/substitute'
description: 'Comma-separated list of names for extra attic caches to pull/substitute'
authToken:
description: 'Authentication token for Cachix, needed for private cache access or to push using an Auth Token'
signingKey:
description: 'Signing key secret retrieved after creating binary cache on https://cachix.org'
description: 'Authentication token for Attic, needed for private cache access or to push using an Auth Token'
skipPush:
description: 'Set to true to disable pushing build results to the cache'
pathsToPush:
description: 'Whitespace-separated list of paths to push. Leave empty to push every build result.'
pushFilter:
description: 'Ignored if pathsToPush is set. Regular expression to exclude derivations for the cache push, for example "(-source$|nixpkgs\.tar\.gz$)". Warning: this filter does not guarantee it will not get pushed in case the path is part of the closure of something that will get pushed.'
cachixArgs:
description: 'Extra command-line arguments to pass to cachix. If empty, defaults to -j8'
atticArgs:
description: 'Extra command-line arguments to pass to attic. If empty, defaults to -j8'
installCommand:
description: 'Override the default cachix installation method'
description: 'Override the default attic installation method'
branding:
color: 'blue'
icon: 'database'

37
dist/main/index.js vendored
View file

@ -4292,45 +4292,46 @@ const which_1 = __importDefault(__nccwpck_require__(207));
exports.IsPost = !!process.env['STATE_isPost'];
// inputs
const name = core.getInput('name', { required: true });
const instance = core.getInput('instance', { required: true });
const extraPullNames = core.getInput('extraPullNames');
const signingKey = core.getInput('signingKey');
const authToken = core.getInput('authToken');
const skipPush = core.getInput('skipPush');
const pathsToPush = core.getInput('pathsToPush');
const pushFilter = core.getInput('pushFilter');
const cachixArgs = core.getInput('cachixArgs');
const atticArgs = core.getInput('atticArgs');
const installCommand = core.getInput('installCommand') ||
"nix-env --quiet -j8 -iA cachix -f https://cachix.org/api/v1/install";
"nix-store -r /nix/store/0zplda5sjpr44lrgh47rrg67iv1f3bam-attic-0.1.0 --extra-substituters https://cache.icewind.me/attic-action --extra-trusted-public-keys attic-action:922cbVIJIubQvnF+ymBpFAbYjBHtD+yU4OHmNasqHhg=" +
"&& nix profile install github:zhaofengli/attic?rev=5f85e35a25085b75e1cbb6cc7291726fa4fab2ed#attic --extra-experimental-features 'nix-command flakes'";
function setup() {
return __awaiter(this, void 0, void 0, function* () {
try {
if (!which_1.default.sync('cachix', { nothrow: true })) {
core.startGroup('Cachix: installing');
if (!which_1.default.sync('attic', { nothrow: true })) {
core.startGroup('Attic: installing');
yield exec.exec('bash', ['-c', installCommand]);
core.endGroup();
}
core.startGroup('Cachix: checking version');
yield exec.exec('cachix', ['--version']);
core.startGroup('Attic: checking version');
yield exec.exec('attic', ['--version']);
core.endGroup();
// for managed signing key and private caches
if (authToken !== "") {
yield exec.exec('cachix', ['authtoken', authToken]);
yield exec.exec('attic', ['login', name, instance, authToken]);
}
core.startGroup(`Cachix: using cache ` + name);
yield exec.exec('cachix', ['use', name]);
else {
yield exec.exec('attic', ['login', name, instance]);
}
core.startGroup(`Attic: using cache ` + name);
yield exec.exec('attic', ['use', name]);
core.endGroup();
if (extraPullNames != "") {
core.startGroup(`Cachix: using extra caches ` + extraPullNames);
core.startGroup(`Attic: using extra caches ` + extraPullNames);
const extraPullNameList = extraPullNames.split(',');
for (let itemName of extraPullNameList) {
const trimmedItemName = itemName.trim();
yield exec.exec('cachix', ['use', trimmedItemName]);
yield exec.exec('attic', ['use', trimmedItemName]);
}
core.endGroup();
}
if (signingKey !== "") {
core.exportVariable('CACHIX_SIGNING_KEY', signingKey);
}
// Remember existing store paths
yield exec.exec("sh", ["-c", `${__dirname}/list-nix-store.sh > /tmp/store-path-pre-build`]);
}
@ -4341,13 +4342,13 @@ function setup() {
}
function upload() {
return __awaiter(this, void 0, void 0, function* () {
core.startGroup('Cachix: push');
core.startGroup('Attic: push');
try {
if (skipPush === 'true') {
core.info('Pushing is disabled as skipPush is set to true');
}
else if (signingKey !== "" || authToken !== "") {
yield exec.exec(`${__dirname}/push-paths.sh`, ['cachix', cachixArgs, name, pathsToPush, pushFilter]);
else if (authToken !== "") {
yield exec.exec(`${__dirname}/push-paths.sh`, ['attic', atticArgs, name, pathsToPush, pushFilter]);
}
else {
core.info('Pushing is disabled as signingKey nor authToken are set (or are empty?) in your YAML file.');

View file

@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail
cachix=$1 cachixArgs=${2:--j8} cache=$3 pathsToPush=$4 pushFilter=$5
attic=$1 atticArgs=${2:--j8} cache=$3 pathsToPush=$4 pushFilter=$5
if [[ $pathsToPush == "" ]]; then
pathsToPush=$(comm -13 <(sort /tmp/store-path-pre-build) <("$(dirname "$0")"/list-nix-store.sh))
@ -11,4 +11,4 @@ if [[ $pathsToPush == "" ]]; then
fi
fi
echo "$pathsToPush" | "$cachix" push $cachixArgs "$cache"
echo "$pathsToPush" | xargs "$attic" push $atticArgs "$cache"

138
flake.lock generated Normal file
View file

@ -0,0 +1,138 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"haze": {
"inputs": {
"flake-utils": "flake-utils",
"naersk": "naersk",
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1683462266,
"narHash": "sha256-EVXzgfNqzNqNbbGQ5+yHaxYfMaosH+nRo+AqEi1r1pI=",
"path": "/nix/store/ad5i24si9fx6prn7r78camch3xf5my5r-source",
"rev": "eb8423f6efe4e8441716565e52bd4c7324181668",
"type": "path"
},
"original": {
"id": "haze",
"type": "indirect"
}
},
"naersk": {
"inputs": {
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1671096816,
"narHash": "sha256-ezQCsNgmpUHdZANDCILm3RvtO1xH8uujk/+EqNvzIOg=",
"owner": "nix-community",
"repo": "naersk",
"rev": "d998160d6a076cfe8f9741e56aeec7e267e3e114",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "naersk",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1674407282,
"narHash": "sha256-2qwc8mrPINSFdWffPK+ji6nQ9aGnnZyHSItVcYDZDlk=",
"path": "/nix/store/47v7isgz6w8zgb1224d46lwvwkdd69bm-source",
"rev": "ab1254087f4cdf4af74b552d7fc95175d9bdbb49",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1674407282,
"narHash": "sha256-2qwc8mrPINSFdWffPK+ji6nQ9aGnnZyHSItVcYDZDlk=",
"path": "/nix/store/47v7isgz6w8zgb1224d46lwvwkdd69bm-source",
"rev": "ab1254087f4cdf4af74b552d7fc95175d9bdbb49",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1684858140,
"narHash": "sha256-dQStox5GYrVlVNMvxxXs3xX9bXG7J7ttSjqUcVm8EaA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a17f99dfcb9643200b3884ca195c69ae41d7f059",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "release-22.11",
"type": "indirect"
}
},
"root": {
"inputs": {
"haze": "haze",
"nixpkgs": "nixpkgs_3",
"utils": "utils"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1681202837,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

26
flake.nix Normal file
View file

@ -0,0 +1,26 @@
{
inputs = {
nixpkgs.url = "nixpkgs/release-22.11";
utils.url = "github:numtide/flake-utils";
};
outputs = {
self,
nixpkgs,
haze,
utils,
}:
utils.lib.eachDefaultSystem (system: let
pkgs = import nixpkgs {
inherit system;
};
in rec {
devShells.default = pkgs.mkShell {
nativeBuildInputs = with pkgs; [
nodejs
typescript
yarn
];
};
});
}

View file

@ -1,8 +1,8 @@
{
"name": "cachix-action",
"name": "attic-action",
"version": "1.0.0",
"private": true,
"description": "nix-build with the help of caching to Cachix",
"description": "nix-build with the help of caching to Attic",
"main": "dist/main/index.js",
"scripts": {
"build": "tsc && ncc build -o dist/main src/main.ts",
@ -10,14 +10,14 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/cachix/cachix-action.git"
"url": "git+https://github.com/icewind1991/attic-action.git"
},
"keywords": [
"actions",
"node",
"setup"
],
"author": "Domen Kožar",
"author": "Robin Appelman",
"license": "ASL2",
"dependencies": {
"@actions/core": "^1.10.0",

View file

@ -6,51 +6,52 @@ export const IsPost = !!process.env['STATE_isPost']
// inputs
const name = core.getInput('name', { required: true });
const instance = core.getInput('instance', { required: true });
const extraPullNames = core.getInput('extraPullNames');
const signingKey = core.getInput('signingKey');
const authToken = core.getInput('authToken')
const skipPush = core.getInput('skipPush');
const pathsToPush = core.getInput('pathsToPush');
const pushFilter = core.getInput('pushFilter');
const cachixArgs = core.getInput('cachixArgs');
const atticArgs = core.getInput('atticArgs');
const installCommand =
core.getInput('installCommand') ||
"nix-env --quiet -j8 -iA cachix -f https://cachix.org/api/v1/install";
"nix-store -r /nix/store/0zplda5sjpr44lrgh47rrg67iv1f3bam-attic-0.1.0 --extra-substituters https://cache.icewind.me/attic-action --extra-trusted-public-keys attic-action:922cbVIJIubQvnF+ymBpFAbYjBHtD+yU4OHmNasqHhg=" +
"&& nix profile install github:zhaofengli/attic?rev=5f85e35a25085b75e1cbb6cc7291726fa4fab2ed#attic --extra-experimental-features 'nix-command flakes'";
async function setup() {
try {
if(!which.sync('cachix', { nothrow: true })) {
core.startGroup('Cachix: installing')
if(!which.sync('attic', { nothrow: true })) {
core.startGroup('Attic: installing')
await exec.exec('bash', ['-c', installCommand]);
core.endGroup()
}
core.startGroup('Cachix: checking version')
await exec.exec('cachix', ['--version']);
core.startGroup('Attic: checking version')
await exec.exec('attic', ['--version']);
core.endGroup()
// for managed signing key and private caches
if (authToken !== "") {
await exec.exec('cachix', ['authtoken', authToken]);
await exec.exec('attic', ['login', name, instance, authToken]);
} else {
await exec.exec('attic', ['login', name, instance]);
}
core.startGroup(`Cachix: using cache ` + name);
await exec.exec('cachix', ['use', name]);
core.startGroup(`Attic: using cache ` + name);
await exec.exec('attic', ['use', name]);
core.endGroup();
if (extraPullNames != "") {
core.startGroup(`Cachix: using extra caches ` + extraPullNames);
core.startGroup(`Attic: using extra caches ` + extraPullNames);
const extraPullNameList = extraPullNames.split(',');
for (let itemName of extraPullNameList) {
const trimmedItemName = itemName.trim();
await exec.exec('cachix', ['use', trimmedItemName]);
await exec.exec('attic', ['use', trimmedItemName]);
}
core.endGroup();
}
if (signingKey !== "") {
core.exportVariable('CACHIX_SIGNING_KEY', signingKey);
}
// Remember existing store paths
await exec.exec("sh", ["-c", `${__dirname}/list-nix-store.sh > /tmp/store-path-pre-build`]);
} catch (error) {
@ -59,12 +60,12 @@ async function setup() {
}
async function upload() {
core.startGroup('Cachix: push');
core.startGroup('Attic: push');
try {
if (skipPush === 'true') {
core.info('Pushing is disabled as skipPush is set to true');
} else if (signingKey !== "" || authToken !== "") {
await exec.exec(`${__dirname}/push-paths.sh`, ['cachix', cachixArgs, name, pathsToPush, pushFilter]);
} else if (authToken !== "") {
await exec.exec(`${__dirname}/push-paths.sh`, ['attic', atticArgs, name, pathsToPush, pushFilter]);
} else {
core.info('Pushing is disabled as signingKey nor authToken are set (or are empty?) in your YAML file.');
}