├── .node-version ├── .prettierignore ├── .prettierrc ├── .gitignore ├── .github ├── dependabot.yml └── workflows │ ├── build.yml │ └── release.yml ├── tsconfig.json ├── src ├── index.ts ├── utils.ts └── stages │ ├── install.ts │ ├── configure.ts │ └── push.ts ├── flake.lock ├── flake.nix ├── package.json ├── README.md ├── LICENSE ├── action.yml └── pnpm-lock.yaml /.node-version: -------------------------------------------------------------------------------- 1 | 24 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .direnv/ 2 | dist/ 3 | 4 | pnpm-lock.yaml 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "printWidth": 120 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | node_modules/ 4 | 5 | # nix 6 | .direnv/ 7 | .envrc 8 | result* 9 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "weekly" 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "skipLibCheck": true, 5 | "target": "es2022", 6 | "allowJs": true, 7 | "resolveJsonModule": true, 8 | "moduleDetection": "force", 9 | "isolatedModules": true, 10 | "verbatimModuleSyntax": true, 11 | "strict": true, 12 | "noUncheckedIndexedAccess": true, 13 | "noImplicitOverride": true, 14 | "module": "preserve", 15 | "noEmit": true, 16 | "lib": ["es2022"] 17 | }, 18 | "include": ["**/*.js", "**/*.ts"], 19 | "exclude": ["node_modules/*", "**/node_modules/*", "dist/*"] 20 | } 21 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { install, isInstalled } from "./stages/install"; 2 | import { configure } from "./stages/configure"; 3 | import { push } from "./stages/push"; 4 | import { getState, saveState, info } from "@actions/core"; 5 | 6 | const isPost = !!getState("isPost"); 7 | 8 | const main = async () => { 9 | if (await isInstalled()) { 10 | info("Skipping attic installation because it is already installed"); 11 | } else { 12 | await install(); 13 | } 14 | await configure(); 15 | }; 16 | 17 | if (!isPost) { 18 | saveState("isPost", true); 19 | main(); 20 | } else { 21 | push(); 22 | } 23 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import { exec } from "@actions/exec"; 2 | 3 | import { readFile } from "node:fs/promises"; 4 | 5 | export const saveStorePaths = async () => { 6 | await exec("sh", ["-c", "nix path-info --all --json > /tmp/store-paths"]); 7 | }; 8 | 9 | export const getStorePaths = async () => { 10 | const rawStorePaths = JSON.parse(await readFile("/tmp/store-paths", "utf8")) as { path: string }[]; 11 | 12 | // compatibility with Nix 2.18 13 | if (Array.isArray(rawStorePaths)) { 14 | return rawStorePaths.map((path) => path.path); 15 | } 16 | 17 | return Object.keys(rawStorePaths); 18 | }; 19 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1755027561, 6 | "narHash": "sha256-IVft239Bc8p8Dtvf7UAACMG5P3ZV+3/aO28gXpGtMXI=", 7 | "owner": "NixOS", 8 | "repo": "nixpkgs", 9 | "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "NixOS", 14 | "ref": "nixos-unstable", 15 | "repo": "nixpkgs", 16 | "type": "github" 17 | } 18 | }, 19 | "root": { 20 | "inputs": { 21 | "nixpkgs": "nixpkgs" 22 | } 23 | } 24 | }, 25 | "root": "root", 26 | "version": 7 27 | } 28 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: "Build" 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | workflow_call: 7 | workflow_dispatch: 8 | 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | os: [ubuntu-latest, macos-latest] 14 | 15 | runs-on: ${{ matrix.os }} 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v5 20 | 21 | - uses: pnpm/action-setup@v4 22 | - uses: actions/setup-node@v4 23 | with: 24 | node-version-file: .node-version 25 | cache: pnpm 26 | cache-dependency-path: pnpm-lock.yaml 27 | 28 | - name: Install dependencies 29 | run: pnpm install 30 | 31 | - name: Build 32 | run: pnpm run build 33 | -------------------------------------------------------------------------------- /src/stages/install.ts: -------------------------------------------------------------------------------- 1 | import * as core from "@actions/core"; 2 | import { exec } from "@actions/exec"; 3 | import { findInPath } from "@actions/io"; 4 | 5 | export const install = async () => { 6 | core.startGroup("Install Attic"); 7 | 8 | core.info("Installing Attic"); 9 | 10 | const inputsFrom = core.getInput("inputs-from"); 11 | 12 | try { 13 | if (inputsFrom) { 14 | await exec("nix", ["profile", "install", "--inputs-from", inputsFrom, "nixpkgs#attic-client"]); 15 | } else { 16 | await exec("nix", ["profile", "install", "github:NixOS/nixpkgs/nixpkgs-unstable#attic-client"]); 17 | } 18 | } catch (e) { 19 | core.setFailed(`Action failed with error: ${e}`); 20 | } 21 | 22 | core.endGroup(); 23 | }; 24 | 25 | export const isInstalled = async () => { 26 | return (await findInPath("attic")).length > 0; 27 | }; 28 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | release: 5 | types: [published, edited] 6 | 7 | jobs: 8 | release: 9 | runs-on: ubuntu-latest 10 | 11 | permissions: 12 | contents: write 13 | 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v5 17 | with: 18 | ref: ${{ github.event.release.tag_name }} 19 | 20 | - uses: pnpm/action-setup@v4 21 | - uses: actions/setup-node@v4 22 | with: 23 | node-version-file: .node-version 24 | cache: pnpm 25 | cache-dependency-path: pnpm-lock.yaml 26 | 27 | - name: Install dependencies 28 | run: pnpm install 29 | 30 | - name: Build 31 | run: pnpm run build 32 | 33 | - uses: JasonEtco/build-and-tag-action@v2 34 | env: 35 | GITHUB_TOKEN: ${{ github.token }} 36 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Github Action for caching Nix derivations with Attic"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 6 | }; 7 | 8 | outputs = 9 | { nixpkgs, ... }: 10 | let 11 | systems = [ 12 | "x86_64-linux" 13 | "aarch64-linux" 14 | "x86_64-darwin" 15 | "aarch64-darwin" 16 | ]; 17 | 18 | forAllSystems = fn: nixpkgs.lib.genAttrs systems (system: fn nixpkgs.legacyPackages.${system}); 19 | in 20 | { 21 | devShells = forAllSystems (pkgs: { 22 | default = pkgs.mkShell { 23 | packages = with pkgs; [ 24 | actionlint 25 | nodejs_20 26 | (nodePackages_latest.pnpm.override { nodejs = nodejs_20; }) 27 | ]; 28 | }; 29 | }); 30 | 31 | formatter = forAllSystems (p: p.nixfmt-rfc-style); 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ryanccn/attic-action", 3 | "main": "dist/index.js", 4 | "description": "Cache Nix derivations with Attic", 5 | "scripts": { 6 | "build": "esbuild src/index.ts --outdir=dist --platform=node --format=cjs --bundle --minify-whitespace --minify-syntax", 7 | "format": "prettier --write ." 8 | }, 9 | "author": "Ryan Cao ", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@actions/core": "^1.11.1", 13 | "@actions/exec": "^1.1.1", 14 | "@actions/io": "^1.1.3" 15 | }, 16 | "devDependencies": { 17 | "@types/node": "^24.3.0", 18 | "esbuild": "^0.25.9", 19 | "prettier": "3.6.2", 20 | "typescript": "^5.9.2" 21 | }, 22 | "pnpm": { 23 | "onlyBuiltDependencies": [ 24 | "esbuild" 25 | ] 26 | }, 27 | "packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748" 28 | } 29 | -------------------------------------------------------------------------------- /src/stages/configure.ts: -------------------------------------------------------------------------------- 1 | import * as core from "@actions/core"; 2 | import { exec } from "@actions/exec"; 3 | import { saveStorePaths } from "../utils"; 4 | 5 | export const configure = async () => { 6 | core.startGroup("Configure Attic"); 7 | 8 | try { 9 | const endpoint = core.getInput("endpoint"); 10 | const cache = core.getInput("cache"); 11 | const token = core.getInput("token"); 12 | const skipUse = core.getInput("skip-use"); 13 | 14 | core.info("Logging in to Attic cache"); 15 | await exec("attic", ["login", "--set-default", cache, endpoint, token]); 16 | 17 | if (skipUse === "true") { 18 | core.info("Not adding Attic cache to substituters as skip-use is set to true"); 19 | } else { 20 | core.info("Adding Attic cache to substituters"); 21 | await exec("attic", ["use", cache]); 22 | } 23 | 24 | core.info("Collecting store paths before build"); 25 | await saveStorePaths(); 26 | } catch (e) { 27 | core.setFailed(`Action failed with error: ${e}`); 28 | } 29 | 30 | core.endGroup(); 31 | }; 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # attic-action 2 | 3 | Cache Nix derivations with [Attic](https://github.com/zhaofengli/attic). 4 | 5 | ## Usage 6 | 7 | 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: 8 | 9 | ```yaml 10 | - name: Setup Attic cache 11 | uses: ryanccn/attic-action@v0 12 | with: 13 | endpoint: ${{ secrets.ATTIC_ENDPOINT }} 14 | cache: ${{ secrets.ATTIC_CACHE }} 15 | token: ${{ secrets.ATTIC_TOKEN }} 16 | ``` 17 | 18 | ## Inputs 19 | 20 | ### `endpoint` 21 | 22 | The Attic endpoint. This is the URL without the cache name. 23 | 24 | ### `cache` 25 | 26 | The name of the Attic cache. 27 | 28 | ### `token` 29 | 30 | The authorization token to provide to Attic (**optional**). 31 | 32 | ### `skip-push` 33 | 34 | Disable pushing new derivations to the cache automatically at the end of the job (**default is false**). 35 | 36 | This requires you to invoke `attic push ` with the paths you want to push to the cache manually. 37 | 38 | ## Outputs 39 | 40 | None 41 | 42 | ## License 43 | 44 | MIT 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ryan Cao 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: "attic-action" 2 | author: "Ryan Cao" 3 | description: "Cache Nix derivations with Attic" 4 | 5 | branding: 6 | icon: "layers" 7 | color: "blue" 8 | 9 | inputs: 10 | endpoint: 11 | description: "Attic endpoint" 12 | required: true 13 | cache: 14 | description: "Attic cache name" 15 | required: true 16 | inputs-from: 17 | description: "Path to get the Nixpkgs flake input from instead of `github:NixOS/nixpkgs/nixpkgs-unstable`" 18 | required: false 19 | include-paths: 20 | description: "Regular expressions for matching paths to include when pushing (delimited by newlines)" 21 | required: false 22 | exclude-paths: 23 | description: "Regular expressions for matching paths to exclude when pushing (delimited by newlines)" 24 | required: false 25 | skip-push: 26 | description: "Disable pushing to the cache automatically" 27 | required: false 28 | token: 29 | description: "Attic authorization token" 30 | required: false 31 | skip-use: 32 | description: "Set to true to skip using Attic cache as a substituter" 33 | required: false 34 | 35 | runs: 36 | using: "node24" 37 | main: "dist/index.js" 38 | post: "dist/index.js" 39 | -------------------------------------------------------------------------------- /src/stages/push.ts: -------------------------------------------------------------------------------- 1 | import * as core from "@actions/core"; 2 | import { exec } from "@actions/exec"; 3 | 4 | import { saveStorePaths, getStorePaths } from "../utils"; 5 | 6 | export const push = async () => { 7 | core.startGroup("Push to Attic"); 8 | 9 | try { 10 | const skipPush = core.getInput("skip-push"); 11 | 12 | if (skipPush === "true") { 13 | core.info("Pushing to cache is disabled by skip-push"); 14 | } else { 15 | const cache = core.getInput("cache"); 16 | core.info("Pushing to cache"); 17 | 18 | const oldPaths = await getStorePaths(); 19 | await saveStorePaths(); 20 | const newPaths = await getStorePaths(); 21 | 22 | let pushPaths = newPaths 23 | .filter((p) => !oldPaths.includes(p)) 24 | .filter( 25 | (p) => !p.endsWith(".drv") && !p.endsWith(".drv.chroot") && !p.endsWith(".check") && !p.endsWith(".lock"), 26 | ); 27 | 28 | const includePaths = core.getMultilineInput("include-paths").map((v) => new RegExp(v)); 29 | if (includePaths.length > 0) { 30 | pushPaths = pushPaths.filter((p) => includePaths.some((v) => v.test(p))); 31 | } 32 | 33 | const excludePaths = core.getMultilineInput("exclude-paths").map((v) => new RegExp(v)); 34 | if (excludePaths.length > 0) { 35 | pushPaths = pushPaths.filter((p) => !excludePaths.some((v) => v.test(p))); 36 | } 37 | 38 | await exec("attic", ["push", "--stdin", cache], { 39 | input: Buffer.from(pushPaths.join("\n")), 40 | }); 41 | } 42 | } catch (e) { 43 | core.warning(`Action encountered error: ${e}`); 44 | core.info("Not considering errors during push a failure."); 45 | } 46 | 47 | core.endGroup(); 48 | }; 49 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | '@actions/core': 12 | specifier: ^1.11.1 13 | version: 1.11.1 14 | '@actions/exec': 15 | specifier: ^1.1.1 16 | version: 1.1.1 17 | '@actions/io': 18 | specifier: ^1.1.3 19 | version: 1.1.3 20 | devDependencies: 21 | '@types/node': 22 | specifier: ^24.3.0 23 | version: 24.3.0 24 | esbuild: 25 | specifier: ^0.25.9 26 | version: 0.25.9 27 | prettier: 28 | specifier: 3.6.2 29 | version: 3.6.2 30 | typescript: 31 | specifier: ^5.9.2 32 | version: 5.9.2 33 | 34 | packages: 35 | 36 | '@actions/core@1.11.1': 37 | resolution: {integrity: sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==} 38 | 39 | '@actions/exec@1.1.1': 40 | resolution: {integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==} 41 | 42 | '@actions/http-client@2.2.3': 43 | resolution: {integrity: sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==} 44 | 45 | '@actions/io@1.1.3': 46 | resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==} 47 | 48 | '@esbuild/aix-ppc64@0.25.9': 49 | resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==} 50 | engines: {node: '>=18'} 51 | cpu: [ppc64] 52 | os: [aix] 53 | 54 | '@esbuild/android-arm64@0.25.9': 55 | resolution: {integrity: sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==} 56 | engines: {node: '>=18'} 57 | cpu: [arm64] 58 | os: [android] 59 | 60 | '@esbuild/android-arm@0.25.9': 61 | resolution: {integrity: sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==} 62 | engines: {node: '>=18'} 63 | cpu: [arm] 64 | os: [android] 65 | 66 | '@esbuild/android-x64@0.25.9': 67 | resolution: {integrity: sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==} 68 | engines: {node: '>=18'} 69 | cpu: [x64] 70 | os: [android] 71 | 72 | '@esbuild/darwin-arm64@0.25.9': 73 | resolution: {integrity: sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==} 74 | engines: {node: '>=18'} 75 | cpu: [arm64] 76 | os: [darwin] 77 | 78 | '@esbuild/darwin-x64@0.25.9': 79 | resolution: {integrity: sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==} 80 | engines: {node: '>=18'} 81 | cpu: [x64] 82 | os: [darwin] 83 | 84 | '@esbuild/freebsd-arm64@0.25.9': 85 | resolution: {integrity: sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==} 86 | engines: {node: '>=18'} 87 | cpu: [arm64] 88 | os: [freebsd] 89 | 90 | '@esbuild/freebsd-x64@0.25.9': 91 | resolution: {integrity: sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==} 92 | engines: {node: '>=18'} 93 | cpu: [x64] 94 | os: [freebsd] 95 | 96 | '@esbuild/linux-arm64@0.25.9': 97 | resolution: {integrity: sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==} 98 | engines: {node: '>=18'} 99 | cpu: [arm64] 100 | os: [linux] 101 | 102 | '@esbuild/linux-arm@0.25.9': 103 | resolution: {integrity: sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==} 104 | engines: {node: '>=18'} 105 | cpu: [arm] 106 | os: [linux] 107 | 108 | '@esbuild/linux-ia32@0.25.9': 109 | resolution: {integrity: sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==} 110 | engines: {node: '>=18'} 111 | cpu: [ia32] 112 | os: [linux] 113 | 114 | '@esbuild/linux-loong64@0.25.9': 115 | resolution: {integrity: sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==} 116 | engines: {node: '>=18'} 117 | cpu: [loong64] 118 | os: [linux] 119 | 120 | '@esbuild/linux-mips64el@0.25.9': 121 | resolution: {integrity: sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==} 122 | engines: {node: '>=18'} 123 | cpu: [mips64el] 124 | os: [linux] 125 | 126 | '@esbuild/linux-ppc64@0.25.9': 127 | resolution: {integrity: sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==} 128 | engines: {node: '>=18'} 129 | cpu: [ppc64] 130 | os: [linux] 131 | 132 | '@esbuild/linux-riscv64@0.25.9': 133 | resolution: {integrity: sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==} 134 | engines: {node: '>=18'} 135 | cpu: [riscv64] 136 | os: [linux] 137 | 138 | '@esbuild/linux-s390x@0.25.9': 139 | resolution: {integrity: sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==} 140 | engines: {node: '>=18'} 141 | cpu: [s390x] 142 | os: [linux] 143 | 144 | '@esbuild/linux-x64@0.25.9': 145 | resolution: {integrity: sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==} 146 | engines: {node: '>=18'} 147 | cpu: [x64] 148 | os: [linux] 149 | 150 | '@esbuild/netbsd-arm64@0.25.9': 151 | resolution: {integrity: sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==} 152 | engines: {node: '>=18'} 153 | cpu: [arm64] 154 | os: [netbsd] 155 | 156 | '@esbuild/netbsd-x64@0.25.9': 157 | resolution: {integrity: sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==} 158 | engines: {node: '>=18'} 159 | cpu: [x64] 160 | os: [netbsd] 161 | 162 | '@esbuild/openbsd-arm64@0.25.9': 163 | resolution: {integrity: sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==} 164 | engines: {node: '>=18'} 165 | cpu: [arm64] 166 | os: [openbsd] 167 | 168 | '@esbuild/openbsd-x64@0.25.9': 169 | resolution: {integrity: sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==} 170 | engines: {node: '>=18'} 171 | cpu: [x64] 172 | os: [openbsd] 173 | 174 | '@esbuild/openharmony-arm64@0.25.9': 175 | resolution: {integrity: sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==} 176 | engines: {node: '>=18'} 177 | cpu: [arm64] 178 | os: [openharmony] 179 | 180 | '@esbuild/sunos-x64@0.25.9': 181 | resolution: {integrity: sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==} 182 | engines: {node: '>=18'} 183 | cpu: [x64] 184 | os: [sunos] 185 | 186 | '@esbuild/win32-arm64@0.25.9': 187 | resolution: {integrity: sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==} 188 | engines: {node: '>=18'} 189 | cpu: [arm64] 190 | os: [win32] 191 | 192 | '@esbuild/win32-ia32@0.25.9': 193 | resolution: {integrity: sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==} 194 | engines: {node: '>=18'} 195 | cpu: [ia32] 196 | os: [win32] 197 | 198 | '@esbuild/win32-x64@0.25.9': 199 | resolution: {integrity: sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==} 200 | engines: {node: '>=18'} 201 | cpu: [x64] 202 | os: [win32] 203 | 204 | '@fastify/busboy@2.1.1': 205 | resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} 206 | engines: {node: '>=14'} 207 | 208 | '@types/node@24.3.0': 209 | resolution: {integrity: sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==} 210 | 211 | esbuild@0.25.9: 212 | resolution: {integrity: sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==} 213 | engines: {node: '>=18'} 214 | hasBin: true 215 | 216 | prettier@3.6.2: 217 | resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} 218 | engines: {node: '>=14'} 219 | hasBin: true 220 | 221 | tunnel@0.0.6: 222 | resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} 223 | engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} 224 | 225 | typescript@5.9.2: 226 | resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} 227 | engines: {node: '>=14.17'} 228 | hasBin: true 229 | 230 | undici-types@7.10.0: 231 | resolution: {integrity: sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==} 232 | 233 | undici@5.29.0: 234 | resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} 235 | engines: {node: '>=14.0'} 236 | 237 | snapshots: 238 | 239 | '@actions/core@1.11.1': 240 | dependencies: 241 | '@actions/exec': 1.1.1 242 | '@actions/http-client': 2.2.3 243 | 244 | '@actions/exec@1.1.1': 245 | dependencies: 246 | '@actions/io': 1.1.3 247 | 248 | '@actions/http-client@2.2.3': 249 | dependencies: 250 | tunnel: 0.0.6 251 | undici: 5.29.0 252 | 253 | '@actions/io@1.1.3': {} 254 | 255 | '@esbuild/aix-ppc64@0.25.9': 256 | optional: true 257 | 258 | '@esbuild/android-arm64@0.25.9': 259 | optional: true 260 | 261 | '@esbuild/android-arm@0.25.9': 262 | optional: true 263 | 264 | '@esbuild/android-x64@0.25.9': 265 | optional: true 266 | 267 | '@esbuild/darwin-arm64@0.25.9': 268 | optional: true 269 | 270 | '@esbuild/darwin-x64@0.25.9': 271 | optional: true 272 | 273 | '@esbuild/freebsd-arm64@0.25.9': 274 | optional: true 275 | 276 | '@esbuild/freebsd-x64@0.25.9': 277 | optional: true 278 | 279 | '@esbuild/linux-arm64@0.25.9': 280 | optional: true 281 | 282 | '@esbuild/linux-arm@0.25.9': 283 | optional: true 284 | 285 | '@esbuild/linux-ia32@0.25.9': 286 | optional: true 287 | 288 | '@esbuild/linux-loong64@0.25.9': 289 | optional: true 290 | 291 | '@esbuild/linux-mips64el@0.25.9': 292 | optional: true 293 | 294 | '@esbuild/linux-ppc64@0.25.9': 295 | optional: true 296 | 297 | '@esbuild/linux-riscv64@0.25.9': 298 | optional: true 299 | 300 | '@esbuild/linux-s390x@0.25.9': 301 | optional: true 302 | 303 | '@esbuild/linux-x64@0.25.9': 304 | optional: true 305 | 306 | '@esbuild/netbsd-arm64@0.25.9': 307 | optional: true 308 | 309 | '@esbuild/netbsd-x64@0.25.9': 310 | optional: true 311 | 312 | '@esbuild/openbsd-arm64@0.25.9': 313 | optional: true 314 | 315 | '@esbuild/openbsd-x64@0.25.9': 316 | optional: true 317 | 318 | '@esbuild/openharmony-arm64@0.25.9': 319 | optional: true 320 | 321 | '@esbuild/sunos-x64@0.25.9': 322 | optional: true 323 | 324 | '@esbuild/win32-arm64@0.25.9': 325 | optional: true 326 | 327 | '@esbuild/win32-ia32@0.25.9': 328 | optional: true 329 | 330 | '@esbuild/win32-x64@0.25.9': 331 | optional: true 332 | 333 | '@fastify/busboy@2.1.1': {} 334 | 335 | '@types/node@24.3.0': 336 | dependencies: 337 | undici-types: 7.10.0 338 | 339 | esbuild@0.25.9: 340 | optionalDependencies: 341 | '@esbuild/aix-ppc64': 0.25.9 342 | '@esbuild/android-arm': 0.25.9 343 | '@esbuild/android-arm64': 0.25.9 344 | '@esbuild/android-x64': 0.25.9 345 | '@esbuild/darwin-arm64': 0.25.9 346 | '@esbuild/darwin-x64': 0.25.9 347 | '@esbuild/freebsd-arm64': 0.25.9 348 | '@esbuild/freebsd-x64': 0.25.9 349 | '@esbuild/linux-arm': 0.25.9 350 | '@esbuild/linux-arm64': 0.25.9 351 | '@esbuild/linux-ia32': 0.25.9 352 | '@esbuild/linux-loong64': 0.25.9 353 | '@esbuild/linux-mips64el': 0.25.9 354 | '@esbuild/linux-ppc64': 0.25.9 355 | '@esbuild/linux-riscv64': 0.25.9 356 | '@esbuild/linux-s390x': 0.25.9 357 | '@esbuild/linux-x64': 0.25.9 358 | '@esbuild/netbsd-arm64': 0.25.9 359 | '@esbuild/netbsd-x64': 0.25.9 360 | '@esbuild/openbsd-arm64': 0.25.9 361 | '@esbuild/openbsd-x64': 0.25.9 362 | '@esbuild/openharmony-arm64': 0.25.9 363 | '@esbuild/sunos-x64': 0.25.9 364 | '@esbuild/win32-arm64': 0.25.9 365 | '@esbuild/win32-ia32': 0.25.9 366 | '@esbuild/win32-x64': 0.25.9 367 | 368 | prettier@3.6.2: {} 369 | 370 | tunnel@0.0.6: {} 371 | 372 | typescript@5.9.2: {} 373 | 374 | undici-types@7.10.0: {} 375 | 376 | undici@5.29.0: 377 | dependencies: 378 | '@fastify/busboy': 2.1.1 379 | --------------------------------------------------------------------------------