diff --git a/.github/workflows/test-cache.yml b/.github/workflows/test-cache.yml index 7bff674..96df107 100644 --- a/.github/workflows/test-cache.yml +++ b/.github/workflows/test-cache.yml @@ -21,7 +21,7 @@ jobs: uses: ./ with: enable-cache: true - cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }} + cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache - run: uv sync working-directory: __tests__/fixtures/uv-project test-restore-cache: @@ -37,7 +37,7 @@ jobs: uses: ./ with: enable-cache: true - cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }} + cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache - name: Cache was hit run: | if [ "$CACHE_HIT" != "true" ]; then @@ -59,7 +59,7 @@ jobs: cache-dependency-glob: | __tests__/fixtures/uv-project/uv.lock **/pyproject.toml - cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }} + cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-dependency-glob - run: uv sync working-directory: __tests__/fixtures/uv-project test-restore-cache-dependency-glob: @@ -79,7 +79,8 @@ jobs: cache-dependency-glob: | __tests__/fixtures/uv-project/uv.lock **/pyproject.toml - cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }} + cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-dependency-glob + ignore-nothing-to-cache: true - name: Cache was not hit run: | if [ "$CACHE_HIT" == "true" ]; then @@ -96,7 +97,7 @@ jobs: uses: ./ with: enable-cache: true - cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }} + cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-local cache-local-path: /tmp/uv-cache - run: uv sync working-directory: __tests__/fixtures/uv-project @@ -110,7 +111,7 @@ jobs: uses: ./ with: enable-cache: true - cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }} + cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-local cache-local-path: /tmp/uv-cache - name: Cache was hit run: | @@ -122,38 +123,38 @@ jobs: - run: uv sync working-directory: __tests__/fixtures/uv-project - prepare-tilde-expansion-tests: + test-tilde-expansion-cache-local-path: runs-on: selfhosted-ubuntu-arm64 steps: + - uses: actions/checkout@v4 - name: Create cache directory run: mkdir -p ~/uv-cache shell: bash - - name: Create cache dependency glob file - run: touch ~/uv-cache.glob - shell: bash - - test-tilde-expansion-cache-local-path: - needs: prepare-tilde-expansion-tests - runs-on: selfhosted-ubuntu-arm64 - steps: - - uses: actions/checkout@v4 - name: Setup with cache uses: ./ with: - enable-cache: true cache-local-path: ~/uv-cache/cache-local-path + - run: uv sync + working-directory: __tests__/fixtures/uv-project test-tilde-expansion-cache-dependency-glob: - needs: prepare-tilde-expansion-tests runs-on: selfhosted-ubuntu-arm64 steps: - uses: actions/checkout@v4 + - name: Create cache directory + run: mkdir -p ~/uv-cache + shell: bash + - name: Create cache dependency glob file + run: touch ~/uv-cache.glob + shell: bash - name: Setup with cache uses: ./ with: enable-cache: true cache-local-path: ~/uv-cache/cache-dependency-glob cache-dependency-glob: "~/uv-cache.glob" + - run: uv sync + working-directory: __tests__/fixtures/uv-project cleanup-tilde-expansion-tests: needs: diff --git a/README.md b/README.md index fbf26a4..73a1c1b 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ Set up your GitHub Actions workflow with a specific version of [uv](https://docs - [Enable Caching](#enable-caching) - [Cache dependency glob](#cache-dependency-glob) - [Local cache path](#local-cache-path) + - [Disable cache pruning](#disable-cache-pruning) + - [Ignore nothing to cache](#ignore-nothing-to-cache) - [GitHub authentication token](#github-authentication-token) - [UV_TOOL_DIR](#uv_tool_dir) - [UV_TOOL_BIN_DIR](#uv_tool_bin_dir) @@ -195,6 +197,19 @@ input. prune-cache: false ``` +### Ignore nothing to cache + +By default, the action will fail if there is nothing to cache. If you want to ignore this, set the +`ignore-nothing-to-cache` input to `true`. + +```yaml +- name: Ignore nothing to cache + uses: astral-sh/setup-uv@v3 + with: + enable-cache: true + ignore-nothing-to-cache: true +``` + ### GitHub authentication token This action uses the GitHub API to fetch the uv release artifacts. To avoid hitting the GitHub API diff --git a/action.yml b/action.yml index bcb05f9..3356c2f 100644 --- a/action.yml +++ b/action.yml @@ -31,7 +31,10 @@ inputs: default: "" prune-cache: description: "Prune cache before saving." - default: true + default: "true" + ignore-nothing-to-cache: + description: "Ignore when nothing is found to cache." + default: "false" tool-dir: description: "Custom path to set UV_TOOL_DIR to." required: false diff --git a/dist/save-cache/index.js b/dist/save-cache/index.js index ea6058c..5d58cbf 100644 --- a/dist/save-cache/index.js +++ b/dist/save-cache/index.js @@ -82510,6 +82510,7 @@ exports.run = run; const cache = __importStar(__nccwpck_require__(5116)); const core = __importStar(__nccwpck_require__(7484)); const exec = __importStar(__nccwpck_require__(5236)); +const fs = __importStar(__nccwpck_require__(3024)); const restore_cache_1 = __nccwpck_require__(5391); const inputs_1 = __nccwpck_require__(9612); function run() { @@ -82517,18 +82518,18 @@ function run() { try { if (inputs_1.enableCache) { yield saveCache(); + // node will stay alive if any promises are not resolved, + // which is a possibility if HTTP requests are dangling + // due to retries or timeouts. We know that if we got here + // that all promises that we care about have successfully + // resolved, so simply exit with success. + process.exit(0); } } catch (error) { const err = error; core.setFailed(err.message); } - // node will stay alive if any promises are not resolved, - // which is a possibility if HTTP requests are dangling - // due to retries or timeouts. We know that if we got here - // that all promises that we care about have successfully - // resolved, so simply exit with success. - process.exit(0); }); } function saveCache() { @@ -82547,8 +82548,23 @@ function saveCache() { yield pruneCache(); } core.info(`Saving cache path: ${inputs_1.cacheLocalPath}`); - yield cache.saveCache([inputs_1.cacheLocalPath], cacheKey); - core.info(`cache saved with the key: ${cacheKey}`); + if (!fs.existsSync(inputs_1.cacheLocalPath) && !inputs_1.ignoreNothingToCache) { + throw new Error(`Cache path ${inputs_1.cacheLocalPath} does not exist on disk. This likely indicates that there are no dependencies to cache. Consider disabling the cache input if it is not needed.`); + } + try { + yield cache.saveCache([inputs_1.cacheLocalPath], cacheKey); + core.info(`cache saved with the key: ${cacheKey}`); + } + catch (e) { + if (e instanceof Error && + e.message === + "Path Validation Error: Path(s) specified in the action for caching do(es) not exist, hence no cache is being saved.") { + core.info("No cacheable paths were found. Ignoring because ignore-nothing-to-save is enabled."); + } + else { + throw e; + } + } }); } function pruneCache() { @@ -82598,7 +82614,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.githubToken = exports.toolDir = exports.toolBinDir = exports.pruneCache = exports.cacheDependencyGlob = exports.cacheLocalPath = exports.cacheSuffix = exports.enableCache = exports.checkSum = exports.version = void 0; +exports.githubToken = exports.toolDir = exports.toolBinDir = exports.ignoreNothingToCache = exports.pruneCache = exports.cacheDependencyGlob = exports.cacheLocalPath = exports.cacheSuffix = exports.enableCache = exports.checkSum = exports.version = void 0; const core = __importStar(__nccwpck_require__(7484)); const node_path_1 = __importDefault(__nccwpck_require__(6760)); exports.version = core.getInput("version"); @@ -82608,6 +82624,7 @@ exports.cacheSuffix = core.getInput("cache-suffix") || ""; exports.cacheLocalPath = getCacheLocalPath(); exports.cacheDependencyGlob = core.getInput("cache-dependency-glob"); exports.pruneCache = core.getInput("prune-cache") === "true"; +exports.ignoreNothingToCache = core.getInput("ignore-nothing-to-cache") === "true"; exports.toolBinDir = getToolBinDir(); exports.toolDir = getToolDir(); exports.githubToken = core.getInput("github-token"); diff --git a/dist/setup/index.js b/dist/setup/index.js index a17d5c8..d062c69 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -90268,7 +90268,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.githubToken = exports.toolDir = exports.toolBinDir = exports.pruneCache = exports.cacheDependencyGlob = exports.cacheLocalPath = exports.cacheSuffix = exports.enableCache = exports.checkSum = exports.version = void 0; +exports.githubToken = exports.toolDir = exports.toolBinDir = exports.ignoreNothingToCache = exports.pruneCache = exports.cacheDependencyGlob = exports.cacheLocalPath = exports.cacheSuffix = exports.enableCache = exports.checkSum = exports.version = void 0; const core = __importStar(__nccwpck_require__(7484)); const node_path_1 = __importDefault(__nccwpck_require__(6760)); exports.version = core.getInput("version"); @@ -90278,6 +90278,7 @@ exports.cacheSuffix = core.getInput("cache-suffix") || ""; exports.cacheLocalPath = getCacheLocalPath(); exports.cacheDependencyGlob = core.getInput("cache-dependency-glob"); exports.pruneCache = core.getInput("prune-cache") === "true"; +exports.ignoreNothingToCache = core.getInput("ignore-nothing-to-cache") === "true"; exports.toolBinDir = getToolBinDir(); exports.toolDir = getToolDir(); exports.githubToken = core.getInput("github-token"); diff --git a/src/save-cache.ts b/src/save-cache.ts index cf5acca..bc2bbf2 100644 --- a/src/save-cache.ts +++ b/src/save-cache.ts @@ -1,6 +1,7 @@ import * as cache from "@actions/cache"; import * as core from "@actions/core"; import * as exec from "@actions/exec"; +import * as fs from "node:fs"; import { STATE_CACHE_MATCHED_KEY, STATE_CACHE_KEY, @@ -8,6 +9,7 @@ import { import { cacheLocalPath, enableCache, + ignoreNothingToCache, pruneCache as shouldPruneCache, } from "./utils/inputs"; @@ -15,17 +17,17 @@ export async function run(): Promise { try { if (enableCache) { await saveCache(); + // node will stay alive if any promises are not resolved, + // which is a possibility if HTTP requests are dangling + // due to retries or timeouts. We know that if we got here + // that all promises that we care about have successfully + // resolved, so simply exit with success. + process.exit(0); } } catch (error) { const err = error as Error; core.setFailed(err.message); } - // node will stay alive if any promises are not resolved, - // which is a possibility if HTTP requests are dangling - // due to retries or timeouts. We know that if we got here - // that all promises that we care about have successfully - // resolved, so simply exit with success. - process.exit(0); } async function saveCache(): Promise { @@ -46,9 +48,27 @@ async function saveCache(): Promise { } core.info(`Saving cache path: ${cacheLocalPath}`); - await cache.saveCache([cacheLocalPath], cacheKey); - - core.info(`cache saved with the key: ${cacheKey}`); + if (!fs.existsSync(cacheLocalPath) && !ignoreNothingToCache) { + throw new Error( + `Cache path ${cacheLocalPath} does not exist on disk. This likely indicates that there are no dependencies to cache. Consider disabling the cache input if it is not needed.`, + ); + } + try { + await cache.saveCache([cacheLocalPath], cacheKey); + core.info(`cache saved with the key: ${cacheKey}`); + } catch (e) { + if ( + e instanceof Error && + e.message === + "Path Validation Error: Path(s) specified in the action for caching do(es) not exist, hence no cache is being saved." + ) { + core.info( + "No cacheable paths were found. Ignoring because ignore-nothing-to-save is enabled.", + ); + } else { + throw e; + } + } } async function pruneCache(): Promise { diff --git a/src/utils/inputs.ts b/src/utils/inputs.ts index 57af924..d817815 100644 --- a/src/utils/inputs.ts +++ b/src/utils/inputs.ts @@ -8,6 +8,8 @@ export const cacheSuffix = core.getInput("cache-suffix") || ""; export const cacheLocalPath = getCacheLocalPath(); export const cacheDependencyGlob = core.getInput("cache-dependency-glob"); export const pruneCache = core.getInput("prune-cache") === "true"; +export const ignoreNothingToCache = + core.getInput("ignore-nothing-to-cache") === "true"; export const toolBinDir = getToolBinDir(); export const toolDir = getToolDir(); export const githubToken = core.getInput("github-token");