Compare commits

...

27 Commits
v0.1.0 ... main

Author SHA1 Message Date
22c2bb1406 Make build 2024-06-16 21:26:31 -06:00
8e8ff90bd6 Use full path when accessing attic 2024-06-16 20:52:16 -06:00
Paul Zinselmeyer
5619ef4781
feat: skip installation of attic when installed (#21) 2024-05-25 08:29:36 +00:00
dependabot[bot]
37f74ba5fa
chore(deps): bump pnpm/action-setup from 2 to 3 (#19)
Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 2 to 3.
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v2...v3)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-23 03:37:47 -04:00
dependabot[bot]
6cfb1137df
chore(deps): bump DeterminateSystems/nix-installer-action from 7 to 9 (#15)
Bumps [DeterminateSystems/nix-installer-action](https://github.com/determinatesystems/nix-installer-action) from 7 to 9.
- [Release notes](https://github.com/determinatesystems/nix-installer-action/releases)
- [Commits](https://github.com/determinatesystems/nix-installer-action/compare/v7...v9)

---
updated-dependencies:
- dependency-name: DeterminateSystems/nix-installer-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-23 03:37:03 -04:00
Ryan
f75ac4b827
fix: support nix >= 2.19 (#18)
* fix: TypeError when pushing

* fix: compatibility with Nix 2.18
2024-01-07 22:00:22 +00:00
seth
6689ac7697
push: don't report failure on error (#16) 2023-12-14 11:12:23 +00:00
dependabot[bot]
4698511c85
chore(deps): bump DeterminateSystems/nix-installer-action from 5 to 7 (#13)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-08 14:21:59 +00:00
seth
7f0e30fedd
chore: misc cleanups for flake and ci (#12) 2023-11-08 14:21:46 +00:00
Ryan Cao
40fa276ac0
chore: use Node v20 for nvm/fnm 2023-10-25 23:20:59 +08:00
dependabot[bot]
fae7bd1d97
chore(deps): bump actions/setup-node from 3 to 4 (#11)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 03:41:22 +00:00
dependabot[bot]
aa6bedf232
chore(deps): bump DeterminateSystems/nix-installer-action from 4 to 5 (#9) 2023-10-10 07:19:24 +08:00
Ryan Cao
6870271f1d
feat!: node18 2023-09-15 15:37:51 +08:00
Ryan Cao
ce977ffab4
fix: various fixes 2023-09-15 00:12:36 +08:00
Daniel Kempkens
8c01d0bda1
feat: automatically configure Nix to use cache (#8) 2023-09-14 16:09:33 +00:00
dependabot[bot]
88dbb4b600
chore(deps): bump actions/checkout from 3 to 4 (#6)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-10 04:24:06 +00:00
dependabot[bot]
fd02e7c96c
chore(deps): bump cachix/install-nix-action from 22 to 23 (#7) 2023-09-05 11:04:12 +08:00
gallexme
56ba67dfc0
fix: save store paths to file (#5)
closes #4
2023-08-06 02:32:52 +00:00
Ryan Cao
e78c87fc0e
fix: split up added paths to avoid argument limit 2023-08-04 20:40:01 +08:00
Ryan Cao
7af24dd783
chore: update flake lock 2023-07-21 21:42:33 +08:00
Ryan Cao
3c5e4de9b2
docs: improve README 2023-07-21 16:11:50 +08:00
Ryan Cao
a2f0acb9d4
chore: add dependabot 2023-07-21 16:07:27 +08:00
seth
ec939ca6ac
chore: don't use channels for testing (#3) 2023-07-21 03:38:26 +00:00
Ryan Cao
3b6f7992de
ci: manually add nixpkgs 2023-07-20 17:50:37 +08:00
Ryan Cao
2533b28a8f
add README 2023-07-20 09:09:48 +08:00
Ryan Cao
00f4a8b31e
improve action.yml 2023-07-20 09:08:36 +08:00
Ryan Cao
ce803b732a
fix: use node import behavior 2023-07-19 12:24:57 +08:00
17 changed files with 179 additions and 110 deletions

7
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View File

@ -4,20 +4,21 @@ on:
release:
types: [published, edited]
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
ref: ${{ github.event.release.tag_name }}
- uses: pnpm/action-setup@v2
- uses: actions/setup-node@v3
- uses: pnpm/action-setup@v3
- uses: actions/setup-node@v4
with:
cache: pnpm
cache-dependency-path: pnpm-lock.yaml

View File

@ -16,10 +16,10 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- uses: actions/setup-node@v3
- uses: pnpm/action-setup@v3
- uses: actions/setup-node@v4
with:
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
@ -28,7 +28,7 @@ jobs:
run: pnpm install && pnpm build
- name: Install Nix
uses: cachix/install-nix-action@v22
uses: DeterminateSystems/nix-installer-action@v9
- name: Setup Attic Cache
uses: ./
@ -38,4 +38,4 @@ jobs:
token: ${{ secrets.ATTIC_TOKEN }}
- name: Build Nix Package
run: nix build -f test.nix
run: nix-build test.nix

View File

@ -1 +1 @@
16
20

44
README.md Normal file
View File

@ -0,0 +1,44 @@
# attic-action
Cache Nix derivations with [Attic](https://github.com/zhaofengli/attic).
## Usage
Configure your attic instance with an endpoint, a cache, and a token that can read from and write to the cache. Then, add this step to a workflow job after Nix is installed:
```yaml
- name: Setup Attic cache
uses: ryanccn/attic-action@v0
with:
endpoint: ${{ secrets.ATTIC_ENDPOINT }}
cache: ${{ secrets.ATTIC_CACHE }}
token: ${{ secrets.ATTIC_TOKEN }}
```
## Inputs
### `endpoint`
The Attic endpoint. This is the URL without the cache name.
### `cache`
The name of the Attic cache.
### `token`
The authorization token to provide to Attic (**optional**).
### `skip-push`
Disable pushing new derivations to the cache automatically at the end of the job (**default is false**).
This requires you to invoke `attic push <cache>` with the paths you want to push to the cache manually.
## Outputs
None
## License
MIT

View File

@ -1,22 +1,29 @@
name: "attic"
name: "attic-action"
author: "Ryan Cao"
description: "Cache Nix derivations with attic"
branding:
icon: "layers"
color: "blue"
inputs:
endpoint:
description: "attic endpoint"
description: "Attic endpoint"
required: true
cache:
description: "attic cache"
description: "Attic cache name"
required: true
skip-push:
description: "set to true to disable pushing to the cache"
description: "Disable pushing to the cache automatically"
required: false
token:
description: "attic token"
description: "Attic authorization token"
required: false
skip-use:
description: "Set to true to skip using attic cache as a substituter"
required: false
runs:
using: "node16"
using: "node20"
main: "dist/index.js"
post: "dist/index.js"
post-if: "success()"

8
dist/index.js vendored Normal file

File diff suppressed because one or more lines are too long

6
flake.lock generated
View File

@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1689534811,
"narHash": "sha256-jnSUdzD/414d94plCyNlvTJJtiTogTep6t7ZgIKIHiE=",
"lastModified": 1689850295,
"narHash": "sha256-fUYf6WdQlhd2H+3aR8jST5dhFH1d0eE22aes8fNIfyk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6cee3b5893090b0f5f0a06b4cf42ca4e60e5d222",
"rev": "5df4d78d54f7a34e9ea1f84a22b4fd9baebc68d0",
"type": "github"
},
"original": {

View File

@ -1,36 +1,30 @@
{
description = "";
description = "Github Action for caching Nix derivations with attic";
inputs = {
nixpkgs.url = "nixpkgs/nixos-unstable";
};
outputs =
{ nixpkgs
, ...
}:
let
mkSystems = sys: builtins.map (arch: "${arch}-${sys}") [ "x86_64" "aarch64" ];
systems =
mkSystems "linux"
++ mkSystems "darwin";
outputs = {nixpkgs, ...}: let
systems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
forAllSystems = nixpkgs.lib.genAttrs systems;
nixpkgsFor = forAllSystems (system: import nixpkgs { inherit system; });
forAllSystems = fn: nixpkgs.lib.genAttrs systems (system: fn nixpkgs.legacyPackages.${system});
in {
devShells = forAllSystems (pkgs: {
default = pkgs.mkShell {
packages = with pkgs; [
actionlint
nodejs_20
(nodePackages_latest.pnpm.override {nodejs = nodejs_20;})
];
};
});
forEachSystem = fn:
forAllSystems (s: fn nixpkgsFor.${s});
in
{
devShells = forEachSystem (pkgs: {
default = pkgs.mkShell {
packages = with pkgs; [
actionlint
nodePackages.pnpm
];
};
});
formatter = forEachSystem (p: p.nixpkgs-fmt);
};
formatter = forAllSystems (p: p.alejandra);
};
}

View File

@ -6,13 +6,12 @@
"build": "esbuild src/index.ts --outdir=dist --platform=node --format=cjs --bundle --minify-whitespace --minify-syntax",
"format": "prettier --write ."
},
"keywords": [],
"author": "Ryan Cao <hello@ryanccn.dev>",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.10.0",
"@actions/exec": "^1.1.1",
"ofetch": "^1.1.1"
"just-split": "^3.2.0"
},
"devDependencies": {
"@types/node": "^16.18.38",
@ -20,5 +19,5 @@
"prettier": "3.0.0",
"typescript": "^5.1.6"
},
"packageManager": "pnpm@8.6.9"
"packageManager": "pnpm@8.7.5"
}

26
pnpm-lock.yaml generated
View File

@ -11,9 +11,9 @@ dependencies:
'@actions/exec':
specifier: ^1.1.1
version: 1.1.1
ofetch:
specifier: ^1.1.1
version: 1.1.1
just-split:
specifier: ^3.2.0
version: 3.2.0
devDependencies:
'@types/node':
@ -256,10 +256,6 @@ packages:
resolution: {integrity: sha512-6sfo1qTulpVbkxECP+AVrHV9OoJqhzCsfTNp5NIG+enM4HyM3HvZCO798WShIXBN0+QtDIcutJCjsVYnQP5rIQ==}
dev: true
/destr@2.0.0:
resolution: {integrity: sha512-FJ9RDpf3GicEBvzI3jxc2XhHzbqD8p4ANw/1kPsFBfTvP1b7Gn/Lg1vO7R9J4IVgoMbyUmFrFGZafJ1hPZpvlg==}
dev: false
/esbuild@0.18.14:
resolution: {integrity: sha512-uNPj5oHPYmj+ZhSQeYQVFZ+hAlJZbAGOmmILWIqrGvPVlNLbyOvU5Bu6Woi8G8nskcx0vwY0iFoMPrzT86Ko+w==}
engines: {node: '>=12'}
@ -290,16 +286,8 @@ packages:
'@esbuild/win32-x64': 0.18.14
dev: true
/node-fetch-native@1.2.0:
resolution: {integrity: sha512-5IAMBTl9p6PaAjYCnMv5FmqIF6GcZnawAVnzaCG0rX2aYZJ4CxEkZNtVPuTRug7fL7wyM5BQYTlAzcyMPi6oTQ==}
dev: false
/ofetch@1.1.1:
resolution: {integrity: sha512-SSMoktrp9SNLi20BWfB/BnnKcL0RDigXThD/mZBeQxkIRv1xrd9183MtLdsqRYLYSqW0eTr5t8w8MqjNhvoOQQ==}
dependencies:
destr: 2.0.0
node-fetch-native: 1.2.0
ufo: 1.1.2
/just-split@3.2.0:
resolution: {integrity: sha512-hh57dN5koTBkmg3T6gBFISVVaW5bgZ6Ct1W5KODD5M7hQJKqGzTKkfMwOil8MBxyztLQEjh/v6UGXE8cP5tnqQ==}
dev: false
/prettier@3.0.0:
@ -319,10 +307,6 @@ packages:
hasBin: true
dev: true
/ufo@1.1.2:
resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==}
dev: false
/uuid@8.3.2:
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
hasBin: true

View File

@ -1,12 +1,16 @@
import { install } from "./stages/install";
import { install, isInstalled } from "./stages/install";
import { configure } from "./stages/configure";
import { push } from "./stages/push.ts";
import { getState, saveState } from "@actions/core";
import { push } from "./stages/push";
import { getState, saveState, info } from "@actions/core";
const isPost = !!getState("isPost");
const main = async () => {
await install();
if (await isInstalled()) {
info("Skipping attic installation because it is already installed");
} else {
await install();
}
await configure();
};

View File

@ -1,6 +1,6 @@
import * as core from "@actions/core";
import { exec } from "@actions/exec";
import { getStorePaths } from "../utils";
import { saveStorePaths } from "../utils";
export const configure = async () => {
core.startGroup("Configure attic");
@ -9,13 +9,20 @@ export const configure = async () => {
const endpoint = core.getInput("endpoint");
const cache = core.getInput("cache");
const token = core.getInput("token");
const skipUse = core.getInput("skip-use");
core.info("Logging in to attic cache");
await exec("attic", ["login", "--set-default", cache, endpoint, token]);
await exec("/run/current-system/sw/bin/attic", ["login", "--set-default", cache, endpoint, token]);
if (skipUse === "true") {
core.info("Not adding attic cache to substituters as skip-use is set to true");
} else {
core.info("Adding attic cache to substituters");
await exec("/run/current-system/sw/bin/attic", ["use", cache]);
}
core.info("Collecting store paths before build");
const paths = await getStorePaths();
core.saveState("initial-paths", JSON.stringify(paths));
await saveStorePaths();
} catch (e) {
core.setFailed(`Action failed with error: ${e}`);
}

View File

@ -1,6 +1,5 @@
import * as core from "@actions/core";
import { exec } from "@actions/exec";
import { fetch } from "ofetch";
import { writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
@ -34,3 +33,8 @@ export const install = async () => {
core.endGroup();
};
export const isInstalled = async () => {
let return_code = await exec("/run/current-system/sw/bin/attic", ["-V"]);
return return_code === 0;
};

View File

@ -1,19 +1,24 @@
import * as core from "@actions/core";
import { exec } from "@actions/exec";
import { getStorePaths } from "../utils";
import splitArray from "just-split";
import { saveStorePaths, getStorePaths } from "../utils";
export const push = async () => {
core.startGroup("Push to Attic");
try {
const skipPush = core.getInput("skip-push");
if (skipPush === "true") {
core.info("Pushing to cache is disabled by skip-push");
} else {
const cache = core.getInput("cache");
core.info("Pushing to cache");
const oldPaths = JSON.parse(core.getState("initial-paths")) as string[];
const oldPaths = await getStorePaths();
await saveStorePaths();
const newPaths = await getStorePaths();
const addedPaths = newPaths
.filter((p) => !oldPaths.includes(p))
@ -21,10 +26,14 @@ export const push = async () => {
(p) => !p.endsWith(".drv") && !p.endsWith(".drv.chroot") && !p.endsWith(".check") && !p.endsWith(".lock"),
);
await exec("attic", ["push", cache, ...addedPaths]);
const splitAddedPaths = splitArray(addedPaths, 25);
for (const addedPaths of splitAddedPaths) {
await exec("/run/current-system/sw/bin/attic", ["push", cache, ...addedPaths]);
}
}
} catch (e) {
core.setFailed(`Action failed with error: ${e}`);
core.warning(`Action encountered error: ${e}`);
core.info("Not considering errors during push a failure.");
}
core.endGroup();

View File

@ -1,23 +1,17 @@
import { exec } from "@actions/exec";
import { Writable } from "node:stream";
class StringStream extends Writable {
chunks: Buffer[] = [];
import { readFile } from "node:fs/promises";
_write(chunk: WithImplicitCoercion<ArrayBuffer | SharedArrayBuffer>, _enc: unknown, next: () => unknown) {
this.chunks.push(Buffer.from(chunk));
next();
}
string() {
return Buffer.concat(this.chunks).toString("utf-8");
}
}
export const getStorePaths = async () => {
const outStream = new StringStream();
await exec("nix", ["path-info", "--all"], { outStream });
const paths = outStream.string().split("\n").filter(Boolean);
return paths;
export const saveStorePaths = async () => {
await exec("sh", ["-c", "nix path-info --all --json > /tmp/store-paths"]);
};
export const getStorePaths = async () => {
const rawStorePaths = JSON.parse(await readFile("/tmp/store-paths", "utf8")) as { path: string }[];
// compatibility with Nix 2.18
if (Array.isArray(rawStorePaths)) {
return rawStorePaths.map((path) => path.path);
};
return Object.keys(rawStorePaths);
};

View File

@ -1,7 +1,14 @@
let
pkgs = import <nixpkgs> { };
time = with builtins; toString currentTime;
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
pkgs = import (
fetchTarball {
url =
lock.nodes.nixpkgs.locked.url
or "https://github.com/NixOS/nixpkgs/archive/${lock.nodes.nixpkgs.locked.rev}.tar.gz";
sha256 = lock.nodes.nixpkgs.locked.narHash;
}
) {};
in
pkgs.runCommand "${time}-test" { } ''
echo "${time}" > $out
''
pkgs.runCommand "non-reproducible-test" {} ''
echo ${toString builtins.currentTime} > $out
''