Compare commits

..

21 Commits

Author SHA1 Message Date
Graham Christensen c5a866b6ab Update to determinate by default (#208)
* Update to determinate by default

Implements https://github.com/DeterminateSystems/nix-src/issues/201

* Fixup the version verification script
2025-11-10 09:48:50 -05:00
Graham Christensen 89b1f59ae9 Drop x86_64-darwin (#207)
* Drop x86_64-darwin

Implements https://github.com/DeterminateSystems/nix-src/issues/224

* Force back to v3.12.2 for users who don't otherwise specify a tag

* ci: don't try to render the devshell on intel macOS

* Try an error?

* Update messaging to be more action-oriented
2025-11-09 22:55:22 -05:00
Luc Perkins 86a5f59de1 Merge pull request #206 from detsys-pr-bot/detsys-ts-update-cb28f5861548d8a85d054c4d6e8e0cd3d3c94329
Update `detsys-ts`: Merge pull request #114 from DeterminateSystems/dependabot/npm_and_yarn/npm-deps-47c548f420
2025-11-07 13:02:42 -03:00
lucperkins 64a1e1d1cb Update detsys-ts for: Merge pull request #114 from DeterminateSystems/dependabot/npm_and_yarn/npm-deps-47c548f420 (cb28f5861548d8a85d054c4d6e8e0cd3d3c94329) 2025-11-07 15:52:50 +00:00
Graham Christensen 2fd3724578 If determinate is false, pass --prefer-upstream (#202)
* If determinate is false, pass --prefer-upstream

* Regenerate

* Update to an installer version that supports preferring upstream

* Delete the rev test, since rev uploads appoar to have broken a long time ago

* Fixup: expect upstream nix at the moment
2025-10-24 22:24:28 -04:00
Luc Perkins 45a18a6995 Merge pull request #203 from detsys-pr-bot/detsys-ts-update-285768c0d657f9709cb689893f12895c36923093
Update `detsys-ts`: Merge pull request #109 from DeterminateSystems/tsup-to-tsdown
2025-09-12 14:50:59 +02:00
lucperkins d3ddf0223c Update detsys-ts for: Merge pull request #109 from DeterminateSystems/tsup-to-tsdown (285768c0d657f9709cb689893f12895c36923093) 2025-09-12 12:39:38 +00:00
gustavderdrache 786fff0690 Apply fixups from CodeRabbit review (#200) 2025-09-09 10:54:24 -04:00
gustavderdrache f161ab07ed Treat FlakeHub logins as a funnel (#199) 2025-09-09 10:40:05 -04:00
gustavderdrache 61ce7897f4 Merge pull request #198 from DeterminateSystems/gustavderdrache/push-mzwwpswkrrup
Record events if authentication is skipped
2025-09-09 09:58:05 -04:00
gustavderdrache 44f3801e21 Improve messages for when auth isn't available 2025-09-09 09:48:10 -04:00
gustavderdrache cb6d4e86fa Standardize login failure events 2025-09-09 09:44:32 -04:00
gustavderdrache e686131f84 Record events if authentication is skipped 2025-09-08 16:04:19 -04:00
Graham Christensen 2c3a2981f1 Report the number of nix builds that passed / failed (#196)
* Report the number of nix builds that passed / failed

* Upgrade
2025-09-03 12:03:09 -04:00
detsys-pr-bot 18b667a294 Update detsys-ts for: Capture the version of Nix in addition to the nix store version (#108) (c7303495f43d348cac78091ef434443b1ef22485) (#197)
Co-authored-by: grahamc <76716+grahamc@users.noreply.github.com>
2025-09-03 15:37:20 +00:00
detsys-pr-bot 428f3c64a3 Update detsys-ts for: Merge pull request #106 from DeterminateSystems/fix-dependabot-warning (6d3f1c5a5781e58b3cd8060cfb578c0c95eeb51e) (#194)
Co-authored-by: lucperkins <1523104+lucperkins@users.noreply.github.com>
2025-07-30 15:59:25 +00:00
detsys-pr-bot 90bb610b90 Update detsys-ts for: Await the request promise so we can cover it with the timout handler (#105) (20c4962e328c1eba8f04da00bbb7a7e307d511e0) (#191)
Co-authored-by: grahamc <76716+grahamc@users.noreply.github.com>
2025-07-14 22:53:06 +00:00
detsys-pr-bot c723f3a885 Update detsys-ts for: Skip complicated rewrites, record groups. (#104) (0095c476e55f64d04f1aa1e1bcc2524c329d073a) (#190)
Co-authored-by: grahamc <76716+grahamc@users.noreply.github.com>
2025-07-03 09:38:17 -04:00
Luc Perkins 41e0dcf215 Merge pull request #188 from detsys-pr-bot/detsys-ts-update-5084fa8e3263a0bed2383f46e407e6c2936e8289
Update `detsys-ts`: Remove FHC action since it's composite (#103)
2025-06-24 12:56:06 -07:00
grahamc e455bc9d67 Update detsys-ts for: Remove FHC action since it's composite (#103) (5084fa8e3263a0bed2383f46e407e6c2936e8289) 2025-06-23 19:56:57 +00:00
detsys-pr-bot b336b210d0 Update detsys-ts for: Merge pull request #101 from DeterminateSystems/gustavderdrache/write-correlation (e252a66f00e041869f7e402e579141f7b8ab1edf) (#187)
Co-authored-by: gustavderdrache <194893+gustavderdrache@users.noreply.github.com>
2025-06-23 18:40:45 +00:00
21 changed files with 42056 additions and 32355 deletions
+74
View File
@@ -0,0 +1,74 @@
{
"plugins": ["@typescript-eslint"],
"extends": ["plugin:github/recommended"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 9,
"sourceType": "module",
"project": "./tsconfig.json"
},
"settings": {
"import/resolver": {
"typescript": {}
}
},
"rules": {
"i18n-text/no-en": "off",
"eslint-comments/no-use": "off",
"import/no-namespace": "off",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_"
}
],
"@typescript-eslint/explicit-member-accessibility": [
"error",
{
"accessibility": "no-public"
}
],
"@typescript-eslint/no-base-to-string": "error",
"@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/array-type": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/ban-ts-comment": "error",
"camelcase": "error",
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/explicit-function-return-type": [
"error",
{
"allowExpressions": true
}
],
"@typescript-eslint/func-call-spacing": ["error", "never"],
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-extraneous-class": "error",
"@typescript-eslint/no-for-in-array": "error",
"@typescript-eslint/no-inferrable-types": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "warn",
"@typescript-eslint/no-unnecessary-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-useless-constructor": "error",
"@typescript-eslint/no-var-requires": "error",
"@typescript-eslint/prefer-for-of": "warn",
"@typescript-eslint/prefer-function-type": "warn",
"@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-array-sort-compare": "error",
"@typescript-eslint/restrict-plus-operands": "error",
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/unbound-method": "error"
},
"env": {
"node": true,
"es6": true
}
}
+1 -2
View File
@@ -7,9 +7,8 @@ EXPECTED_VERSION="${1}"
INSTALLED_NIX_VERSION_OUTPUT=$(nix --version)
INSTALLED_NIX_VERSION=$(echo "${INSTALLED_NIX_VERSION_OUTPUT}" | awk '{print $NF}')
EXPECTED_OUTPUT="nix (Nix) ${EXPECTED_VERSION}"
if [ "${INSTALLED_NIX_VERSION_OUTPUT}" != "${EXPECTED_OUTPUT}" ]; then
if [ "${INSTALLED_NIX_VERSION}" != "${EXPECTED_VERSION}" ]; then
echo "Nix version ${INSTALLED_NIX_VERSION} didn't match expected version ${EXPECTED_VERSION}"
exit 1
else
+10 -16
View File
@@ -8,7 +8,7 @@ on:
jobs:
tests:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
needs:
- check-dist-up-to-date
- install-nix
@@ -24,19 +24,17 @@ jobs:
check-dist-up-to-date:
name: Check the dist/ folder is up to date
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/flakehub-cache-action@main
- name: pnpm install
run: nix develop --command pnpm install
- name: Check formatting
- name: prettier format
run: nix develop --command pnpm run check-fmt
- name: Link
- name: ESLint
run: nix develop --command pnpm run lint
- name: Test
run: nix develop --command pnpm run test
- name: tsup build
run: nix develop --command pnpm run build
- name: ncc package
@@ -80,7 +78,7 @@ jobs:
run: echo $PATH
- name: Render the devshell
if: success() || failure()
if: (success() || failure()) && matrix.runner != 'macos-13-large' && matrix.runner != 'macos-14-large'
run: |
nix develop --command date
@@ -148,18 +146,14 @@ jobs:
install-with-non-default-source-inputs:
name: Install Nix using non-default source-${{ matrix.inputs.key }}
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
strategy:
matrix:
inputs:
# https://github.com/DeterminateSystems/nix-installer/blob/v0.18.0
# https://github.com/DeterminateSystems/nix-installer/blob/v3.11.3
- key: url
value: https://github.com/DeterminateSystems/nix-installer/releases/download/v0.18.0/nix-installer-x86_64-linux
nix-version: "2.21.2"
# https://github.com/DeterminateSystems/nix-installer/tree/7011c077ec491da410fbc39f68676b0908b9ce7e
- key: revision
value: 7011c077ec491da410fbc39f68676b0908b9ce7e
nix-version: "2.19.2"
value: https://github.com/DeterminateSystems/nix-installer/releases/download/v3.11.3/nix-installer-x86_64-linux
nix-version: "2.31.2" # 3.11.3 is based on 2.31.2
steps:
- uses: actions/checkout@v4
@@ -173,7 +167,7 @@ jobs:
install-no-id-token:
name: Install Nix without an ID token
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: ./
+3
View File
@@ -53,6 +53,9 @@ typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
+3
View File
@@ -0,0 +1,3 @@
dist/
lib/
node_modules/
+1
View File
@@ -0,0 +1 @@
{}
+1 -1
View File
@@ -96,7 +96,7 @@ Differing from the upstream [Nix](https://github.com/NixOS/nix) installer script
| Parameter | Description | Type | Default |
| :---------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------- | :------------------------------------------------------------- |
| `backtrace` | The setting for [`RUST_BACKTRACE`][backtrace] | string | |
| `determinate` | Whether to install [Determinate Nix](https://determinate.systems/enterprise) and log in to FlakeHub for private Flakes and binary caches. | Boolean | `false` |
| `determinate` | Whether to install [Determinate Nix](https://determinate.systems/enterprise) and log in to FlakeHub for private Flakes and binary caches. | Boolean | `true` |
| `extra-args` | Extra arguments to pass to the planner (prefer using structured `with:` arguments unless using a custom [planner]!) | string | |
| `extra-conf` | Extra configuration lines for `/etc/nix/nix.conf` (includes `access-tokens` with `secrets.GITHUB_TOKEN` automatically if `github-token` is set) | string | |
| `flakehub` | Deprecated. Implies `determinate`. | Boolean | `false` |
+1 -1
View File
@@ -10,7 +10,7 @@ inputs:
determinate:
description: |
Whether to install [Determinate Nix](https://determinate.systems/enterprise) and log in to FlakeHub for private Flakes and binary caches.
default: false
default: true
extra-args:
description: Extra args to pass to the planner (prefer using structured `with:` arguments unless using a custom planner!)
required: false
-148
View File
@@ -1,148 +0,0 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true },
"files": {
"ignoreUnknown": false,
"ignore": ["dist"]
},
"formatter": {
"enabled": true,
"useEditorconfig": true,
"formatWithErrors": false,
"indentStyle": "space",
"indentWidth": 2,
"lineEnding": "lf",
"lineWidth": 80,
"attributePosition": "auto",
"bracketSpacing": true
},
"organizeImports": { "enabled": true },
"linter": {
"enabled": true,
"rules": {
"recommended": false,
"complexity": {
"noExtraBooleanCast": "error",
"noMultipleSpacesInRegularExpressionLiterals": "error",
"noStaticOnlyClass": "error",
"noUselessConstructor": "error",
"noUselessStringConcat": "error",
"noUselessTypeConstraint": "error"
},
"correctness": {
"noConstAssign": "error",
"noConstantCondition": "error",
"noEmptyCharacterClassInRegex": "error",
"noEmptyPattern": "error",
"noGlobalObjectCalls": "error",
"noInnerDeclarations": "error",
"noInvalidConstructorSuper": "error",
"noNewSymbol": "error",
"noSelfAssign": "error",
"noSwitchDeclarations": "error",
"noUndeclaredVariables": "error",
"noUnreachable": "error",
"noUnreachableSuper": "error",
"noUnsafeFinally": "error",
"noUnusedLabels": "error",
"noUnusedVariables": "error",
"useArrayLiterals": "off",
"useIsNan": "error",
"useYield": "error"
},
"style": {
"noArguments": "error",
"noCommaOperator": "error",
"noInferrableTypes": "error",
"noNamespace": "error",
"noNonNullAssertion": "warn",
"noVar": "error",
"useAsConstAssertion": "error",
"useConsistentArrayType": "error",
"useConst": "error",
"useForOf": "warn",
"useShorthandFunctionType": "warn",
"useSingleVarDeclarator": "error",
"useTemplate": "error"
},
"suspicious": {
"noCatchAssign": "error",
"noClassAssign": "error",
"noCompareNegZero": "error",
"noConsole": "error",
"noControlCharactersInRegex": "error",
"noDebugger": "error",
"noDoubleEquals": "error",
"noDuplicateCase": "error",
"noDuplicateClassMembers": "error",
"noDuplicateObjectKeys": "error",
"noDuplicateParameters": "error",
"noEmptyBlockStatements": "error",
"noExplicitAny": "error",
"noExtraNonNullAssertion": "error",
"noFallthroughSwitchClause": "error",
"noFunctionAssign": "error",
"noGlobalAssign": "error",
"noMisleadingInstantiator": "error",
"noRedeclare": "error",
"noSparseArray": "error",
"noUnsafeDeclarationMerging": "error",
"noUnsafeNegation": "error",
"useNamespaceKeyword": "error",
"useValidTypeof": "error"
}
}
},
"javascript": {
"formatter": {
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingCommas": "all",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSameLine": false,
"quoteStyle": "double",
"attributePosition": "auto",
"bracketSpacing": true
},
"globals": ["exports"]
},
"overrides": [
{
"include": ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"],
"linter": {
"rules": {
"complexity": { "noWith": "off" },
"correctness": {
"noConstAssign": "off",
"noGlobalObjectCalls": "off",
"noInvalidBuiltinInstantiation": "off",
"noInvalidConstructorSuper": "off",
"noNewSymbol": "off",
"noSetterReturn": "off",
"noUndeclaredVariables": "off",
"noUnreachable": "off",
"noUnreachableSuper": "off"
},
"style": {
"noArguments": "error",
"noVar": "error",
"useConst": "error",
"useNamingConvention": "error"
},
"suspicious": {
"noClassAssign": "off",
"noDuplicateClassMembers": "off",
"noDuplicateObjectKeys": "off",
"noDuplicateParameters": "off",
"noFunctionAssign": "off",
"noImportAssign": "off",
"noRedeclare": "off",
"noUnsafeNegation": "off",
"useGetterReturn": "off"
}
}
}
}
]
}
Generated Vendored
+35837 -29996
View File
File diff suppressed because one or more lines are too long
Generated
+12 -12
View File
@@ -2,30 +2,30 @@
"nodes": {
"flake-schemas": {
"locked": {
"lastModified": 1721999734,
"narHash": "sha256-G5CxYeJVm4lcEtaO87LKzOsVnWeTcHGKbKxNamNWgOw=",
"rev": "0a5c42297d870156d9c57d8f99e476b738dcd982",
"revCount": 75,
"lastModified": 1693491534,
"narHash": "sha256-ifw8Td8kD08J8DxFbYjeIx5naHcDLz7s2IFP3X42I/U=",
"rev": "c702cbb663d6d70bbb716584a2ee3aeb35017279",
"revCount": 21,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/DeterminateSystems/flake-schemas/0.1.5/0190ef2f-61e0-794b-ba14-e82f225e55e6/source.tar.gz"
"url": "https://api.flakehub.com/f/pinned/DeterminateSystems/flake-schemas/0.1.1/018a4c59-80e1-708a-bb4d-854930c20f72/source.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://flakehub.com/f/DeterminateSystems/flake-schemas/0.1"
"url": "https://flakehub.com/f/DeterminateSystems/flake-schemas/%2A.tar.gz"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1748460289,
"narHash": "sha256-7doLyJBzCllvqX4gszYtmZUToxKvMUrg45EUWaUYmBg=",
"rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102",
"revCount": 807377,
"lastModified": 1696879762,
"narHash": "sha256-Ud6bH4DMcYHUDKavNMxAhcIpDGgHMyL/yaDEAVSImQY=",
"rev": "f99e5f03cc0aa231ab5950a15ed02afec45ed51a",
"revCount": 534224,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.807377%2Brev-96ec055edbe5ee227f28cdbc3f1ddf1df5965102/01972133-94d2-786e-bfeb-34136c7f0b07/source.tar.gz"
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.534224%2Brev-f99e5f03cc0aa231ab5950a15ed02afec45ed51a/018b1d3c-12f0-76a5-b796-7668d7633f08/source.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://flakehub.com/f/NixOS/nixpkgs/0.1"
"url": "https://flakehub.com/f/NixOS/nixpkgs/0.1.0.tar.gz"
}
},
"root": {
+5 -5
View File
@@ -3,13 +3,13 @@
description = "Development environment for the Nix Installer action for GitHub.";
inputs = {
flake-schemas.url = "https://flakehub.com/f/DeterminateSystems/flake-schemas/0.1";
nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1";
flake-schemas.url = "https://flakehub.com/f/DeterminateSystems/flake-schemas/*.tar.gz";
nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1.0.tar.gz";
};
outputs = { self, flake-schemas, nixpkgs }:
let
supportedSystems = [ "x86_64-linux" "aarch64-darwin" "aarch64-linux" "x86_64-darwin" ];
supportedSystems = [ "x86_64-linux" "aarch64-darwin" "aarch64-linux" ];
forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f {
pkgs = import nixpkgs { inherit system; };
});
@@ -21,9 +21,9 @@
default = pkgs.mkShell {
packages = with pkgs; [
nodejs_latest
nodePackages_latest.pnpm
biome
nixpkgs-fmt
nodePackages_latest.pnpm
nodePackages_latest.typescript-language-server
];
};
});
+17 -9
View File
@@ -7,12 +7,12 @@
"type": "module",
"scripts": {
"build": "tsup",
"format": "biome format --write",
"check-fmt": "biome format",
"lint": "biome lint",
"format": "prettier --write .",
"check-fmt": "prettier --check .",
"lint": "eslint src/**/*.ts",
"package": "ncc build",
"test": "vitest --watch false",
"all": "pnpm run test && pnpm run format && pnpm run lint && pnpm run test && pnpm run build && pnpm run package"
"all": "pnpm run test && pnpm run format && pnpm run lint && pnpm run build && pnpm run package"
},
"repository": {
"type": "git",
@@ -30,15 +30,23 @@
"@actions/exec": "^1.1.1",
"@actions/github": "^6.0.1",
"detsys-ts": "github:DeterminateSystems/detsys-ts",
"got": "^14.4.7",
"got": "^14.6.2",
"string-argv": "^0.3.2",
"vitest": "^3.2.0"
"vitest": "^3.2.4"
},
"devDependencies": {
"@types/node": "^20.17.57",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/node": "^20.19.24",
"@types/uuid": "^9.0.8",
"@vercel/ncc": "^0.38.3",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@vercel/ncc": "^0.38.4",
"eslint": "^8.57.1",
"eslint-import-resolver-typescript": "^3.10.1",
"eslint-plugin-github": "^4.10.2",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-prettier": "^5.5.4",
"prettier": "^3.6.2",
"tsup": "^8.5.0",
"typescript": "^5.8.3"
"typescript": "^5.9.3"
}
}
+5973 -2054
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1,8 +1,8 @@
import { parseEvents, getRecentEvents } from "./events.js";
import { expect, test } from "vitest";
import { getRecentEvents, parseEvents } from "./events.js";
// Handy test for locally making sure you can fetch recent events:
// biome-ignore lint/correctness/noConstantCondition: testing
// eslint-disable-next-line no-constant-condition
if (false) {
test("Parsing existing events", async () => {
expect(await getRecentEvents(new Date(Date.now() - 1000000))).toStrictEqual(
+2 -2
View File
@@ -1,6 +1,6 @@
import got from "got";
export interface Event {
export interface DEvent {
v: string;
c: string;
drv: string;
@@ -11,7 +11,7 @@ export interface Event {
}
export interface ParsedEventsResult {
readonly events: Event[];
readonly events: DEvent[];
readonly hasMismatches: boolean;
}
+10 -14
View File
@@ -5,6 +5,8 @@ import {
summarizeFailures,
} from "./failuresummary.js";
/* eslint-disable @typescript-eslint/no-non-null-assertion */
test("Select for failure events", () => {
const events = [
{
@@ -97,12 +99,10 @@ test("Summarize Failures", async () => {
}
};
// biome-ignore lint/style/noNonNullAssertion: testing
const summary: FailureSummary = (await summarizeFailures(events, logMaker))!;
expect(
summary.markdownLines.join("\n"),
).toStrictEqual(`### Build error review :boom:
expect(summary.markdownLines.join("\n"))
.toStrictEqual(`### Build error review :boom:
> [!NOTE]
> 2 builds failed
<details><summary>Failure log: <code>/nix/store/rz9hrpay90sjrid5hx3x8v606ji679xa-<strong>dep-1</strong>.drv</code></summary>
@@ -150,9 +150,8 @@ test("Summarize Failures", async () => {
</details>
`);
expect(
summary.logLines.join("\n"),
).toStrictEqual(`\u001b[38;2;255;0;0mBuild logs from 2 failures
expect(summary.logLines.join("\n"))
.toStrictEqual(`\u001b[38;2;255;0;0mBuild logs from 2 failures
The following build logs are also available in the Markdown summary:
::group::Failed build: /nix/store/rz9hrpay90sjrid5hx3x8v606ji679xa-dep-1.drv
/nix/store/rz9hrpay90sjrid5hx3x8v606ji679xa-dep-1.drv
@@ -229,16 +228,14 @@ test("Omit some logs if there are too many", async () => {
return `${drv}\n`.repeat(5).trimEnd();
};
// biome-ignore lint/style/noNonNullAssertion: testing
const summary: FailureSummary = (await summarizeFailures(
events,
logMaker,
500,
))!;
expect(
summary.markdownLines.join("\n"),
).toStrictEqual(`### Build error review :boom:
expect(summary.markdownLines.join("\n"))
.toStrictEqual(`### Build error review :boom:
> [!NOTE]
> 2 builds failed
<details><summary>Failure log: <code>/nix/store/rz9hrpay90sjrid5hx3x8v606ji679xa-<strong>dep-1</strong>.drv</code></summary>
@@ -257,9 +254,8 @@ test("Omit some logs if there are too many", async () => {
> The full logs are available in the post-run phase of the Nix Installer Action.
> * \`/nix/store/rz9hrpay90sjrid5hx3x8v606ji679xa-dep-3.drv\``);
expect(
summary.logLines.join("\n"),
).toStrictEqual(`\u001b[38;2;255;0;0mBuild logs from 2 failures
expect(summary.logLines.join("\n"))
.toStrictEqual(`\u001b[38;2;255;0;0mBuild logs from 2 failures
The following build logs are also available in the Markdown summary:
::group::Failed build: /nix/store/rz9hrpay90sjrid5hx3x8v606ji679xa-dep-1.drv
/nix/store/rz9hrpay90sjrid5hx3x8v606ji679xa-dep-1.drv
+5 -5
View File
@@ -1,14 +1,14 @@
import { stripVTControlCharacters } from "node:util";
import { getExecOutput } from "@actions/exec";
import { Event } from "./events.js";
import { DEvent } from "./events.js";
import { stripVTControlCharacters } from "node:util";
// CI summaries have a max length of "1024k" which I assume to be 1048576 bytes.
// Generously, the mermaid doc is about 50,000 bytes.
// Rounding it all down a bit further for wiggle room, that leaves lots of log space.
const defaultMaxSummaryLength = 995_000;
export function getBuildFailures(events: Event[]): Event[] {
return events.filter((event: Event): Boolean => {
export function getBuildFailures(events: DEvent[]): DEvent[] {
return events.filter((event: DEvent): Boolean => {
return event.c === "BuildFailureResponseEventV1";
});
}
@@ -19,7 +19,7 @@ export interface FailureSummary {
}
export async function summarizeFailures(
events: Event[],
events: DEvent[],
getLog: (drv: string) => Promise<string | undefined> = getLogFromNix,
maxLength: number = defaultMaxSummaryLength,
): Promise<FailureSummary | undefined> {
+90 -61
View File
@@ -1,31 +1,34 @@
import { SpawnOptions, spawn } from "node:child_process";
import fs, { mkdirSync, openSync } from "node:fs";
import { access, readFile, stat, writeFile } from "node:fs/promises";
import { userInfo } from "node:os";
import { join } from "node:path";
import { setTimeout } from "node:timers/promises";
import * as path from "path";
import * as actionsCore from "@actions/core";
import * as actionsExec from "@actions/exec";
import * as github from "@actions/github";
import { access, readFile, stat, writeFile } from "node:fs/promises";
import { join } from "node:path";
import fs, { mkdirSync, openSync } from "node:fs";
import { userInfo } from "node:os";
import stringArgv from "string-argv";
import * as path from "path";
import { DetSysAction, inputs, platform, stringifyError } from "detsys-ts";
import got from "got";
import stringArgv from "string-argv";
import { annotateMismatches } from "./annotate.js";
import { getRecentEvents } from "./events.js";
import { summarizeFailures } from "./failuresummary.js";
import { setTimeout } from "node:timers/promises";
import { getFixHashes } from "./fixHashes.js";
import { annotateMismatches } from "./annotate.js";
import { DEvent, getRecentEvents } from "./events.js";
import { makeMermaidReport } from "./mermaid.js";
import { summarizeFailures } from "./failuresummary.js";
import { SpawnOptions, spawn } from "node:child_process";
// Nix installation events
const EVENT_INSTALL_NIX_FAILURE = "install_nix_failure";
const EVENT_INSTALL_NIX_START = "install_nix_start";
const EVENT_INSTALL_NIX_SUCCESS = "install_nix_start";
const EVENT_INSTALL_NIX_SUCCESS = "install_nix_success";
const EVENT_SETUP_KVM = "setup_kvm";
const EVENT_UNINSTALL_NIX = "uninstall";
// FlakeHub events
const EVENT_LOGIN_TO_FLAKEHUB = "login_to_flakehub";
const EVENT_LOGIN_START = "flakehub-login:start";
const EVENT_LOGIN_FAILURE = "flakehub-login:failure";
const EVENT_LOGIN_SUCCESS = "flakehub-login:success";
const EVENT_LOGIN_END = "flakehub-login:end";
// Other events
const EVENT_CONCLUDE_JOB = "conclude_job";
@@ -45,6 +48,7 @@ const FACT_SENT_SIGTERM = "sent_sigterm";
// Flags
const FLAG_DETERMINATE = "--determinate";
const FLAG_PREFER_UPSTREAM_NIX = "--prefer-upstream-nix";
// Pre/post state keys
const STATE_DAEMONDIR = "DNI_DAEMONDIR";
@@ -86,6 +90,20 @@ class NixInstallerAction extends DetSysAction {
runnerOs: string | undefined;
constructor() {
if (platform.getArchOs() === "X64-macOS") {
// Holy guacamole this is ugly
actionsCore.error(
"Determinate Nix Installer no longer supports macOS on Intel. Please migrate to Apple Silicon, and use Nix's built-in Rosetta support to build for Intel. See: https://github.com/DeterminateSystems/nix-src/issues/224",
);
const sourceTag = inputs.getStringOrUndefined("source-tag");
if (sourceTag === undefined) {
actionsCore.notice(
"Pinning the installer tag to v3.12.2 (the last version to support Intel Macs) as a temporary fallback.",
);
process.env["INPUT_SOURCE-TAG"] = "v3.12.2";
}
}
super({
name: "nix-installer",
fetchStyle: "nix-style",
@@ -138,10 +156,10 @@ class NixInstallerAction extends DetSysAction {
}
async main(): Promise<void> {
actionsCore.saveState(STATE_START_DATETIME, new Date().toISOString());
await this.scienceDebugFly();
await this.detectAndForceNoSystemd();
await this.install();
actionsCore.saveState(STATE_START_DATETIME, new Date().toISOString());
}
async post(): Promise<void> {
@@ -157,7 +175,7 @@ class NixInstallerAction extends DetSysAction {
await this.reportOverall();
}
private get isMacOs(): boolean {
private get isMacOS(): boolean {
return this.runnerOs === "macOS";
}
@@ -194,22 +212,17 @@ class NixInstallerAction extends DetSysAction {
});
this.recordEvent("debug-probe-urls:response", {
// biome-ignore lint/style/useNamingConvention: Posthog JSON
debug_probe_urls_ip: resp.ip,
// biome-ignore lint/style/useNamingConvention: Posthog JSON
debug_probe_urls_ok: resp.ok,
// biome-ignore lint/style/useNamingConvention: Posthog JSON
debug_probe_urls_status_code: resp.statusCode,
// biome-ignore lint/style/useNamingConvention: Posthog JSON
debug_probe_urls_body: resp.body,
// biome-ignore lint/style/useNamingConvention: Posthog JSON
debug_probe_urls_ip: resp.ip, // eslint-disable-line camelcase
debug_probe_urls_ok: resp.ok, // eslint-disable-line camelcase
debug_probe_urls_status_code: resp.statusCode, // eslint-disable-line camelcase
debug_probe_urls_body: resp.body, // eslint-disable-line camelcase
// eslint-disable-next-line camelcase
debug_probe_urls_elapsed:
(resp.timings.end ?? 0) - resp.timings.start,
});
} catch (e: unknown) {
this.recordEvent("debug-probe-urls:exception", {
// biome-ignore lint/style/useNamingConvention: Posthog JSON
debug_probe_urls_exception: stringifyError(e),
debug_probe_urls_exception: stringifyError(e), // eslint-disable-line camelcase
});
}
} catch (err: unknown) {
@@ -287,7 +300,7 @@ class NixInstallerAction extends DetSysAction {
}
if (this.nixBuildUserBase !== null) {
executionEnv.NIX_INSTALLER_NIX_BUILD_USER_ID_BASE = `${this.nixBuildUserCount}`;
executionEnv.NIX_INSTALLER_NIX_BUILD_USER_ID_BASE = `${this.nixBuildUserBase}`;
}
if (this.nixPackageUrl !== null) {
@@ -307,14 +320,14 @@ class NixInstallerAction extends DetSysAction {
// TODO: Error if the user uses these on not-MacOS
if (this.macEncrypt !== null) {
if (!this.isMacOs) {
if (!this.isMacOS) {
throw new Error("`mac-encrypt` while `$RUNNER_OS` was not `macOS`");
}
executionEnv.NIX_INSTALLER_ENCRYPT = this.macEncrypt;
}
if (this.macCaseSensitive !== null) {
if (!this.isMacOs) {
if (!this.isMacOS) {
throw new Error(
"`mac-case-sensitive` while `$RUNNER_OS` was not `macOS`",
);
@@ -323,7 +336,7 @@ class NixInstallerAction extends DetSysAction {
}
if (this.macVolumeLabel !== null) {
if (!this.isMacOs) {
if (!this.isMacOS) {
throw new Error(
"`mac-volume-label` while `$RUNNER_OS` was not `macOS`",
);
@@ -332,7 +345,7 @@ class NixInstallerAction extends DetSysAction {
}
if (this.macRootDisk !== null) {
if (!this.isMacOs) {
if (!this.isMacOS) {
throw new Error("`mac-root-disk` while `$RUNNER_OS` was not `macOS`");
}
executionEnv.NIX_INSTALLER_ROOT_DISK = this.macRootDisk;
@@ -348,7 +361,7 @@ class NixInstallerAction extends DetSysAction {
// TODO: Error if the user uses these on MacOS
if (this.init !== null) {
if (this.isMacOs) {
if (this.isMacOS) {
throw new Error(
"`init` is not a valid option when `$RUNNER_OS` is `macOS`",
);
@@ -434,6 +447,8 @@ class NixInstallerAction extends DetSysAction {
if (this.extraArgs && !this.extraArgs.includes(FLAG_DETERMINATE)) {
args.push(FLAG_DETERMINATE);
}
} else {
args.push(FLAG_PREFER_UPSTREAM_NIX);
}
return args;
@@ -601,6 +616,7 @@ class NixInstallerAction extends DetSysAction {
await stat(socketPath);
return true;
} catch (error: unknown) {
// eslint-disable-next-line no-undef
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
actionsCore.debug(`Socket '${socketPath}' does not exist yet`);
return false;
@@ -620,6 +636,8 @@ class NixInstallerAction extends DetSysAction {
const startDate = new Date(actionsCore.getState(STATE_START_DATETIME));
const { events, hasMismatches } = await getRecentEvents(startDate);
await this.reportPassFailCount(events);
const mermaidSummary = makeMermaidReport(events);
const failureSummary = await summarizeFailures(events);
@@ -670,6 +688,29 @@ class NixInstallerAction extends DetSysAction {
}
}
async reportPassFailCount(events: DEvent[]): Promise<void> {
let built = 0;
let failed = 0;
let unknown = 0;
for (const event of events) {
switch (event.c) {
case "BuiltPathResponseEventV1":
built++;
break;
case "BuildFailureResponseEventV1":
failed++;
break;
default:
unknown++;
}
}
this.addFact("nix_builds_succeeded", built);
this.addFact("nix_builds_failed", failed);
this.addFact("nix_builds_unknown_event", unknown);
}
async setGithubPath(): Promise<void> {
// Interim versions of the `nix-installer` crate may have already manipulated `$GITHUB_PATH`, as root even! Accessing that will be an error.
try {
@@ -694,6 +735,8 @@ class NixInstallerAction extends DetSysAction {
}
async flakehubLogin(): Promise<void> {
this.recordEvent(EVENT_LOGIN_START);
const canLogin =
process.env["ACTIONS_ID_TOKEN_REQUEST_URL"] &&
process.env["ACTIONS_ID_TOKEN_REQUEST_TOKEN"];
@@ -704,14 +747,20 @@ class NixInstallerAction extends DetSysAction {
const head = pr?.head?.repo?.full_name;
if (pr && base !== head) {
this.recordEvent(EVENT_LOGIN_FAILURE, { reason: "fork" });
this.recordEvent(EVENT_LOGIN_END);
actionsCore.info(
`Not logging in to FlakeHub: GitHub Actions does not allow OIDC authentication from forked repositories ("${head}" is not the same repository as "${base}").`,
`FlakeHub is disabled because this is a fork. GitHub Actions does not allow OIDC authentication from forked repositories ("${head}" is not from the same repository as "${base}").`,
);
return;
}
this.recordEvent(EVENT_LOGIN_FAILURE, { reason: "not-configured" });
this.recordEvent(EVENT_LOGIN_END);
actionsCore.info(
`Not logging in to FlakeHub: GitHub Actions has not provided OIDC token endpoints; please make sure that \`id-token: write\` and \`contents: read\` are set for this step's (or job's) permissions.`,
"FlakeHub is disabled because the workflow is misconfigured. Please make sure that `id-token: write` and `contents: read` are set for this step's (or job's) permissions so that GitHub Actions provides OIDC token endpoints.",
);
actionsCore.info(
`For more information, see https://docs.determinate.systems/guides/github-actions/#nix-installer-action`,
@@ -720,15 +769,18 @@ class NixInstallerAction extends DetSysAction {
}
actionsCore.startGroup("Logging in to FlakeHub");
this.recordEvent(EVENT_LOGIN_TO_FLAKEHUB);
try {
await actionsExec.exec(`determinate-nixd`, ["login", "github-action"]);
this.recordEvent(EVENT_LOGIN_SUCCESS);
} catch (e: unknown) {
actionsCore.warning(`FlakeHub Login failure: ${stringifyError(e)}`);
this.recordEvent("flakehub-login:failure", {
this.recordEvent(EVENT_LOGIN_FAILURE, {
reason: "failed",
exception: stringifyError(e),
});
}
this.recordEvent(EVENT_LOGIN_END);
actionsCore.endGroup();
}
@@ -739,7 +791,6 @@ class NixInstallerAction extends DetSysAction {
["uninstall"],
{
env: {
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_NO_CONFIRM: "true",
...process.env, // To get $PATH, etc
},
@@ -955,7 +1006,7 @@ class NixInstallerAction extends DetSysAction {
}
private get defaultPlanner(): string {
if (this.isMacOs) {
if (this.isMacOS) {
return "macos";
} else if (this.isLinux) {
return "linux";
@@ -1001,51 +1052,29 @@ class NixInstallerAction extends DetSysAction {
}
}
// All env vars are strings, no fanciness here.
type ExecuteEnvironment = {
// biome-ignore lint/style/useNamingConvention: environment variable
// All env vars are strings, no fanciness here.
RUST_BACKTRACE?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_MODIFY_PROFILE?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_NIX_BUILD_GROUP_NAME?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_NIX_BUILD_GROUP_ID?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_NIX_BUILD_USER_PREFIX?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_NIX_BUILD_USER_COUNT?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_NIX_BUILD_USER_ID_BASE?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_NIX_PACKAGE_URL?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_PROXY?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_SSL_CERT_FILE?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_DIAGNOSTIC_ENDPOINT?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_DIAGNOSTIC_ATTRIBUTION?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_ENCRYPT?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_CASE_SENSITIVE?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_VOLUME_LABEL?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_ROOT_DISK?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_INIT?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_START_DAEMON?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_NO_CONFIRM?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_EXTRA_CONF?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_LOG_DIRECTIVES?: string;
// biome-ignore lint/style/useNamingConvention: environment variable
NIX_INSTALLER_LOGGER?: string;
};
+6 -24
View File
@@ -1,9 +1,11 @@
import { mermaidify, makeMermaidReport } from "./mermaid.js";
import { DEvent, parseEvents } from "./events.js";
import { expect, test } from "vitest";
import { Event, parseEvents } from "./events.js";
import { makeMermaidReport, mermaidify } from "./mermaid.js";
function generateEvents(count: number): Event[] {
const events: Event[] = [];
/* eslint-disable @typescript-eslint/no-non-null-assertion */
function generateEvents(count: number): DEvent[] {
const events: DEvent[] = [];
for (let i = 0; i < count; i++) {
events.push({
@@ -27,21 +29,16 @@ test("Empty event list returns no report", () => {
});
test("Create a very large report doc and make sure it is small enough", () => {
// biome-ignore lint/style/noNonNullAssertion: testing
const report = makeMermaidReport(generateEvents(2500))!;
// Assert the `.drv` suffix was pruned (1 reference = the NOTE at the end)
// biome-ignore lint/style/noNonNullAssertion: testing
expect(report.match(/\.drv/g)!.length).equals(1);
// Assert the `/nix/store` prefix was pruned (1 reference = the NOTE at the end)
// biome-ignore lint/style/noNonNullAssertion: testing
expect(report.match(/\/nix\/store\//g)!.length).equals(1);
// Assert that some events were pruned
// biome-ignore lint/style/noNonNullAssertion: testing
expect(report.match(/dep-/g)!.length).lessThan(2500);
// biome-ignore lint/style/noNonNullAssertion: testing
expect(report.match(/dep-/g)!.length).greaterThan(1500);
expect(report).toContain("suffix, and builds that took less than ");
@@ -52,19 +49,15 @@ test("Create a very large report doc and make sure it is small enough", () => {
test("Create a medium large report doc and make sure it is small enough", () => {
const eventCount = 675;
// biome-ignore lint/style/noNonNullAssertion: testing
const report = makeMermaidReport(generateEvents(eventCount))!;
// Assert the `.drv` suffix was pruned (1 reference = the NOTE at the end)
// biome-ignore lint/style/noNonNullAssertion: testing
expect(report.match(/\.drv/g)!.length).equals(1);
// Assert the `/nix/store` prefix was pruned (1 reference = the NOTE at the end)
// biome-ignore lint/style/noNonNullAssertion: testing
expect(report.match(/\/nix\/store\//g)!.length).equals(1);
// Assert that no lines were pruned
// biome-ignore lint/style/noNonNullAssertion: testing
expect(report.match(/dep-/g)!.length).toStrictEqual(eventCount);
expect(report).toContain(
@@ -76,15 +69,12 @@ test("Create a medium large report doc and make sure it is small enough", () =>
});
test("Create a small report doc and make sure it isn't pruned", () => {
// biome-ignore lint/style/noNonNullAssertion: testing
const report = makeMermaidReport(generateEvents(100))!;
// Assert 100 events have the `.drv` suffix, ie: were not pruned
// biome-ignore lint/style/noNonNullAssertion: testing
expect(report.match(/\.drv/g)!.length).equals(100);
// Assert 100 events have the `.drv` suffix, ie: were not pruned
// biome-ignore lint/style/noNonNullAssertion: testing
expect(report.match(/\/nix\/store\//g)!.length).equals(100);
expect(report.length).lessThan(50000);
@@ -93,13 +83,9 @@ test("Create a small report doc and make sure it isn't pruned", () => {
test("Generate a really big report and shrink it", () => {
const events = generateEvents(1000);
// biome-ignore lint/style/noNonNullAssertion: testing
const originalLength = mermaidify(events, -1)!.length;
// biome-ignore lint/style/noNonNullAssertion: testing
const limitedLengthZero = mermaidify(events, 0)!.length;
// biome-ignore lint/style/noNonNullAssertion: testing
const limitedLengthOne = mermaidify(events, 1)!.length;
// biome-ignore lint/style/noNonNullAssertion: testing
const limitedLengthTwo = mermaidify(events, 2)!.length;
expect(originalLength).greaterThan(limitedLengthZero);
@@ -187,13 +173,9 @@ hash-mismatch-md5-base16 (4s):crit, 3, 4s
test("Generate a really big report and shrink it", () => {
const events = generateEvents(1000);
// biome-ignore lint/style/noNonNullAssertion: testing
const originalLength = mermaidify(events, -1)!.length;
// biome-ignore lint/style/noNonNullAssertion: testing
const limitedLengthZero = mermaidify(events, 0)!.length;
// biome-ignore lint/style/noNonNullAssertion: testing
const limitedLengthOne = mermaidify(events, 1)!.length;
// biome-ignore lint/style/noNonNullAssertion: testing
const limitedLengthTwo = mermaidify(events, 2)!.length;
expect(originalLength).greaterThan(limitedLengthZero);
+3 -3
View File
@@ -1,7 +1,7 @@
import { Event } from "./events.js";
import { DEvent } from "./events.js";
import { truncateDerivation } from "./util.js";
export function makeMermaidReport(events: Event[]): string | undefined {
export function makeMermaidReport(events: DEvent[]): string | undefined {
// # 50k is the max: https://github.com/mermaid-js/mermaid/blob/c269dc822c528e1afbde34e18a1cad03d972d4fe/src/defaultConfig.js#L55
const maxLength = 49900;
let mermaid = "";
@@ -42,7 +42,7 @@ export function makeMermaidReport(events: Event[]): string | undefined {
}
export function mermaidify(
allEvents: Event[],
allEvents: DEvent[],
pruneLevel: number,
): string | undefined {
const events = allEvents