feat: add cache-dependency-path variables

This commit is contained in:
Nogic 2023-04-30 02:44:19 +00:00
parent 15b6d31610
commit 9bc24e1526
5 changed files with 44 additions and 9 deletions

View File

@ -98,6 +98,8 @@ steps:
- run: dotnet restore --locked-mode - run: dotnet restore --locked-mode
``` ```
### Reduce caching size
**Note:** Use [`NUGET_PACKAGES`](https://learn.microsoft.com/nuget/reference/cli-reference/cli-ref-environment-variables) environment variable if available. Some action runners already has huge libraries. (ex. Xamarin) **Note:** Use [`NUGET_PACKAGES`](https://learn.microsoft.com/nuget/reference/cli-reference/cli-ref-environment-variables) environment variable if available. Some action runners already has huge libraries. (ex. Xamarin)
```yaml ```yaml
@ -112,6 +114,21 @@ steps:
- run: dotnet restore --locked-mode - run: dotnet restore --locked-mode
``` ```
### Caching NuGet packages in monorepos
```yaml
env:
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.x
cache: true
cache-dependency-path: subdir/packages.lock.json
- run: dotnet restore --locked-mode
```
## Matrix Testing ## Matrix Testing
Using `setup-dotnet` it's possible to use [matrix syntax](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix) to install several versions of .NET SDK: Using `setup-dotnet` it's possible to use [matrix syntax](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix) to install several versions of .NET SDK:
```yml ```yml

View File

@ -3,6 +3,7 @@ import * as core from '@actions/core';
import * as glob from '@actions/glob'; import * as glob from '@actions/glob';
import {restoreCache} from '../src/cache-restore'; import {restoreCache} from '../src/cache-restore';
import {getNuGetFolderPath} from '../src/cache-utils'; import {getNuGetFolderPath} from '../src/cache-utils';
import {lockFilePattern} from '../src/constants';
jest.mock('@actions/cache'); jest.mock('@actions/cache');
jest.mock('@actions/core'); jest.mock('@actions/core');
@ -20,15 +21,16 @@ describe('cache-restore tests', () => {
}); });
}); });
beforeEach(() => { beforeEach(() => {
jest.mocked(glob.hashFiles).mockClear();
jest.mocked(core.saveState).mockClear(); jest.mocked(core.saveState).mockClear();
jest.mocked(core.setOutput).mockClear(); jest.mocked(core.setOutput).mockClear();
jest.mocked(cache.restoreCache).mockClear(); jest.mocked(cache.restoreCache).mockClear();
}); });
it('does not call cache.restoreCache() when lock file is not found', async () => { it('throws error when lock file is not found', async () => {
jest.mocked(glob.hashFiles).mockResolvedValue(''); jest.mocked(glob.hashFiles).mockResolvedValue('');
await restoreCache(); await expect(restoreCache(lockFilePattern)).rejects.toThrow();
expect(jest.mocked(core.saveState)).not.toHaveBeenCalled(); expect(jest.mocked(core.saveState)).not.toHaveBeenCalled();
expect(jest.mocked(core.setOutput)).not.toHaveBeenCalled(); expect(jest.mocked(core.setOutput)).not.toHaveBeenCalled();
@ -39,7 +41,7 @@ describe('cache-restore tests', () => {
jest.mocked(glob.hashFiles).mockResolvedValue('hash'); jest.mocked(glob.hashFiles).mockResolvedValue('hash');
jest.mocked(cache.restoreCache).mockResolvedValue(undefined); jest.mocked(cache.restoreCache).mockResolvedValue(undefined);
await restoreCache(); await restoreCache(lockFilePattern);
const expectedKey = `dotnet-cache-${process.env.RUNNER_OS}-hash`; const expectedKey = `dotnet-cache-${process.env.RUNNER_OS}-hash`;
expect(jest.mocked(core.saveState)).toHaveBeenCalledWith( expect(jest.mocked(core.saveState)).toHaveBeenCalledWith(
@ -61,7 +63,7 @@ describe('cache-restore tests', () => {
jest.mocked(glob.hashFiles).mockResolvedValue('hash'); jest.mocked(glob.hashFiles).mockResolvedValue('hash');
jest.mocked(cache.restoreCache).mockResolvedValue(expectedKey); jest.mocked(cache.restoreCache).mockResolvedValue(expectedKey);
await restoreCache(); await restoreCache(lockFilePattern);
expect(jest.mocked(core.saveState)).toHaveBeenCalledWith( expect(jest.mocked(core.saveState)).toHaveBeenCalledWith(
'CACHE_KEY', 'CACHE_KEY',
@ -76,5 +78,16 @@ describe('cache-restore tests', () => {
true true
); );
}); });
it('calls glob.hashFiles("**/packages.lock.json") if cacheDependencyPath is falsy', async () => {
const expectedKey = `dotnet-cache-${process.env.RUNNER_OS}-hash`;
jest.mocked(glob.hashFiles).mockResolvedValue('hash');
jest.mocked(cache.restoreCache).mockResolvedValue(expectedKey);
await restoreCache('');
expect(jest.mocked(glob.hashFiles)).not.toHaveBeenCalledWith('');
expect(jest.mocked(glob.hashFiles)).toHaveBeenCalledWith(lockFilePattern);
});
}); });
}); });

View File

@ -21,6 +21,9 @@ inputs:
description: 'Optional input to enable caching of the NuGet global-packages folder' description: 'Optional input to enable caching of the NuGet global-packages folder'
required: false required: false
default: false default: false
cache-dependency-path:
description: 'Used to specify the path to a dependency file: packages.lock.json. Supports wildcards or a list of file names for caching multiple dependencies.'
required: false
outputs: outputs:
cache-hit: cache-hit:
description: 'A boolean value to indicate if a cache was hit.' description: 'A boolean value to indicate if a cache was hit.'

View File

@ -5,11 +5,12 @@ import * as glob from '@actions/glob';
import {getNuGetFolderPath} from './cache-utils'; import {getNuGetFolderPath} from './cache-utils';
import {lockFilePattern, State, Outputs} from './constants'; import {lockFilePattern, State, Outputs} from './constants';
export const restoreCache = async () => { export const restoreCache = async (cacheDependencyPath?: string) => {
const fileHash = await glob.hashFiles(lockFilePattern); const fileHash = await glob.hashFiles(cacheDependencyPath || lockFilePattern);
if (!fileHash) { if (!fileHash) {
core.warning(`No matches found for glob: ${lockFilePattern}`); throw new Error(
return; 'Some specified paths were not resolved, unable to cache dependencies.'
);
} }
const platform = process.env.RUNNER_OS; const platform = process.env.RUNNER_OS;

View File

@ -96,7 +96,8 @@ export async function run() {
core.setOutput(Outputs.DotnetVersion, versionToOutput); core.setOutput(Outputs.DotnetVersion, versionToOutput);
if (core.getBooleanInput('cache') && isCacheFeatureAvailable()) { if (core.getBooleanInput('cache') && isCacheFeatureAvailable()) {
await restoreCache(); const cacheDependencyPath = core.getInput('cache-dependency-path');
await restoreCache(cacheDependencyPath);
} else { } else {
core.setOutput(Outputs.CacheHit, false); core.setOutput(Outputs.CacheHit, false);
} }