mirror of
				https://github.com/actions/setup-node.git
				synced 2025-11-04 12:03:34 +00:00 
			
		
		
		
	Merge branch 'actions:main' into V3.7.0
This commit is contained in:
		
						commit
						80792ccbaa
					
				
							
								
								
									
										109
									
								
								.github/workflows/e2e-cache.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										109
									
								
								.github/workflows/e2e-cache.yml
									
									
									
									
										vendored
									
									
								
							@ -134,3 +134,112 @@ jobs:
 | 
				
			|||||||
      - name: Verify node and yarn
 | 
					      - name: Verify node and yarn
 | 
				
			||||||
        run: __tests__/verify-node.sh "${{ matrix.node-version }}"
 | 
					        run: __tests__/verify-node.sh "${{ matrix.node-version }}"
 | 
				
			||||||
        shell: bash
 | 
					        shell: bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  yarn-subprojects:
 | 
				
			||||||
 | 
					    name: Test yarn subprojects
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        node-version: [12, 14, 16]
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: prepare sub-projects
 | 
				
			||||||
 | 
					        run: __tests__/prepare-yarn-subprojects.sh yarn1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # expect
 | 
				
			||||||
 | 
					      #  - no errors
 | 
				
			||||||
 | 
					      #  - log
 | 
				
			||||||
 | 
					      #    ##[debug]Cache Paths:
 | 
				
			||||||
 | 
					      #    ##[debug]["sub2/.yarn/cache","sub3/.yarn/cache","../../../.cache/yarn/v6"]
 | 
				
			||||||
 | 
					      - name: Setup Node
 | 
				
			||||||
 | 
					        uses: ./
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          node-version: ${{ matrix.node-version }}
 | 
				
			||||||
 | 
					          cache: 'yarn'
 | 
				
			||||||
 | 
					          cache-dependency-path: |
 | 
				
			||||||
 | 
					            **/*.lock
 | 
				
			||||||
 | 
					            yarn.lock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  yarn-subprojects-berry-local:
 | 
				
			||||||
 | 
					    name: Test yarn subprojects all locally managed
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        node-version: [12, 14, 16]
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: prepare sub-projects
 | 
				
			||||||
 | 
					        run: __tests__/prepare-yarn-subprojects.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # expect
 | 
				
			||||||
 | 
					      #  - no errors
 | 
				
			||||||
 | 
					      #  - log
 | 
				
			||||||
 | 
					      #    ##[info]All dependencies are managed locally by yarn3, the previous cache can be used
 | 
				
			||||||
 | 
					      #    ##[debug]["node-cache-Linux-yarn-401024703386272f1a950c9f014cbb1bb79a7a5b6e1fb00e8b90d06734af41ee","node-cache-Linux-yarn"]
 | 
				
			||||||
 | 
					      - name: Setup Node
 | 
				
			||||||
 | 
					        uses: ./
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          node-version: ${{ matrix.node-version }}
 | 
				
			||||||
 | 
					          cache: 'yarn'
 | 
				
			||||||
 | 
					          cache-dependency-path: |
 | 
				
			||||||
 | 
					            sub2/*.lock
 | 
				
			||||||
 | 
					            sub3/*.lock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  yarn-subprojects-berry-global:
 | 
				
			||||||
 | 
					    name: Test yarn subprojects some locally managed
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        node-version: [12, 14, 16]
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: prepare sub-projects
 | 
				
			||||||
 | 
					        run: __tests__/prepare-yarn-subprojects.sh global
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # expect
 | 
				
			||||||
 | 
					      #  - no errors
 | 
				
			||||||
 | 
					      #  - log must
 | 
				
			||||||
 | 
					      #    ##[debug]"/home/runner/work/setup-node-test/setup-node-test/sub2" dependencies are managed by yarn 3 locally
 | 
				
			||||||
 | 
					      #    ##[debug]"/home/runner/work/setup-node-test/setup-node-test/sub3" dependencies are not managed by yarn 3 locally
 | 
				
			||||||
 | 
					      - name: Setup Node
 | 
				
			||||||
 | 
					        uses: ./
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          node-version: ${{ matrix.node-version }}
 | 
				
			||||||
 | 
					          cache: 'yarn'
 | 
				
			||||||
 | 
					          cache-dependency-path: |
 | 
				
			||||||
 | 
					            sub2/*.lock
 | 
				
			||||||
 | 
					            sub3/*.lock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  yarn-subprojects-berry-git:
 | 
				
			||||||
 | 
					    name: Test yarn subprojects managed by git
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        node-version: [12, 14, 16]
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: prepare sub-projects
 | 
				
			||||||
 | 
					        run: /bin/bash __tests__/prepare-yarn-subprojects.sh keepcache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # expect
 | 
				
			||||||
 | 
					      #  - no errors
 | 
				
			||||||
 | 
					      #  - log
 | 
				
			||||||
 | 
					      #    [debug]"/home/runner/work/setup-node-test/setup-node-test/sub2" has .yarn/cache - dependencies are kept in the repository
 | 
				
			||||||
 | 
					      #    [debug]"/home/runner/work/setup-node-test/setup-node-test/sub3" has .yarn/cache - dependencies are kept in the repository
 | 
				
			||||||
 | 
					      #    [debug]["node-cache-Linux-yarn-401024703386272f1a950c9f014cbb1bb79a7a5b6e1fb00e8b90d06734af41ee"]
 | 
				
			||||||
 | 
					      - name: Setup Node
 | 
				
			||||||
 | 
					        uses: ./
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          node-version: ${{ matrix.node-version }}
 | 
				
			||||||
 | 
					          cache: 'yarn'
 | 
				
			||||||
 | 
					          cache-dependency-path: |
 | 
				
			||||||
 | 
					            sub2/*.lock
 | 
				
			||||||
 | 
					            sub3/*.lock
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,10 @@
 | 
				
			|||||||
import os from 'os';
 | 
					import os from 'os';
 | 
				
			||||||
import * as fs from 'fs';
 | 
					import fs from 'fs';
 | 
				
			||||||
import * as path from 'path';
 | 
					import * as path from 'path';
 | 
				
			||||||
import * as core from '@actions/core';
 | 
					import * as core from '@actions/core';
 | 
				
			||||||
import * as io from '@actions/io';
 | 
					import * as io from '@actions/io';
 | 
				
			||||||
import * as auth from '../src/authutil';
 | 
					import * as auth from '../src/authutil';
 | 
				
			||||||
 | 
					import * as cacheUtils from '../src/cache-utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let rcFile: string;
 | 
					let rcFile: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -32,13 +32,13 @@ describe('cache-restore', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  function findCacheFolder(command: string) {
 | 
					  function findCacheFolder(command: string) {
 | 
				
			||||||
    switch (command) {
 | 
					    switch (command) {
 | 
				
			||||||
      case utils.supportedPackageManagers.npm.getCacheFolderCommand:
 | 
					      case 'npm config get cache':
 | 
				
			||||||
        return npmCachePath;
 | 
					        return npmCachePath;
 | 
				
			||||||
      case utils.supportedPackageManagers.pnpm.getCacheFolderCommand:
 | 
					      case 'pnpm store path --silent':
 | 
				
			||||||
        return pnpmCachePath;
 | 
					        return pnpmCachePath;
 | 
				
			||||||
      case utils.supportedPackageManagers.yarn1.getCacheFolderCommand:
 | 
					      case 'yarn cache dir':
 | 
				
			||||||
        return yarn1CachePath;
 | 
					        return yarn1CachePath;
 | 
				
			||||||
      case utils.supportedPackageManagers.yarn2.getCacheFolderCommand:
 | 
					      case 'yarn config get cacheFolder':
 | 
				
			||||||
        return yarn2CachePath;
 | 
					        return yarn2CachePath;
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
        return 'packge/not/found';
 | 
					        return 'packge/not/found';
 | 
				
			||||||
@ -108,7 +108,7 @@ describe('cache-restore', () => {
 | 
				
			|||||||
    it.each([['npm7'], ['npm6'], ['pnpm6'], ['yarn1'], ['yarn2'], ['random']])(
 | 
					    it.each([['npm7'], ['npm6'], ['pnpm6'], ['yarn1'], ['yarn2'], ['random']])(
 | 
				
			||||||
      'Throw an error because %s is not supported',
 | 
					      'Throw an error because %s is not supported',
 | 
				
			||||||
      async packageManager => {
 | 
					      async packageManager => {
 | 
				
			||||||
        await expect(restoreCache(packageManager)).rejects.toThrow(
 | 
					        await expect(restoreCache(packageManager, '')).rejects.toThrow(
 | 
				
			||||||
          `Caching for '${packageManager}' is not supported`
 | 
					          `Caching for '${packageManager}' is not supported`
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -132,7 +132,7 @@ describe('cache-restore', () => {
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await restoreCache(packageManager);
 | 
					        await restoreCache(packageManager, '');
 | 
				
			||||||
        expect(hashFilesSpy).toHaveBeenCalled();
 | 
					        expect(hashFilesSpy).toHaveBeenCalled();
 | 
				
			||||||
        expect(infoSpy).toHaveBeenCalledWith(
 | 
					        expect(infoSpy).toHaveBeenCalledWith(
 | 
				
			||||||
          `Cache restored from key: node-cache-${platform}-${packageManager}-${fileHash}`
 | 
					          `Cache restored from key: node-cache-${platform}-${packageManager}-${fileHash}`
 | 
				
			||||||
@ -163,7 +163,7 @@ describe('cache-restore', () => {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        restoreCacheSpy.mockImplementationOnce(() => undefined);
 | 
					        restoreCacheSpy.mockImplementationOnce(() => undefined);
 | 
				
			||||||
        await restoreCache(packageManager);
 | 
					        await restoreCache(packageManager, '');
 | 
				
			||||||
        expect(hashFilesSpy).toHaveBeenCalled();
 | 
					        expect(hashFilesSpy).toHaveBeenCalled();
 | 
				
			||||||
        expect(infoSpy).toHaveBeenCalledWith(
 | 
					        expect(infoSpy).toHaveBeenCalledWith(
 | 
				
			||||||
          `${packageManager} cache is not found`
 | 
					          `${packageManager} cache is not found`
 | 
				
			||||||
 | 
				
			|||||||
@ -107,18 +107,20 @@ describe('run', () => {
 | 
				
			|||||||
  describe('Validate unchanged cache is not saved', () => {
 | 
					  describe('Validate unchanged cache is not saved', () => {
 | 
				
			||||||
    it('should not save cache for yarn1', async () => {
 | 
					    it('should not save cache for yarn1', async () => {
 | 
				
			||||||
      inputs['cache'] = 'yarn';
 | 
					      inputs['cache'] = 'yarn';
 | 
				
			||||||
      getStateSpy.mockImplementation(() => yarnFileHash);
 | 
					      getStateSpy.mockImplementation(key =>
 | 
				
			||||||
      getCommandOutputSpy
 | 
					        key === State.CachePrimaryKey || key === State.CacheMatchedKey
 | 
				
			||||||
        .mockImplementationOnce(() => '1.2.3')
 | 
					          ? yarnFileHash
 | 
				
			||||||
        .mockImplementationOnce(() => `${commonPath}/yarn1`);
 | 
					          : key === State.CachePaths
 | 
				
			||||||
 | 
					          ? '["/foo/bar"]'
 | 
				
			||||||
 | 
					          : 'not expected'
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      await run();
 | 
					      await run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
					      expect(getInputSpy).toHaveBeenCalled();
 | 
				
			||||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
					      expect(getStateSpy).toHaveBeenCalledTimes(3);
 | 
				
			||||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
 | 
					      expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn1`);
 | 
					      expect(debugSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 1.2.3');
 | 
					 | 
				
			||||||
      expect(infoSpy).toHaveBeenCalledWith(
 | 
					      expect(infoSpy).toHaveBeenCalledWith(
 | 
				
			||||||
        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
					        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@ -127,18 +129,20 @@ describe('run', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    it('should not save cache for yarn2', async () => {
 | 
					    it('should not save cache for yarn2', async () => {
 | 
				
			||||||
      inputs['cache'] = 'yarn';
 | 
					      inputs['cache'] = 'yarn';
 | 
				
			||||||
      getStateSpy.mockImplementation(() => yarnFileHash);
 | 
					      getStateSpy.mockImplementation(key =>
 | 
				
			||||||
      getCommandOutputSpy
 | 
					        key === State.CachePrimaryKey || key === State.CacheMatchedKey
 | 
				
			||||||
        .mockImplementationOnce(() => '2.2.3')
 | 
					          ? yarnFileHash
 | 
				
			||||||
        .mockImplementationOnce(() => `${commonPath}/yarn2`);
 | 
					          : key === State.CachePaths
 | 
				
			||||||
 | 
					          ? '["/foo/bar"]'
 | 
				
			||||||
 | 
					          : 'not expected'
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      await run();
 | 
					      await run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
					      expect(getInputSpy).toHaveBeenCalled();
 | 
				
			||||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
					      expect(getStateSpy).toHaveBeenCalledTimes(3);
 | 
				
			||||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
 | 
					      expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn2`);
 | 
					      expect(debugSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 2.2.3');
 | 
					 | 
				
			||||||
      expect(infoSpy).toHaveBeenCalledWith(
 | 
					      expect(infoSpy).toHaveBeenCalledWith(
 | 
				
			||||||
        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
					        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@ -147,35 +151,40 @@ describe('run', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    it('should not save cache for npm', async () => {
 | 
					    it('should not save cache for npm', async () => {
 | 
				
			||||||
      inputs['cache'] = 'npm';
 | 
					      inputs['cache'] = 'npm';
 | 
				
			||||||
      getStateSpy.mockImplementation(() => npmFileHash);
 | 
					      getStateSpy.mockImplementation(key =>
 | 
				
			||||||
 | 
					        key === State.CachePrimaryKey || key === State.CacheMatchedKey
 | 
				
			||||||
 | 
					          ? yarnFileHash
 | 
				
			||||||
 | 
					          : key === State.CachePaths
 | 
				
			||||||
 | 
					          ? '["/foo/bar"]'
 | 
				
			||||||
 | 
					          : 'not expected'
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
      getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/npm`);
 | 
					      getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/npm`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      await run();
 | 
					      await run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
					      expect(getInputSpy).toHaveBeenCalled();
 | 
				
			||||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
					      expect(getStateSpy).toHaveBeenCalledTimes(3);
 | 
				
			||||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
 | 
					      expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(debugSpy).toHaveBeenCalledWith(`npm path is ${commonPath}/npm`);
 | 
					      expect(debugSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(infoSpy).toHaveBeenCalledWith(
 | 
					 | 
				
			||||||
        `Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
      expect(setFailedSpy).not.toHaveBeenCalled();
 | 
					      expect(setFailedSpy).not.toHaveBeenCalled();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it('should not save cache for pnpm', async () => {
 | 
					    it('should not save cache for pnpm', async () => {
 | 
				
			||||||
      inputs['cache'] = 'pnpm';
 | 
					      inputs['cache'] = 'pnpm';
 | 
				
			||||||
      getStateSpy.mockImplementation(() => pnpmFileHash);
 | 
					      getStateSpy.mockImplementation(key =>
 | 
				
			||||||
      getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/pnpm`);
 | 
					        key === State.CachePrimaryKey || key === State.CacheMatchedKey
 | 
				
			||||||
 | 
					          ? yarnFileHash
 | 
				
			||||||
 | 
					          : key === State.CachePaths
 | 
				
			||||||
 | 
					          ? '["/foo/bar"]'
 | 
				
			||||||
 | 
					          : 'not expected'
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      await run();
 | 
					      await run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
					      expect(getInputSpy).toHaveBeenCalled();
 | 
				
			||||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
					      expect(getStateSpy).toHaveBeenCalledTimes(3);
 | 
				
			||||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
 | 
					      expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(debugSpy).toHaveBeenCalledWith(`pnpm path is ${commonPath}/pnpm`);
 | 
					      expect(debugSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(infoSpy).toHaveBeenCalledWith(
 | 
					 | 
				
			||||||
        `Cache hit occurred on the primary key ${pnpmFileHash}, not saving cache.`
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
      expect(setFailedSpy).not.toHaveBeenCalled();
 | 
					      expect(setFailedSpy).not.toHaveBeenCalled();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
@ -183,24 +192,22 @@ describe('run', () => {
 | 
				
			|||||||
  describe('action saves the cache', () => {
 | 
					  describe('action saves the cache', () => {
 | 
				
			||||||
    it('saves cache from yarn 1', async () => {
 | 
					    it('saves cache from yarn 1', async () => {
 | 
				
			||||||
      inputs['cache'] = 'yarn';
 | 
					      inputs['cache'] = 'yarn';
 | 
				
			||||||
      getStateSpy.mockImplementation((name: string) => {
 | 
					      getStateSpy.mockImplementation((key: string) =>
 | 
				
			||||||
        if (name === State.CacheMatchedKey) {
 | 
					        key === State.CacheMatchedKey
 | 
				
			||||||
          return yarnFileHash;
 | 
					          ? yarnFileHash
 | 
				
			||||||
        } else {
 | 
					          : key === State.CachePrimaryKey
 | 
				
			||||||
          return npmFileHash;
 | 
					          ? npmFileHash
 | 
				
			||||||
        }
 | 
					          : key === State.CachePaths
 | 
				
			||||||
      });
 | 
					          ? '["/foo/bar"]'
 | 
				
			||||||
      getCommandOutputSpy
 | 
					          : 'not expected'
 | 
				
			||||||
        .mockImplementationOnce(() => '1.2.3')
 | 
					      );
 | 
				
			||||||
        .mockImplementationOnce(() => `${commonPath}/yarn1`);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      await run();
 | 
					      await run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
					      expect(getInputSpy).toHaveBeenCalled();
 | 
				
			||||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
					      expect(getStateSpy).toHaveBeenCalledTimes(3);
 | 
				
			||||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
 | 
					      expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn1`);
 | 
					      expect(debugSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 1.2.3');
 | 
					 | 
				
			||||||
      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
					      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
				
			||||||
        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
					        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@ -213,24 +220,22 @@ describe('run', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    it('saves cache from yarn 2', async () => {
 | 
					    it('saves cache from yarn 2', async () => {
 | 
				
			||||||
      inputs['cache'] = 'yarn';
 | 
					      inputs['cache'] = 'yarn';
 | 
				
			||||||
      getStateSpy.mockImplementation((name: string) => {
 | 
					      getStateSpy.mockImplementation((key: string) =>
 | 
				
			||||||
        if (name === State.CacheMatchedKey) {
 | 
					        key === State.CacheMatchedKey
 | 
				
			||||||
          return yarnFileHash;
 | 
					          ? yarnFileHash
 | 
				
			||||||
        } else {
 | 
					          : key === State.CachePrimaryKey
 | 
				
			||||||
          return npmFileHash;
 | 
					          ? npmFileHash
 | 
				
			||||||
        }
 | 
					          : key === State.CachePaths
 | 
				
			||||||
      });
 | 
					          ? '["/foo/bar"]'
 | 
				
			||||||
      getCommandOutputSpy
 | 
					          : 'not expected'
 | 
				
			||||||
        .mockImplementationOnce(() => '2.2.3')
 | 
					      );
 | 
				
			||||||
        .mockImplementationOnce(() => `${commonPath}/yarn2`);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      await run();
 | 
					      await run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
					      expect(getInputSpy).toHaveBeenCalled();
 | 
				
			||||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
					      expect(getStateSpy).toHaveBeenCalledTimes(3);
 | 
				
			||||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
 | 
					      expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn2`);
 | 
					      expect(debugSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 2.2.3');
 | 
					 | 
				
			||||||
      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
					      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
				
			||||||
        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
					        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@ -243,21 +248,22 @@ describe('run', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    it('saves cache from npm', async () => {
 | 
					    it('saves cache from npm', async () => {
 | 
				
			||||||
      inputs['cache'] = 'npm';
 | 
					      inputs['cache'] = 'npm';
 | 
				
			||||||
      getStateSpy.mockImplementation((name: string) => {
 | 
					      getStateSpy.mockImplementation((key: string) =>
 | 
				
			||||||
        if (name === State.CacheMatchedKey) {
 | 
					        key === State.CacheMatchedKey
 | 
				
			||||||
          return npmFileHash;
 | 
					          ? npmFileHash
 | 
				
			||||||
        } else {
 | 
					          : key === State.CachePrimaryKey
 | 
				
			||||||
          return yarnFileHash;
 | 
					          ? yarnFileHash
 | 
				
			||||||
        }
 | 
					          : key === State.CachePaths
 | 
				
			||||||
      });
 | 
					          ? '["/foo/bar"]'
 | 
				
			||||||
      getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/npm`);
 | 
					          : 'not expected'
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      await run();
 | 
					      await run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
					      expect(getInputSpy).toHaveBeenCalled();
 | 
				
			||||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
					      expect(getStateSpy).toHaveBeenCalledTimes(3);
 | 
				
			||||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
 | 
					      expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(debugSpy).toHaveBeenCalledWith(`npm path is ${commonPath}/npm`);
 | 
					      expect(debugSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
					      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
				
			||||||
        `Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
 | 
					        `Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@ -270,21 +276,22 @@ describe('run', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    it('saves cache from pnpm', async () => {
 | 
					    it('saves cache from pnpm', async () => {
 | 
				
			||||||
      inputs['cache'] = 'pnpm';
 | 
					      inputs['cache'] = 'pnpm';
 | 
				
			||||||
      getStateSpy.mockImplementation((name: string) => {
 | 
					      getStateSpy.mockImplementation((key: string) =>
 | 
				
			||||||
        if (name === State.CacheMatchedKey) {
 | 
					        key === State.CacheMatchedKey
 | 
				
			||||||
          return pnpmFileHash;
 | 
					          ? pnpmFileHash
 | 
				
			||||||
        } else {
 | 
					          : key === State.CachePrimaryKey
 | 
				
			||||||
          return npmFileHash;
 | 
					          ? npmFileHash
 | 
				
			||||||
        }
 | 
					          : key === State.CachePaths
 | 
				
			||||||
      });
 | 
					          ? '["/foo/bar"]'
 | 
				
			||||||
      getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/pnpm`);
 | 
					          : 'not expected'
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      await run();
 | 
					      await run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
					      expect(getInputSpy).toHaveBeenCalled();
 | 
				
			||||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
					      expect(getStateSpy).toHaveBeenCalledTimes(3);
 | 
				
			||||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
 | 
					      expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(debugSpy).toHaveBeenCalledWith(`pnpm path is ${commonPath}/pnpm`);
 | 
					      expect(debugSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
					      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
				
			||||||
        `Cache hit occurred on the primary key ${pnpmFileHash}, not saving cache.`
 | 
					        `Cache hit occurred on the primary key ${pnpmFileHash}, not saving cache.`
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@ -297,14 +304,15 @@ describe('run', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    it('save with -1 cacheId , should not fail workflow', async () => {
 | 
					    it('save with -1 cacheId , should not fail workflow', async () => {
 | 
				
			||||||
      inputs['cache'] = 'npm';
 | 
					      inputs['cache'] = 'npm';
 | 
				
			||||||
      getStateSpy.mockImplementation((name: string) => {
 | 
					      getStateSpy.mockImplementation((key: string) =>
 | 
				
			||||||
        if (name === State.CacheMatchedKey) {
 | 
					        key === State.CacheMatchedKey
 | 
				
			||||||
          return npmFileHash;
 | 
					          ? npmFileHash
 | 
				
			||||||
        } else {
 | 
					          : key === State.CachePrimaryKey
 | 
				
			||||||
          return yarnFileHash;
 | 
					          ? yarnFileHash
 | 
				
			||||||
        }
 | 
					          : key === State.CachePaths
 | 
				
			||||||
      });
 | 
					          ? '["/foo/bar"]'
 | 
				
			||||||
      getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/npm`);
 | 
					          : 'not expected'
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
      saveCacheSpy.mockImplementation(() => {
 | 
					      saveCacheSpy.mockImplementation(() => {
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@ -312,9 +320,9 @@ describe('run', () => {
 | 
				
			|||||||
      await run();
 | 
					      await run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
					      expect(getInputSpy).toHaveBeenCalled();
 | 
				
			||||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
					      expect(getStateSpy).toHaveBeenCalledTimes(3);
 | 
				
			||||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
 | 
					      expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(debugSpy).toHaveBeenCalledWith(`npm path is ${commonPath}/npm`);
 | 
					      expect(debugSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
					      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
				
			||||||
        `Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
 | 
					        `Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@ -327,14 +335,15 @@ describe('run', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    it('saves with error from toolkit, should fail workflow', async () => {
 | 
					    it('saves with error from toolkit, should fail workflow', async () => {
 | 
				
			||||||
      inputs['cache'] = 'npm';
 | 
					      inputs['cache'] = 'npm';
 | 
				
			||||||
      getStateSpy.mockImplementation((name: string) => {
 | 
					      getStateSpy.mockImplementation((key: string) =>
 | 
				
			||||||
        if (name === State.CacheMatchedKey) {
 | 
					        key === State.CacheMatchedKey
 | 
				
			||||||
          return npmFileHash;
 | 
					          ? npmFileHash
 | 
				
			||||||
        } else {
 | 
					          : key === State.CachePrimaryKey
 | 
				
			||||||
          return yarnFileHash;
 | 
					          ? yarnFileHash
 | 
				
			||||||
        }
 | 
					          : key === State.CachePaths
 | 
				
			||||||
      });
 | 
					          ? '["/foo/bar"]'
 | 
				
			||||||
      getCommandOutputSpy.mockImplementationOnce(() => `${commonPath}/npm`);
 | 
					          : 'not expected'
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
      saveCacheSpy.mockImplementation(() => {
 | 
					      saveCacheSpy.mockImplementation(() => {
 | 
				
			||||||
        throw new cache.ValidationError('Validation failed');
 | 
					        throw new cache.ValidationError('Validation failed');
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@ -342,9 +351,9 @@ describe('run', () => {
 | 
				
			|||||||
      await run();
 | 
					      await run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
					      expect(getInputSpy).toHaveBeenCalled();
 | 
				
			||||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
					      expect(getStateSpy).toHaveBeenCalledTimes(3);
 | 
				
			||||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
 | 
					      expect(getCommandOutputSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(debugSpy).toHaveBeenCalledWith(`npm path is ${commonPath}/npm`);
 | 
					      expect(debugSpy).toHaveBeenCalledTimes(0);
 | 
				
			||||||
      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
					      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
				
			||||||
        `Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
 | 
					        `Cache hit occurred on the primary key ${npmFileHash}, not saving cache.`
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,18 @@ import * as core from '@actions/core';
 | 
				
			|||||||
import * as cache from '@actions/cache';
 | 
					import * as cache from '@actions/cache';
 | 
				
			||||||
import path from 'path';
 | 
					import path from 'path';
 | 
				
			||||||
import * as utils from '../src/cache-utils';
 | 
					import * as utils from '../src/cache-utils';
 | 
				
			||||||
import {PackageManagerInfo, isCacheFeatureAvailable} from '../src/cache-utils';
 | 
					import {
 | 
				
			||||||
 | 
					  PackageManagerInfo,
 | 
				
			||||||
 | 
					  isCacheFeatureAvailable,
 | 
				
			||||||
 | 
					  supportedPackageManagers,
 | 
				
			||||||
 | 
					  getCommandOutput,
 | 
				
			||||||
 | 
					  resetProjectDirectoriesMemoized
 | 
				
			||||||
 | 
					} from '../src/cache-utils';
 | 
				
			||||||
 | 
					import fs from 'fs';
 | 
				
			||||||
 | 
					import * as cacheUtils from '../src/cache-utils';
 | 
				
			||||||
 | 
					import * as glob from '@actions/glob';
 | 
				
			||||||
 | 
					import {Globber} from '@actions/glob';
 | 
				
			||||||
 | 
					import {MockGlobber} from './mock/glob-mock';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('cache-utils', () => {
 | 
					describe('cache-utils', () => {
 | 
				
			||||||
  const versionYarn1 = '1.2.3';
 | 
					  const versionYarn1 = '1.2.3';
 | 
				
			||||||
@ -30,7 +41,7 @@ describe('cache-utils', () => {
 | 
				
			|||||||
    it.each<[string, PackageManagerInfo | null]>([
 | 
					    it.each<[string, PackageManagerInfo | null]>([
 | 
				
			||||||
      ['npm', utils.supportedPackageManagers.npm],
 | 
					      ['npm', utils.supportedPackageManagers.npm],
 | 
				
			||||||
      ['pnpm', utils.supportedPackageManagers.pnpm],
 | 
					      ['pnpm', utils.supportedPackageManagers.pnpm],
 | 
				
			||||||
      ['yarn', utils.supportedPackageManagers.yarn1],
 | 
					      ['yarn', utils.supportedPackageManagers.yarn],
 | 
				
			||||||
      ['yarn1', null],
 | 
					      ['yarn1', null],
 | 
				
			||||||
      ['yarn2', null],
 | 
					      ['yarn2', null],
 | 
				
			||||||
      ['npm7', null]
 | 
					      ['npm7', null]
 | 
				
			||||||
@ -72,4 +83,263 @@ describe('cache-utils', () => {
 | 
				
			|||||||
    jest.resetAllMocks();
 | 
					    jest.resetAllMocks();
 | 
				
			||||||
    jest.clearAllMocks();
 | 
					    jest.clearAllMocks();
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe('getCacheDirectoriesPaths', () => {
 | 
				
			||||||
 | 
					    let existsSpy: jest.SpyInstance;
 | 
				
			||||||
 | 
					    let lstatSpy: jest.SpyInstance;
 | 
				
			||||||
 | 
					    let globCreateSpy: jest.SpyInstance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    beforeEach(() => {
 | 
				
			||||||
 | 
					      existsSpy = jest.spyOn(fs, 'existsSync');
 | 
				
			||||||
 | 
					      existsSpy.mockImplementation(() => true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      lstatSpy = jest.spyOn(fs, 'lstatSync');
 | 
				
			||||||
 | 
					      lstatSpy.mockImplementation(arg => ({
 | 
				
			||||||
 | 
					        isDirectory: () => true
 | 
				
			||||||
 | 
					      }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      globCreateSpy = jest.spyOn(glob, 'create');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      globCreateSpy.mockImplementation(
 | 
				
			||||||
 | 
					        (pattern: string): Promise<Globber> =>
 | 
				
			||||||
 | 
					          MockGlobber.create(['/foo', '/bar'])
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      resetProjectDirectoriesMemoized();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    afterEach(() => {
 | 
				
			||||||
 | 
					      existsSpy.mockRestore();
 | 
				
			||||||
 | 
					      lstatSpy.mockRestore();
 | 
				
			||||||
 | 
					      globCreateSpy.mockRestore();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it.each([
 | 
				
			||||||
 | 
					      [supportedPackageManagers.npm, ''],
 | 
				
			||||||
 | 
					      [supportedPackageManagers.npm, '/dir/file.lock'],
 | 
				
			||||||
 | 
					      [supportedPackageManagers.npm, '/**/file.lock'],
 | 
				
			||||||
 | 
					      [supportedPackageManagers.pnpm, ''],
 | 
				
			||||||
 | 
					      [supportedPackageManagers.pnpm, '/dir/file.lock'],
 | 
				
			||||||
 | 
					      [supportedPackageManagers.pnpm, '/**/file.lock']
 | 
				
			||||||
 | 
					    ])(
 | 
				
			||||||
 | 
					      'getCacheDirectoriesPaths should return one dir for non yarn',
 | 
				
			||||||
 | 
					      async (packageManagerInfo, cacheDependency) => {
 | 
				
			||||||
 | 
					        getCommandOutputSpy.mockImplementation(() => 'foo');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const dirs = await cacheUtils.getCacheDirectories(
 | 
				
			||||||
 | 
					          packageManagerInfo,
 | 
				
			||||||
 | 
					          cacheDependency
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        expect(dirs).toEqual(['foo']);
 | 
				
			||||||
 | 
					        // to do not call for a version
 | 
				
			||||||
 | 
					        // call once for get cache folder
 | 
				
			||||||
 | 
					        expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('getCacheDirectoriesPaths should return one dir for yarn without cacheDependency', async () => {
 | 
				
			||||||
 | 
					      getCommandOutputSpy.mockImplementation(() => 'foo');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const dirs = await cacheUtils.getCacheDirectories(
 | 
				
			||||||
 | 
					        supportedPackageManagers.yarn,
 | 
				
			||||||
 | 
					        ''
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      expect(dirs).toEqual(['foo']);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it.each([
 | 
				
			||||||
 | 
					      [supportedPackageManagers.npm, ''],
 | 
				
			||||||
 | 
					      [supportedPackageManagers.npm, '/dir/file.lock'],
 | 
				
			||||||
 | 
					      [supportedPackageManagers.npm, '/**/file.lock'],
 | 
				
			||||||
 | 
					      [supportedPackageManagers.pnpm, ''],
 | 
				
			||||||
 | 
					      [supportedPackageManagers.pnpm, '/dir/file.lock'],
 | 
				
			||||||
 | 
					      [supportedPackageManagers.pnpm, '/**/file.lock'],
 | 
				
			||||||
 | 
					      [supportedPackageManagers.yarn, ''],
 | 
				
			||||||
 | 
					      [supportedPackageManagers.yarn, '/dir/file.lock'],
 | 
				
			||||||
 | 
					      [supportedPackageManagers.yarn, '/**/file.lock']
 | 
				
			||||||
 | 
					    ])(
 | 
				
			||||||
 | 
					      'getCacheDirectoriesPaths should throw for getCommandOutput returning empty',
 | 
				
			||||||
 | 
					      async (packageManagerInfo, cacheDependency) => {
 | 
				
			||||||
 | 
					        getCommandOutputSpy.mockImplementation((command: string) =>
 | 
				
			||||||
 | 
					          // return empty string to indicate getCacheFolderPath failed
 | 
				
			||||||
 | 
					          //        --version still works
 | 
				
			||||||
 | 
					          command.includes('version') ? '1.' : ''
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await expect(
 | 
				
			||||||
 | 
					          cacheUtils.getCacheDirectories(packageManagerInfo, cacheDependency)
 | 
				
			||||||
 | 
					        ).rejects.toThrow(); //'Could not get cache folder path for /dir');
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it.each([
 | 
				
			||||||
 | 
					      [supportedPackageManagers.yarn, '/dir/file.lock'],
 | 
				
			||||||
 | 
					      [supportedPackageManagers.yarn, '/**/file.lock']
 | 
				
			||||||
 | 
					    ])(
 | 
				
			||||||
 | 
					      'getCacheDirectoriesPaths should nothrow in case of having not directories',
 | 
				
			||||||
 | 
					      async (packageManagerInfo, cacheDependency) => {
 | 
				
			||||||
 | 
					        lstatSpy.mockImplementation(arg => ({
 | 
				
			||||||
 | 
					          isDirectory: () => false
 | 
				
			||||||
 | 
					        }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await cacheUtils.getCacheDirectories(
 | 
				
			||||||
 | 
					          packageManagerInfo,
 | 
				
			||||||
 | 
					          cacheDependency
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        expect(warningSpy).toHaveBeenCalledTimes(1);
 | 
				
			||||||
 | 
					        expect(warningSpy).toHaveBeenCalledWith(
 | 
				
			||||||
 | 
					          `No existing directories found containing cache-dependency-path="${cacheDependency}"`
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it.each(['1.1.1', '2.2.2'])(
 | 
				
			||||||
 | 
					      'getCacheDirectoriesPaths yarn v%s should return one dir without cacheDependency',
 | 
				
			||||||
 | 
					      async version => {
 | 
				
			||||||
 | 
					        getCommandOutputSpy.mockImplementationOnce(() => version);
 | 
				
			||||||
 | 
					        getCommandOutputSpy.mockImplementationOnce(() => `foo${version}`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const dirs = await cacheUtils.getCacheDirectories(
 | 
				
			||||||
 | 
					          supportedPackageManagers.yarn,
 | 
				
			||||||
 | 
					          ''
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        expect(dirs).toEqual([`foo${version}`]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it.each(['1.1.1', '2.2.2'])(
 | 
				
			||||||
 | 
					      'getCacheDirectoriesPaths yarn v%s should return 2 dirs with globbed cacheDependency',
 | 
				
			||||||
 | 
					      async version => {
 | 
				
			||||||
 | 
					        let dirNo = 1;
 | 
				
			||||||
 | 
					        getCommandOutputSpy.mockImplementation((command: string) =>
 | 
				
			||||||
 | 
					          command.includes('version') ? version : `file_${version}_${dirNo++}`
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        globCreateSpy.mockImplementation(
 | 
				
			||||||
 | 
					          (pattern: string): Promise<Globber> =>
 | 
				
			||||||
 | 
					            MockGlobber.create(['/tmp/dir1/file', '/tmp/dir2/file'])
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const dirs = await cacheUtils.getCacheDirectories(
 | 
				
			||||||
 | 
					          supportedPackageManagers.yarn,
 | 
				
			||||||
 | 
					          '/tmp/**/file'
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        expect(dirs).toEqual([`file_${version}_1`, `file_${version}_2`]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it.each(['1.1.1', '2.2.2'])(
 | 
				
			||||||
 | 
					      'getCacheDirectoriesPaths yarn v%s should return 2 dirs  with globbed cacheDependency expanding to duplicates',
 | 
				
			||||||
 | 
					      async version => {
 | 
				
			||||||
 | 
					        let dirNo = 1;
 | 
				
			||||||
 | 
					        getCommandOutputSpy.mockImplementation((command: string) =>
 | 
				
			||||||
 | 
					          command.includes('version') ? version : `file_${version}_${dirNo++}`
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        globCreateSpy.mockImplementation(
 | 
				
			||||||
 | 
					          (pattern: string): Promise<Globber> =>
 | 
				
			||||||
 | 
					            MockGlobber.create([
 | 
				
			||||||
 | 
					              '/tmp/dir1/file',
 | 
				
			||||||
 | 
					              '/tmp/dir2/file',
 | 
				
			||||||
 | 
					              '/tmp/dir1/file'
 | 
				
			||||||
 | 
					            ])
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const dirs = await cacheUtils.getCacheDirectories(
 | 
				
			||||||
 | 
					          supportedPackageManagers.yarn,
 | 
				
			||||||
 | 
					          '/tmp/**/file'
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        expect(dirs).toEqual([`file_${version}_1`, `file_${version}_2`]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it.each(['1.1.1', '2.2.2'])(
 | 
				
			||||||
 | 
					      'getCacheDirectoriesPaths yarn v%s should return 2 uniq dirs despite duplicate cache directories',
 | 
				
			||||||
 | 
					      async version => {
 | 
				
			||||||
 | 
					        let dirNo = 1;
 | 
				
			||||||
 | 
					        getCommandOutputSpy.mockImplementation((command: string) =>
 | 
				
			||||||
 | 
					          command.includes('version')
 | 
				
			||||||
 | 
					            ? version
 | 
				
			||||||
 | 
					            : `file_${version}_${dirNo++ % 2}`
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        globCreateSpy.mockImplementation(
 | 
				
			||||||
 | 
					          (pattern: string): Promise<Globber> =>
 | 
				
			||||||
 | 
					            MockGlobber.create([
 | 
				
			||||||
 | 
					              '/tmp/dir1/file',
 | 
				
			||||||
 | 
					              '/tmp/dir2/file',
 | 
				
			||||||
 | 
					              '/tmp/dir3/file'
 | 
				
			||||||
 | 
					            ])
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const dirs = await cacheUtils.getCacheDirectories(
 | 
				
			||||||
 | 
					          supportedPackageManagers.yarn,
 | 
				
			||||||
 | 
					          '/tmp/**/file'
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        expect(dirs).toEqual([`file_${version}_1`, `file_${version}_0`]);
 | 
				
			||||||
 | 
					        expect(getCommandOutputSpy).toHaveBeenCalledTimes(6);
 | 
				
			||||||
 | 
					        expect(getCommandOutputSpy).toHaveBeenCalledWith(
 | 
				
			||||||
 | 
					          'yarn --version',
 | 
				
			||||||
 | 
					          '/tmp/dir1'
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        expect(getCommandOutputSpy).toHaveBeenCalledWith(
 | 
				
			||||||
 | 
					          'yarn --version',
 | 
				
			||||||
 | 
					          '/tmp/dir2'
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        expect(getCommandOutputSpy).toHaveBeenCalledWith(
 | 
				
			||||||
 | 
					          'yarn --version',
 | 
				
			||||||
 | 
					          '/tmp/dir3'
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        expect(getCommandOutputSpy).toHaveBeenCalledWith(
 | 
				
			||||||
 | 
					          version.startsWith('1.')
 | 
				
			||||||
 | 
					            ? 'yarn cache dir'
 | 
				
			||||||
 | 
					            : 'yarn config get cacheFolder',
 | 
				
			||||||
 | 
					          '/tmp/dir1'
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        expect(getCommandOutputSpy).toHaveBeenCalledWith(
 | 
				
			||||||
 | 
					          version.startsWith('1.')
 | 
				
			||||||
 | 
					            ? 'yarn cache dir'
 | 
				
			||||||
 | 
					            : 'yarn config get cacheFolder',
 | 
				
			||||||
 | 
					          '/tmp/dir2'
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        expect(getCommandOutputSpy).toHaveBeenCalledWith(
 | 
				
			||||||
 | 
					          version.startsWith('1.')
 | 
				
			||||||
 | 
					            ? 'yarn cache dir'
 | 
				
			||||||
 | 
					            : 'yarn config get cacheFolder',
 | 
				
			||||||
 | 
					          '/tmp/dir3'
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it.each(['1.1.1', '2.2.2'])(
 | 
				
			||||||
 | 
					      'getCacheDirectoriesPaths yarn v%s should return 4 dirs with multiple globs',
 | 
				
			||||||
 | 
					      async version => {
 | 
				
			||||||
 | 
					        // simulate wrong indents
 | 
				
			||||||
 | 
					        const cacheDependencyPath = `/tmp/dir1/file
 | 
				
			||||||
 | 
					          /tmp/dir2/file
 | 
				
			||||||
 | 
					/tmp/**/file
 | 
				
			||||||
 | 
					          `;
 | 
				
			||||||
 | 
					        globCreateSpy.mockImplementation(
 | 
				
			||||||
 | 
					          (pattern: string): Promise<Globber> =>
 | 
				
			||||||
 | 
					            MockGlobber.create([
 | 
				
			||||||
 | 
					              '/tmp/dir1/file',
 | 
				
			||||||
 | 
					              '/tmp/dir2/file',
 | 
				
			||||||
 | 
					              '/tmp/dir3/file',
 | 
				
			||||||
 | 
					              '/tmp/dir4/file'
 | 
				
			||||||
 | 
					            ])
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        let dirNo = 1;
 | 
				
			||||||
 | 
					        getCommandOutputSpy.mockImplementation((command: string) =>
 | 
				
			||||||
 | 
					          command.includes('version') ? version : `file_${version}_${dirNo++}`
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        const dirs = await cacheUtils.getCacheDirectories(
 | 
				
			||||||
 | 
					          supportedPackageManagers.yarn,
 | 
				
			||||||
 | 
					          cacheDependencyPath
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        expect(dirs).toEqual([
 | 
				
			||||||
 | 
					          `file_${version}_1`,
 | 
				
			||||||
 | 
					          `file_${version}_2`,
 | 
				
			||||||
 | 
					          `file_${version}_3`,
 | 
				
			||||||
 | 
					          `file_${version}_4`
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										18
									
								
								__tests__/mock/glob-mock.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								__tests__/mock/glob-mock.test.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					import {MockGlobber} from './glob-mock';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('mocked globber tests', () => {
 | 
				
			||||||
 | 
					  it('globber should return generator', async () => {
 | 
				
			||||||
 | 
					    const globber = new MockGlobber(['aaa', 'bbb', 'ccc']);
 | 
				
			||||||
 | 
					    const generator = globber.globGenerator();
 | 
				
			||||||
 | 
					    const result: string[] = [];
 | 
				
			||||||
 | 
					    for await (const itemPath of generator) {
 | 
				
			||||||
 | 
					      result.push(itemPath);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    expect(result).toEqual(['aaa', 'bbb', 'ccc']);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  it('globber should return glob', async () => {
 | 
				
			||||||
 | 
					    const globber = new MockGlobber(['aaa', 'bbb', 'ccc']);
 | 
				
			||||||
 | 
					    const result: string[] = await globber.glob();
 | 
				
			||||||
 | 
					    expect(result).toEqual(['aaa', 'bbb', 'ccc']);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										29
									
								
								__tests__/mock/glob-mock.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								__tests__/mock/glob-mock.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					import {Globber} from '@actions/glob';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class MockGlobber implements Globber {
 | 
				
			||||||
 | 
					  private readonly expected: string[];
 | 
				
			||||||
 | 
					  constructor(expected: string[]) {
 | 
				
			||||||
 | 
					    this.expected = expected;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  getSearchPaths(): string[] {
 | 
				
			||||||
 | 
					    return this.expected.slice();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async glob(): Promise<string[]> {
 | 
				
			||||||
 | 
					    const result: string[] = [];
 | 
				
			||||||
 | 
					    for await (const itemPath of this.globGenerator()) {
 | 
				
			||||||
 | 
					      result.push(itemPath);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async *globGenerator(): AsyncGenerator<string, void> {
 | 
				
			||||||
 | 
					    for (const e of this.expected) {
 | 
				
			||||||
 | 
					      yield e;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static async create(expected: string[]): Promise<MockGlobber> {
 | 
				
			||||||
 | 
					    return new MockGlobber(expected);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										59
									
								
								__tests__/prepare-yarn-subprojects.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										59
									
								
								__tests__/prepare-yarn-subprojects.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					#!/bin/sh -e
 | 
				
			||||||
 | 
					export YARN_ENABLE_IMMUTABLE_INSTALLS=false
 | 
				
			||||||
 | 
					rm package.json
 | 
				
			||||||
 | 
					rm package-lock.json
 | 
				
			||||||
 | 
					echo "create yarn2 project in the sub2"
 | 
				
			||||||
 | 
					mkdir sub2
 | 
				
			||||||
 | 
					cd sub2
 | 
				
			||||||
 | 
					cat <<EOT >package.json
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "subproject",
 | 
				
			||||||
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "random": "^3.0.6",
 | 
				
			||||||
 | 
					    "uuid": "^9.0.0"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EOT
 | 
				
			||||||
 | 
					yarn set version 2.4.3
 | 
				
			||||||
 | 
					yarn install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "create yarn3 project in the sub3"
 | 
				
			||||||
 | 
					cd ..
 | 
				
			||||||
 | 
					mkdir sub3
 | 
				
			||||||
 | 
					cd sub3
 | 
				
			||||||
 | 
					cat <<EOT >package.json
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "subproject",
 | 
				
			||||||
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "random": "^3.0.6",
 | 
				
			||||||
 | 
					    "uuid": "^9.0.0"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EOT
 | 
				
			||||||
 | 
					yarn set version 3.5.1
 | 
				
			||||||
 | 
					yarn install
 | 
				
			||||||
 | 
					if [ x$1 = 'xglobal' ];then
 | 
				
			||||||
 | 
					  echo enableGlobalCache
 | 
				
			||||||
 | 
					  echo 'enableGlobalCache: true' >> .yarnrc.yml
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cd ..
 | 
				
			||||||
 | 
					if [ x$1 != 'xkeepcache' -a x$2 != 'xkeepcache' ]; then
 | 
				
			||||||
 | 
					  rm -rf sub2/.yarn/cache
 | 
				
			||||||
 | 
					  rm -rf sub3/.yarn/cache
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ x$1 = 'xyarn1' ];then
 | 
				
			||||||
 | 
					  echo "create yarn1 project in the root"
 | 
				
			||||||
 | 
					  cat <<EOT >package.json
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "subproject",
 | 
				
			||||||
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "random": "^3.0.6",
 | 
				
			||||||
 | 
					    "uuid": "^9.0.0"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EOT
 | 
				
			||||||
 | 
					  yarn set version 1.22.19
 | 
				
			||||||
 | 
					  yarn install
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
							
								
								
									
										1501
									
								
								dist/cache-save/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1501
									
								
								dist/cache-save/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										217
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										217
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							@ -71144,7 +71144,8 @@ const restoreCache = (packageManager, cacheDependencyPath) => __awaiter(void 0,
 | 
				
			|||||||
        throw new Error(`Caching for '${packageManager}' is not supported`);
 | 
					        throw new Error(`Caching for '${packageManager}' is not supported`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const platform = process.env.RUNNER_OS;
 | 
					    const platform = process.env.RUNNER_OS;
 | 
				
			||||||
    const cachePath = yield cache_utils_1.getCacheDirectoryPath(packageManagerInfo, packageManager);
 | 
					    const cachePaths = yield cache_utils_1.getCacheDirectories(packageManagerInfo, cacheDependencyPath);
 | 
				
			||||||
 | 
					    core.saveState(constants_1.State.CachePaths, cachePaths);
 | 
				
			||||||
    const lockFilePath = cacheDependencyPath
 | 
					    const lockFilePath = cacheDependencyPath
 | 
				
			||||||
        ? cacheDependencyPath
 | 
					        ? cacheDependencyPath
 | 
				
			||||||
        : findLockFile(packageManagerInfo);
 | 
					        : findLockFile(packageManagerInfo);
 | 
				
			||||||
@ -71152,10 +71153,19 @@ const restoreCache = (packageManager, cacheDependencyPath) => __awaiter(void 0,
 | 
				
			|||||||
    if (!fileHash) {
 | 
					    if (!fileHash) {
 | 
				
			||||||
        throw new Error('Some specified paths were not resolved, unable to cache dependencies.');
 | 
					        throw new Error('Some specified paths were not resolved, unable to cache dependencies.');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const primaryKey = `node-cache-${platform}-${packageManager}-${fileHash}`;
 | 
					    const keyPrefix = `node-cache-${platform}-${packageManager}`;
 | 
				
			||||||
 | 
					    const primaryKey = `${keyPrefix}-${fileHash}`;
 | 
				
			||||||
    core.debug(`primary key is ${primaryKey}`);
 | 
					    core.debug(`primary key is ${primaryKey}`);
 | 
				
			||||||
    core.saveState(constants_1.State.CachePrimaryKey, primaryKey);
 | 
					    core.saveState(constants_1.State.CachePrimaryKey, primaryKey);
 | 
				
			||||||
    const cacheKey = yield cache.restoreCache([cachePath], primaryKey);
 | 
					    const isManagedByYarnBerry = yield cache_utils_1.repoHasYarnBerryManagedDependencies(packageManagerInfo, cacheDependencyPath);
 | 
				
			||||||
 | 
					    let cacheKey;
 | 
				
			||||||
 | 
					    if (isManagedByYarnBerry) {
 | 
				
			||||||
 | 
					        core.info('All dependencies are managed locally by yarn3, the previous cache can be used');
 | 
				
			||||||
 | 
					        cacheKey = yield cache.restoreCache(cachePaths, primaryKey, [keyPrefix]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					        cacheKey = yield cache.restoreCache(cachePaths, primaryKey);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    core.setOutput('cache-hit', Boolean(cacheKey));
 | 
					    core.setOutput('cache-hit', Boolean(cacheKey));
 | 
				
			||||||
    if (!cacheKey) {
 | 
					    if (!cacheKey) {
 | 
				
			||||||
        core.info(`${packageManager} cache is not found`);
 | 
					        core.info(`${packageManager} cache is not found`);
 | 
				
			||||||
@ -71212,31 +71222,47 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
 | 
				
			|||||||
        step((generator = generator.apply(thisArg, _arguments || [])).next());
 | 
					        step((generator = generator.apply(thisArg, _arguments || [])).next());
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					var __importDefault = (this && this.__importDefault) || function (mod) {
 | 
				
			||||||
 | 
					    return (mod && mod.__esModule) ? mod : { "default": mod };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
 | 
					Object.defineProperty(exports, "__esModule", ({ value: true }));
 | 
				
			||||||
exports.isCacheFeatureAvailable = exports.isGhes = exports.getCacheDirectoryPath = exports.getPackageManagerInfo = exports.getCommandOutput = exports.supportedPackageManagers = void 0;
 | 
					exports.isCacheFeatureAvailable = exports.isGhes = exports.repoHasYarnBerryManagedDependencies = exports.getCacheDirectories = exports.resetProjectDirectoriesMemoized = exports.getPackageManagerInfo = exports.getCommandOutputNotEmpty = exports.getCommandOutput = exports.supportedPackageManagers = void 0;
 | 
				
			||||||
const core = __importStar(__nccwpck_require__(2186));
 | 
					const core = __importStar(__nccwpck_require__(2186));
 | 
				
			||||||
const exec = __importStar(__nccwpck_require__(1514));
 | 
					const exec = __importStar(__nccwpck_require__(1514));
 | 
				
			||||||
const cache = __importStar(__nccwpck_require__(7799));
 | 
					const cache = __importStar(__nccwpck_require__(7799));
 | 
				
			||||||
 | 
					const glob = __importStar(__nccwpck_require__(8090));
 | 
				
			||||||
 | 
					const path_1 = __importDefault(__nccwpck_require__(1017));
 | 
				
			||||||
 | 
					const fs_1 = __importDefault(__nccwpck_require__(7147));
 | 
				
			||||||
 | 
					const util_1 = __nccwpck_require__(2629);
 | 
				
			||||||
exports.supportedPackageManagers = {
 | 
					exports.supportedPackageManagers = {
 | 
				
			||||||
    npm: {
 | 
					    npm: {
 | 
				
			||||||
 | 
					        name: 'npm',
 | 
				
			||||||
        lockFilePatterns: ['package-lock.json', 'npm-shrinkwrap.json', 'yarn.lock'],
 | 
					        lockFilePatterns: ['package-lock.json', 'npm-shrinkwrap.json', 'yarn.lock'],
 | 
				
			||||||
        getCacheFolderCommand: 'npm config get cache'
 | 
					        getCacheFolderPath: () => exports.getCommandOutputNotEmpty('npm config get cache', 'Could not get npm cache folder path')
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    pnpm: {
 | 
					    pnpm: {
 | 
				
			||||||
 | 
					        name: 'pnpm',
 | 
				
			||||||
        lockFilePatterns: ['pnpm-lock.yaml'],
 | 
					        lockFilePatterns: ['pnpm-lock.yaml'],
 | 
				
			||||||
        getCacheFolderCommand: 'pnpm store path --silent'
 | 
					        getCacheFolderPath: () => exports.getCommandOutputNotEmpty('pnpm store path --silent', 'Could not get pnpm cache folder path')
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    yarn1: {
 | 
					    yarn: {
 | 
				
			||||||
 | 
					        name: 'yarn',
 | 
				
			||||||
        lockFilePatterns: ['yarn.lock'],
 | 
					        lockFilePatterns: ['yarn.lock'],
 | 
				
			||||||
        getCacheFolderCommand: 'yarn cache dir'
 | 
					        getCacheFolderPath: (projectDir) => __awaiter(void 0, void 0, void 0, function* () {
 | 
				
			||||||
    },
 | 
					            const yarnVersion = yield exports.getCommandOutputNotEmpty(`yarn --version`, 'Could not retrieve version of yarn', projectDir);
 | 
				
			||||||
    yarn2: {
 | 
					            core.debug(`Consumed yarn version is ${yarnVersion} (working dir: "${projectDir || ''}")`);
 | 
				
			||||||
        lockFilePatterns: ['yarn.lock'],
 | 
					            const stdOut = yarnVersion.startsWith('1.')
 | 
				
			||||||
        getCacheFolderCommand: 'yarn config get cacheFolder'
 | 
					                ? yield exports.getCommandOutput('yarn cache dir', projectDir)
 | 
				
			||||||
 | 
					                : yield exports.getCommandOutput('yarn config get cacheFolder', projectDir);
 | 
				
			||||||
 | 
					            if (!stdOut) {
 | 
				
			||||||
 | 
					                throw new Error(`Could not get yarn cache folder path for ${projectDir}`);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return stdOut;
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
const getCommandOutput = (toolCommand) => __awaiter(void 0, void 0, void 0, function* () {
 | 
					const getCommandOutput = (toolCommand, cwd) => __awaiter(void 0, void 0, void 0, function* () {
 | 
				
			||||||
    let { stdout, stderr, exitCode } = yield exec.getExecOutput(toolCommand, undefined, { ignoreReturnCode: true });
 | 
					    let { stdout, stderr, exitCode } = yield exec.getExecOutput(toolCommand, undefined, Object.assign({ ignoreReturnCode: true }, (cwd && { cwd })));
 | 
				
			||||||
    if (exitCode) {
 | 
					    if (exitCode) {
 | 
				
			||||||
        stderr = !stderr.trim()
 | 
					        stderr = !stderr.trim()
 | 
				
			||||||
            ? `The '${toolCommand}' command failed with exit code: ${exitCode}`
 | 
					            ? `The '${toolCommand}' command failed with exit code: ${exitCode}`
 | 
				
			||||||
@ -71246,13 +71272,14 @@ const getCommandOutput = (toolCommand) => __awaiter(void 0, void 0, void 0, func
 | 
				
			|||||||
    return stdout.trim();
 | 
					    return stdout.trim();
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
exports.getCommandOutput = getCommandOutput;
 | 
					exports.getCommandOutput = getCommandOutput;
 | 
				
			||||||
const getPackageManagerVersion = (packageManager, command) => __awaiter(void 0, void 0, void 0, function* () {
 | 
					const getCommandOutputNotEmpty = (toolCommand, error, cwd) => __awaiter(void 0, void 0, void 0, function* () {
 | 
				
			||||||
    const stdOut = yield exports.getCommandOutput(`${packageManager} ${command}`);
 | 
					    const stdOut = exports.getCommandOutput(toolCommand, cwd);
 | 
				
			||||||
    if (!stdOut) {
 | 
					    if (!stdOut) {
 | 
				
			||||||
        throw new Error(`Could not retrieve version of ${packageManager}`);
 | 
					        throw new Error(error);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return stdOut;
 | 
					    return stdOut;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					exports.getCommandOutputNotEmpty = getCommandOutputNotEmpty;
 | 
				
			||||||
const getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, void 0, function* () {
 | 
					const getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, void 0, function* () {
 | 
				
			||||||
    if (packageManager === 'npm') {
 | 
					    if (packageManager === 'npm') {
 | 
				
			||||||
        return exports.supportedPackageManagers.npm;
 | 
					        return exports.supportedPackageManagers.npm;
 | 
				
			||||||
@ -71261,29 +71288,142 @@ const getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, void
 | 
				
			|||||||
        return exports.supportedPackageManagers.pnpm;
 | 
					        return exports.supportedPackageManagers.pnpm;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (packageManager === 'yarn') {
 | 
					    else if (packageManager === 'yarn') {
 | 
				
			||||||
        const yarnVersion = yield getPackageManagerVersion('yarn', '--version');
 | 
					        return exports.supportedPackageManagers.yarn;
 | 
				
			||||||
        core.debug(`Consumed yarn version is ${yarnVersion}`);
 | 
					 | 
				
			||||||
        if (yarnVersion.startsWith('1.')) {
 | 
					 | 
				
			||||||
            return exports.supportedPackageManagers.yarn1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else {
 | 
					 | 
				
			||||||
            return exports.supportedPackageManagers.yarn2;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        return null;
 | 
					        return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
exports.getPackageManagerInfo = getPackageManagerInfo;
 | 
					exports.getPackageManagerInfo = getPackageManagerInfo;
 | 
				
			||||||
const getCacheDirectoryPath = (packageManagerInfo, packageManager) => __awaiter(void 0, void 0, void 0, function* () {
 | 
					/**
 | 
				
			||||||
    const stdOut = yield exports.getCommandOutput(packageManagerInfo.getCacheFolderCommand);
 | 
					 * getProjectDirectoriesFromCacheDependencyPath is called twice during `restoreCache`
 | 
				
			||||||
    if (!stdOut) {
 | 
					 *  - first through `getCacheDirectories`
 | 
				
			||||||
        throw new Error(`Could not get cache folder path for ${packageManager}`);
 | 
					 *  - second from `repoHasYarn3ManagedCache`
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  it contains expensive IO operation and thus should be memoized
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					let projectDirectoriesMemoized = null;
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * unit test must reset memoized variables
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const resetProjectDirectoriesMemoized = () => (projectDirectoriesMemoized = null);
 | 
				
			||||||
 | 
					exports.resetProjectDirectoriesMemoized = resetProjectDirectoriesMemoized;
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Expands (converts) the string input `cache-dependency-path` to list of directories that
 | 
				
			||||||
 | 
					 * may be project roots
 | 
				
			||||||
 | 
					 * @param cacheDependencyPath - either a single string or multiline string with possible glob patterns
 | 
				
			||||||
 | 
					 *                              expected to be the result of `core.getInput('cache-dependency-path')`
 | 
				
			||||||
 | 
					 * @return list of directories and possible
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const getProjectDirectoriesFromCacheDependencyPath = (cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {
 | 
				
			||||||
 | 
					    if (projectDirectoriesMemoized !== null) {
 | 
				
			||||||
 | 
					        return projectDirectoriesMemoized;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    core.debug(`${packageManager} path is ${stdOut}`);
 | 
					    const globber = yield glob.create(cacheDependencyPath);
 | 
				
			||||||
    return stdOut.trim();
 | 
					    const cacheDependenciesPaths = yield globber.glob();
 | 
				
			||||||
 | 
					    const existingDirectories = cacheDependenciesPaths
 | 
				
			||||||
 | 
					        .map(path_1.default.dirname)
 | 
				
			||||||
 | 
					        .filter(util_1.unique())
 | 
				
			||||||
 | 
					        .filter(directory => fs_1.default.lstatSync(directory).isDirectory());
 | 
				
			||||||
 | 
					    if (!existingDirectories.length)
 | 
				
			||||||
 | 
					        core.warning(`No existing directories found containing cache-dependency-path="${cacheDependencyPath}"`);
 | 
				
			||||||
 | 
					    projectDirectoriesMemoized = existingDirectories;
 | 
				
			||||||
 | 
					    return existingDirectories;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
exports.getCacheDirectoryPath = getCacheDirectoryPath;
 | 
					/**
 | 
				
			||||||
 | 
					 * Finds the cache directories configured for the repo if cache-dependency-path is not empty
 | 
				
			||||||
 | 
					 * @param packageManagerInfo - an object having getCacheFolderPath method specific to given PM
 | 
				
			||||||
 | 
					 * @param cacheDependencyPath - either a single string or multiline string with possible glob patterns
 | 
				
			||||||
 | 
					 *                              expected to be the result of `core.getInput('cache-dependency-path')`
 | 
				
			||||||
 | 
					 * @return list of files on which the cache depends
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const getCacheDirectoriesFromCacheDependencyPath = (packageManagerInfo, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {
 | 
				
			||||||
 | 
					    const projectDirectories = yield getProjectDirectoriesFromCacheDependencyPath(cacheDependencyPath);
 | 
				
			||||||
 | 
					    const cacheFoldersPaths = yield Promise.all(projectDirectories.map((projectDirectory) => __awaiter(void 0, void 0, void 0, function* () {
 | 
				
			||||||
 | 
					        const cacheFolderPath = yield packageManagerInfo.getCacheFolderPath(projectDirectory);
 | 
				
			||||||
 | 
					        core.debug(`${packageManagerInfo.name}'s cache folder "${cacheFolderPath}" configured for the directory "${projectDirectory}"`);
 | 
				
			||||||
 | 
					        return cacheFolderPath;
 | 
				
			||||||
 | 
					    })));
 | 
				
			||||||
 | 
					    // uniq in order to do not cache the same directories twice
 | 
				
			||||||
 | 
					    return cacheFoldersPaths.filter(util_1.unique());
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Finds the cache directories configured for the repo ignoring cache-dependency-path
 | 
				
			||||||
 | 
					 * @param packageManagerInfo - an object having getCacheFolderPath method specific to given PM
 | 
				
			||||||
 | 
					 * @return list of files on which the cache depends
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const getCacheDirectoriesForRootProject = (packageManagerInfo) => __awaiter(void 0, void 0, void 0, function* () {
 | 
				
			||||||
 | 
					    const cacheFolderPath = yield packageManagerInfo.getCacheFolderPath();
 | 
				
			||||||
 | 
					    core.debug(`${packageManagerInfo.name}'s cache folder "${cacheFolderPath}" configured for the root directory`);
 | 
				
			||||||
 | 
					    return [cacheFolderPath];
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A function to find the cache directories configured for the repo
 | 
				
			||||||
 | 
					 * currently it handles only the case of PM=yarn && cacheDependencyPath is not empty
 | 
				
			||||||
 | 
					 * @param packageManagerInfo - an object having getCacheFolderPath method specific to given PM
 | 
				
			||||||
 | 
					 * @param cacheDependencyPath - either a single string or multiline string with possible glob patterns
 | 
				
			||||||
 | 
					 *                              expected to be the result of `core.getInput('cache-dependency-path')`
 | 
				
			||||||
 | 
					 * @return list of files on which the cache depends
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const getCacheDirectories = (packageManagerInfo, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {
 | 
				
			||||||
 | 
					    // For yarn, if cacheDependencyPath is set, ask information about cache folders in each project
 | 
				
			||||||
 | 
					    // folder satisfied by cacheDependencyPath https://github.com/actions/setup-node/issues/488
 | 
				
			||||||
 | 
					    if (packageManagerInfo.name === 'yarn' && cacheDependencyPath) {
 | 
				
			||||||
 | 
					        return getCacheDirectoriesFromCacheDependencyPath(packageManagerInfo, cacheDependencyPath);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return getCacheDirectoriesForRootProject(packageManagerInfo);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					exports.getCacheDirectories = getCacheDirectories;
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A function to check if the directory is a yarn project configured to manage
 | 
				
			||||||
 | 
					 * obsolete dependencies in the local cache
 | 
				
			||||||
 | 
					 * @param directory - a path to the folder
 | 
				
			||||||
 | 
					 * @return - true if the directory's project is yarn managed
 | 
				
			||||||
 | 
					 *  - if there's .yarn/cache folder do not mess with the dependencies kept in the repo, return false
 | 
				
			||||||
 | 
					 *  - global cache is not managed by yarn @see https://yarnpkg.com/features/offline-cache, return false
 | 
				
			||||||
 | 
					 *  - if local cache is not explicitly enabled (not yarn3), return false
 | 
				
			||||||
 | 
					 *  - return true otherwise
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const projectHasYarnBerryManagedDependencies = (directory) => __awaiter(void 0, void 0, void 0, function* () {
 | 
				
			||||||
 | 
					    const workDir = directory || process.env.GITHUB_WORKSPACE || '.';
 | 
				
			||||||
 | 
					    core.debug(`check if "${workDir}" has locally managed yarn3 dependencies`);
 | 
				
			||||||
 | 
					    // if .yarn/cache directory exists the cache is managed by version control system
 | 
				
			||||||
 | 
					    const yarnCacheFile = path_1.default.join(workDir, '.yarn', 'cache');
 | 
				
			||||||
 | 
					    if (fs_1.default.existsSync(yarnCacheFile) &&
 | 
				
			||||||
 | 
					        fs_1.default.lstatSync(yarnCacheFile).isDirectory()) {
 | 
				
			||||||
 | 
					        core.debug(`"${workDir}" has .yarn/cache - dependencies are kept in the repository`);
 | 
				
			||||||
 | 
					        return Promise.resolve(false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // NOTE: yarn1 returns 'undefined' with return code = 0
 | 
				
			||||||
 | 
					    const enableGlobalCache = yield exports.getCommandOutput('yarn config get enableGlobalCache', workDir);
 | 
				
			||||||
 | 
					    // only local cache is not managed by yarn
 | 
				
			||||||
 | 
					    const managed = enableGlobalCache.includes('false');
 | 
				
			||||||
 | 
					    if (managed) {
 | 
				
			||||||
 | 
					        core.debug(`"${workDir}" dependencies are managed by yarn 3 locally`);
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					        core.debug(`"${workDir}" dependencies are not managed by yarn 3 locally`);
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A function to report the repo contains Yarn managed projects
 | 
				
			||||||
 | 
					 * @param packageManagerInfo - used to make sure current package manager is yarn
 | 
				
			||||||
 | 
					 * @param cacheDependencyPath - either a single string or multiline string with possible glob patterns
 | 
				
			||||||
 | 
					 *                              expected to be the result of `core.getInput('cache-dependency-path')`
 | 
				
			||||||
 | 
					 * @return - true if all project directories configured to be Yarn managed
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const repoHasYarnBerryManagedDependencies = (packageManagerInfo, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {
 | 
				
			||||||
 | 
					    if (packageManagerInfo.name !== 'yarn')
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    const yarnDirs = cacheDependencyPath
 | 
				
			||||||
 | 
					        ? yield getProjectDirectoriesFromCacheDependencyPath(cacheDependencyPath)
 | 
				
			||||||
 | 
					        : [''];
 | 
				
			||||||
 | 
					    const isManagedList = yield Promise.all(yarnDirs.map(projectHasYarnBerryManagedDependencies));
 | 
				
			||||||
 | 
					    return isManagedList.every(Boolean);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					exports.repoHasYarnBerryManagedDependencies = repoHasYarnBerryManagedDependencies;
 | 
				
			||||||
function isGhes() {
 | 
					function isGhes() {
 | 
				
			||||||
    const ghUrl = new URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com');
 | 
					    const ghUrl = new URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com');
 | 
				
			||||||
    return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
 | 
					    return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
 | 
				
			||||||
@ -71321,6 +71461,7 @@ var State;
 | 
				
			|||||||
(function (State) {
 | 
					(function (State) {
 | 
				
			||||||
    State["CachePrimaryKey"] = "CACHE_KEY";
 | 
					    State["CachePrimaryKey"] = "CACHE_KEY";
 | 
				
			||||||
    State["CacheMatchedKey"] = "CACHE_RESULT";
 | 
					    State["CacheMatchedKey"] = "CACHE_RESULT";
 | 
				
			||||||
 | 
					    State["CachePaths"] = "CACHE_PATHS";
 | 
				
			||||||
})(State = exports.State || (exports.State = {}));
 | 
					})(State = exports.State || (exports.State = {}));
 | 
				
			||||||
var Outputs;
 | 
					var Outputs;
 | 
				
			||||||
(function (Outputs) {
 | 
					(function (Outputs) {
 | 
				
			||||||
@ -72159,7 +72300,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
 | 
					Object.defineProperty(exports, "__esModule", ({ value: true }));
 | 
				
			||||||
exports.printEnvDetailsAndSetOutput = exports.parseNodeVersionFile = void 0;
 | 
					exports.unique = exports.printEnvDetailsAndSetOutput = exports.parseNodeVersionFile = void 0;
 | 
				
			||||||
const core = __importStar(__nccwpck_require__(2186));
 | 
					const core = __importStar(__nccwpck_require__(2186));
 | 
				
			||||||
const exec = __importStar(__nccwpck_require__(1514));
 | 
					const exec = __importStar(__nccwpck_require__(1514));
 | 
				
			||||||
function parseNodeVersionFile(contents) {
 | 
					function parseNodeVersionFile(contents) {
 | 
				
			||||||
@ -72221,6 +72362,16 @@ function getToolVersion(tool, options) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					const unique = () => {
 | 
				
			||||||
 | 
					    const encountered = new Set();
 | 
				
			||||||
 | 
					    return (value) => {
 | 
				
			||||||
 | 
					        if (encountered.has(value))
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        encountered.add(value);
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					exports.unique = unique;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/***/ }),
 | 
					/***/ }),
 | 
				
			||||||
 | 
				
			|||||||
@ -261,10 +261,14 @@ steps:
 | 
				
			|||||||
  with:
 | 
					  with:
 | 
				
			||||||
    node-version: '14'
 | 
					    node-version: '14'
 | 
				
			||||||
    cache: 'pnpm'
 | 
					    cache: 'pnpm'
 | 
				
			||||||
- run: pnpm install --frozen-lockfile
 | 
					- run: pnpm install
 | 
				
			||||||
- run: pnpm test
 | 
					- run: pnpm test
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> **Note**: By default `--frozen-lockfile` option is passed starting from pnpm `6.10.x`. It will be automatically added if you run it on [CI](https://pnpm.io/cli/install#--frozen-lockfile). 
 | 
				
			||||||
 | 
					> If the `pnpm-lock.yaml` file changes then pass `--frozen-lockfile` option.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**Using wildcard patterns to cache dependencies**
 | 
					**Using wildcard patterns to cache dependencies**
 | 
				
			||||||
```yaml
 | 
					```yaml
 | 
				
			||||||
steps:
 | 
					steps:
 | 
				
			||||||
@ -401,11 +405,14 @@ steps:
 | 
				
			|||||||
    yarn config set npmScopes.my-org.npmAlwaysAuth true
 | 
					    yarn config set npmScopes.my-org.npmAlwaysAuth true
 | 
				
			||||||
    yarn config set npmScopes.my-org.npmAuthToken $NPM_AUTH_TOKEN
 | 
					    yarn config set npmScopes.my-org.npmAuthToken $NPM_AUTH_TOKEN
 | 
				
			||||||
  env:
 | 
					  env:
 | 
				
			||||||
    NPM_AUTH_TOKEN: ${{ secrets.YARN_TOKEN }}
 | 
					    NPM_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
				
			||||||
- name: Install dependencies
 | 
					- name: Install dependencies
 | 
				
			||||||
  run: yarn install --immutable
 | 
					  run: yarn install --immutable
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
NOTE: As per https://github.com/actions/setup-node/issues/49 you cannot use `secrets.GITHUB_TOKEN` to access private GitHub Packages within the same organisation but in a different repository.
 | 
					
 | 
				
			||||||
 | 
					To access private GitHub Packages within the same organization, go to "Manage Actions access" in Package settings and set the repositories you want to access.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please refer to the [Ensuring workflow access to your package - Configuring a package's access control and visibility](https://docs.github.com/en/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility#ensuring-workflow-access-to-your-package) for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### always-auth input
 | 
					### always-auth input
 | 
				
			||||||
The always-auth input sets `always-auth=true` in .npmrc file. With this option set [npm](https://docs.npmjs.com/cli/v6/using-npm/config#always-auth)/yarn sends the authentication credentials when making a request to the registries.
 | 
					The always-auth input sets `always-auth=true` in .npmrc file. With this option set [npm](https://docs.npmjs.com/cli/v6/using-npm/config#always-auth)/yarn sends the authentication credentials when making a request to the registries.
 | 
				
			||||||
 | 
				
			|||||||
@ -6,14 +6,15 @@ import fs from 'fs';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import {State} from './constants';
 | 
					import {State} from './constants';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  getCacheDirectoryPath,
 | 
					  getCacheDirectories,
 | 
				
			||||||
  getPackageManagerInfo,
 | 
					  getPackageManagerInfo,
 | 
				
			||||||
 | 
					  repoHasYarnBerryManagedDependencies,
 | 
				
			||||||
  PackageManagerInfo
 | 
					  PackageManagerInfo
 | 
				
			||||||
} from './cache-utils';
 | 
					} from './cache-utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const restoreCache = async (
 | 
					export const restoreCache = async (
 | 
				
			||||||
  packageManager: string,
 | 
					  packageManager: string,
 | 
				
			||||||
  cacheDependencyPath?: string
 | 
					  cacheDependencyPath: string
 | 
				
			||||||
) => {
 | 
					) => {
 | 
				
			||||||
  const packageManagerInfo = await getPackageManagerInfo(packageManager);
 | 
					  const packageManagerInfo = await getPackageManagerInfo(packageManager);
 | 
				
			||||||
  if (!packageManagerInfo) {
 | 
					  if (!packageManagerInfo) {
 | 
				
			||||||
@ -21,10 +22,11 @@ export const restoreCache = async (
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  const platform = process.env.RUNNER_OS;
 | 
					  const platform = process.env.RUNNER_OS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const cachePath = await getCacheDirectoryPath(
 | 
					  const cachePaths = await getCacheDirectories(
 | 
				
			||||||
    packageManagerInfo,
 | 
					    packageManagerInfo,
 | 
				
			||||||
    packageManager
 | 
					    cacheDependencyPath
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					  core.saveState(State.CachePaths, cachePaths);
 | 
				
			||||||
  const lockFilePath = cacheDependencyPath
 | 
					  const lockFilePath = cacheDependencyPath
 | 
				
			||||||
    ? cacheDependencyPath
 | 
					    ? cacheDependencyPath
 | 
				
			||||||
    : findLockFile(packageManagerInfo);
 | 
					    : findLockFile(packageManagerInfo);
 | 
				
			||||||
@ -36,12 +38,26 @@ export const restoreCache = async (
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const primaryKey = `node-cache-${platform}-${packageManager}-${fileHash}`;
 | 
					  const keyPrefix = `node-cache-${platform}-${packageManager}`;
 | 
				
			||||||
 | 
					  const primaryKey = `${keyPrefix}-${fileHash}`;
 | 
				
			||||||
  core.debug(`primary key is ${primaryKey}`);
 | 
					  core.debug(`primary key is ${primaryKey}`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  core.saveState(State.CachePrimaryKey, primaryKey);
 | 
					  core.saveState(State.CachePrimaryKey, primaryKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const cacheKey = await cache.restoreCache([cachePath], primaryKey);
 | 
					  const isManagedByYarnBerry = await repoHasYarnBerryManagedDependencies(
 | 
				
			||||||
 | 
					    packageManagerInfo,
 | 
				
			||||||
 | 
					    cacheDependencyPath
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  let cacheKey: string | undefined;
 | 
				
			||||||
 | 
					  if (isManagedByYarnBerry) {
 | 
				
			||||||
 | 
					    core.info(
 | 
				
			||||||
 | 
					      'All dependencies are managed locally by yarn3, the previous cache can be used'
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    cacheKey = await cache.restoreCache(cachePaths, primaryKey, [keyPrefix]);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    cacheKey = await cache.restoreCache(cachePaths, primaryKey);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  core.setOutput('cache-hit', Boolean(cacheKey));
 | 
					  core.setOutput('cache-hit', Boolean(cacheKey));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!cacheKey) {
 | 
					  if (!cacheKey) {
 | 
				
			||||||
@ -56,6 +72,7 @@ export const restoreCache = async (
 | 
				
			|||||||
const findLockFile = (packageManager: PackageManagerInfo) => {
 | 
					const findLockFile = (packageManager: PackageManagerInfo) => {
 | 
				
			||||||
  const lockFiles = packageManager.lockFilePatterns;
 | 
					  const lockFiles = packageManager.lockFilePatterns;
 | 
				
			||||||
  const workspace = process.env.GITHUB_WORKSPACE!;
 | 
					  const workspace = process.env.GITHUB_WORKSPACE!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const rootContent = fs.readdirSync(workspace);
 | 
					  const rootContent = fs.readdirSync(workspace);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const lockFile = lockFiles.find(item => rootContent.includes(item));
 | 
					  const lockFile = lockFiles.find(item => rootContent.includes(item));
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,7 @@
 | 
				
			|||||||
import * as core from '@actions/core';
 | 
					import * as core from '@actions/core';
 | 
				
			||||||
import * as cache from '@actions/cache';
 | 
					import * as cache from '@actions/cache';
 | 
				
			||||||
import fs from 'fs';
 | 
					 | 
				
			||||||
import {State} from './constants';
 | 
					import {State} from './constants';
 | 
				
			||||||
import {getCacheDirectoryPath, getPackageManagerInfo} from './cache-utils';
 | 
					import {getPackageManagerInfo} from './cache-utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Catch and log any unhandled exceptions.  These exceptions can leak out of the uploadChunk method in
 | 
					// Catch and log any unhandled exceptions.  These exceptions can leak out of the uploadChunk method in
 | 
				
			||||||
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
 | 
					// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
 | 
				
			||||||
@ -24,6 +23,7 @@ export async function run() {
 | 
				
			|||||||
const cachePackages = async (packageManager: string) => {
 | 
					const cachePackages = async (packageManager: string) => {
 | 
				
			||||||
  const state = core.getState(State.CacheMatchedKey);
 | 
					  const state = core.getState(State.CacheMatchedKey);
 | 
				
			||||||
  const primaryKey = core.getState(State.CachePrimaryKey);
 | 
					  const primaryKey = core.getState(State.CachePrimaryKey);
 | 
				
			||||||
 | 
					  const cachePaths = JSON.parse(core.getState(State.CachePaths) || '[]');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const packageManagerInfo = await getPackageManagerInfo(packageManager);
 | 
					  const packageManagerInfo = await getPackageManagerInfo(packageManager);
 | 
				
			||||||
  if (!packageManagerInfo) {
 | 
					  if (!packageManagerInfo) {
 | 
				
			||||||
@ -31,14 +31,12 @@ const cachePackages = async (packageManager: string) => {
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const cachePath = await getCacheDirectoryPath(
 | 
					  if (cachePaths.length === 0) {
 | 
				
			||||||
    packageManagerInfo,
 | 
					    // TODO: core.getInput has a bug - it can return undefined despite its definition (tests only?)
 | 
				
			||||||
    packageManager
 | 
					    //       export declare function getInput(name: string, options?: InputOptions): string;
 | 
				
			||||||
  );
 | 
					    const cacheDependencyPath = core.getInput('cache-dependency-path') || '';
 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!fs.existsSync(cachePath)) {
 | 
					 | 
				
			||||||
    throw new Error(
 | 
					    throw new Error(
 | 
				
			||||||
      `Cache folder path is retrieved for ${packageManager} but doesn't exist on disk: ${cachePath}`
 | 
					      `Cache folder paths are not retrieved for ${packageManager} with cache-dependency-path = ${cacheDependencyPath}`
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -49,7 +47,7 @@ const cachePackages = async (packageManager: string) => {
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const cacheId = await cache.saveCache([cachePath], primaryKey);
 | 
					  const cacheId = await cache.saveCache(cachePaths, primaryKey);
 | 
				
			||||||
  if (cacheId == -1) {
 | 
					  if (cacheId == -1) {
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,40 +1,79 @@
 | 
				
			|||||||
import * as core from '@actions/core';
 | 
					import * as core from '@actions/core';
 | 
				
			||||||
import * as exec from '@actions/exec';
 | 
					import * as exec from '@actions/exec';
 | 
				
			||||||
import * as cache from '@actions/cache';
 | 
					import * as cache from '@actions/cache';
 | 
				
			||||||
 | 
					import * as glob from '@actions/glob';
 | 
				
			||||||
type SupportedPackageManagers = {
 | 
					import path from 'path';
 | 
				
			||||||
  [prop: string]: PackageManagerInfo;
 | 
					import fs from 'fs';
 | 
				
			||||||
};
 | 
					import {unique} from './util';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface PackageManagerInfo {
 | 
					export interface PackageManagerInfo {
 | 
				
			||||||
 | 
					  name: string;
 | 
				
			||||||
  lockFilePatterns: Array<string>;
 | 
					  lockFilePatterns: Array<string>;
 | 
				
			||||||
  getCacheFolderCommand: string;
 | 
					  getCacheFolderPath: (projectDir?: string) => Promise<string>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface SupportedPackageManagers {
 | 
				
			||||||
 | 
					  npm: PackageManagerInfo;
 | 
				
			||||||
 | 
					  pnpm: PackageManagerInfo;
 | 
				
			||||||
 | 
					  yarn: PackageManagerInfo;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
export const supportedPackageManagers: SupportedPackageManagers = {
 | 
					export const supportedPackageManagers: SupportedPackageManagers = {
 | 
				
			||||||
  npm: {
 | 
					  npm: {
 | 
				
			||||||
 | 
					    name: 'npm',
 | 
				
			||||||
    lockFilePatterns: ['package-lock.json', 'npm-shrinkwrap.json', 'yarn.lock'],
 | 
					    lockFilePatterns: ['package-lock.json', 'npm-shrinkwrap.json', 'yarn.lock'],
 | 
				
			||||||
    getCacheFolderCommand: 'npm config get cache'
 | 
					    getCacheFolderPath: () =>
 | 
				
			||||||
 | 
					      getCommandOutputNotEmpty(
 | 
				
			||||||
 | 
					        'npm config get cache',
 | 
				
			||||||
 | 
					        'Could not get npm cache folder path'
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  pnpm: {
 | 
					  pnpm: {
 | 
				
			||||||
 | 
					    name: 'pnpm',
 | 
				
			||||||
    lockFilePatterns: ['pnpm-lock.yaml'],
 | 
					    lockFilePatterns: ['pnpm-lock.yaml'],
 | 
				
			||||||
    getCacheFolderCommand: 'pnpm store path --silent'
 | 
					    getCacheFolderPath: () =>
 | 
				
			||||||
 | 
					      getCommandOutputNotEmpty(
 | 
				
			||||||
 | 
					        'pnpm store path --silent',
 | 
				
			||||||
 | 
					        'Could not get pnpm cache folder path'
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  yarn1: {
 | 
					  yarn: {
 | 
				
			||||||
 | 
					    name: 'yarn',
 | 
				
			||||||
    lockFilePatterns: ['yarn.lock'],
 | 
					    lockFilePatterns: ['yarn.lock'],
 | 
				
			||||||
    getCacheFolderCommand: 'yarn cache dir'
 | 
					    getCacheFolderPath: async projectDir => {
 | 
				
			||||||
  },
 | 
					      const yarnVersion = await getCommandOutputNotEmpty(
 | 
				
			||||||
  yarn2: {
 | 
					        `yarn --version`,
 | 
				
			||||||
    lockFilePatterns: ['yarn.lock'],
 | 
					        'Could not retrieve version of yarn',
 | 
				
			||||||
    getCacheFolderCommand: 'yarn config get cacheFolder'
 | 
					        projectDir
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      core.debug(
 | 
				
			||||||
 | 
					        `Consumed yarn version is ${yarnVersion} (working dir: "${
 | 
				
			||||||
 | 
					          projectDir || ''
 | 
				
			||||||
 | 
					        }")`
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const stdOut = yarnVersion.startsWith('1.')
 | 
				
			||||||
 | 
					        ? await getCommandOutput('yarn cache dir', projectDir)
 | 
				
			||||||
 | 
					        : await getCommandOutput('yarn config get cacheFolder', projectDir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (!stdOut) {
 | 
				
			||||||
 | 
					        throw new Error(
 | 
				
			||||||
 | 
					          `Could not get yarn cache folder path for ${projectDir}`
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return stdOut;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getCommandOutput = async (toolCommand: string) => {
 | 
					export const getCommandOutput = async (
 | 
				
			||||||
 | 
					  toolCommand: string,
 | 
				
			||||||
 | 
					  cwd?: string
 | 
				
			||||||
 | 
					): Promise<string> => {
 | 
				
			||||||
  let {stdout, stderr, exitCode} = await exec.getExecOutput(
 | 
					  let {stdout, stderr, exitCode} = await exec.getExecOutput(
 | 
				
			||||||
    toolCommand,
 | 
					    toolCommand,
 | 
				
			||||||
    undefined,
 | 
					    undefined,
 | 
				
			||||||
    {ignoreReturnCode: true}
 | 
					    {ignoreReturnCode: true, ...(cwd && {cwd})}
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (exitCode) {
 | 
					  if (exitCode) {
 | 
				
			||||||
@ -47,16 +86,15 @@ export const getCommandOutput = async (toolCommand: string) => {
 | 
				
			|||||||
  return stdout.trim();
 | 
					  return stdout.trim();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getPackageManagerVersion = async (
 | 
					export const getCommandOutputNotEmpty = async (
 | 
				
			||||||
  packageManager: string,
 | 
					  toolCommand: string,
 | 
				
			||||||
  command: string
 | 
					  error: string,
 | 
				
			||||||
) => {
 | 
					  cwd?: string
 | 
				
			||||||
  const stdOut = await getCommandOutput(`${packageManager} ${command}`);
 | 
					): Promise<string> => {
 | 
				
			||||||
 | 
					  const stdOut = getCommandOutput(toolCommand, cwd);
 | 
				
			||||||
  if (!stdOut) {
 | 
					  if (!stdOut) {
 | 
				
			||||||
    throw new Error(`Could not retrieve version of ${packageManager}`);
 | 
					    throw new Error(error);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  return stdOut;
 | 
					  return stdOut;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -66,35 +104,190 @@ export const getPackageManagerInfo = async (packageManager: string) => {
 | 
				
			|||||||
  } else if (packageManager === 'pnpm') {
 | 
					  } else if (packageManager === 'pnpm') {
 | 
				
			||||||
    return supportedPackageManagers.pnpm;
 | 
					    return supportedPackageManagers.pnpm;
 | 
				
			||||||
  } else if (packageManager === 'yarn') {
 | 
					  } else if (packageManager === 'yarn') {
 | 
				
			||||||
    const yarnVersion = await getPackageManagerVersion('yarn', '--version');
 | 
					    return supportedPackageManagers.yarn;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    core.debug(`Consumed yarn version is ${yarnVersion}`);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (yarnVersion.startsWith('1.')) {
 | 
					 | 
				
			||||||
      return supportedPackageManagers.yarn1;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      return supportedPackageManagers.yarn2;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    return null;
 | 
					    return null;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getCacheDirectoryPath = async (
 | 
					/**
 | 
				
			||||||
  packageManagerInfo: PackageManagerInfo,
 | 
					 * getProjectDirectoriesFromCacheDependencyPath is called twice during `restoreCache`
 | 
				
			||||||
  packageManager: string
 | 
					 *  - first through `getCacheDirectories`
 | 
				
			||||||
) => {
 | 
					 *  - second from `repoHasYarn3ManagedCache`
 | 
				
			||||||
  const stdOut = await getCommandOutput(
 | 
					 *
 | 
				
			||||||
    packageManagerInfo.getCacheFolderCommand
 | 
					 *  it contains expensive IO operation and thus should be memoized
 | 
				
			||||||
  );
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!stdOut) {
 | 
					let projectDirectoriesMemoized: string[] | null = null;
 | 
				
			||||||
    throw new Error(`Could not get cache folder path for ${packageManager}`);
 | 
					/**
 | 
				
			||||||
 | 
					 * unit test must reset memoized variables
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const resetProjectDirectoriesMemoized = () =>
 | 
				
			||||||
 | 
					  (projectDirectoriesMemoized = null);
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Expands (converts) the string input `cache-dependency-path` to list of directories that
 | 
				
			||||||
 | 
					 * may be project roots
 | 
				
			||||||
 | 
					 * @param cacheDependencyPath - either a single string or multiline string with possible glob patterns
 | 
				
			||||||
 | 
					 *                              expected to be the result of `core.getInput('cache-dependency-path')`
 | 
				
			||||||
 | 
					 * @return list of directories and possible
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const getProjectDirectoriesFromCacheDependencyPath = async (
 | 
				
			||||||
 | 
					  cacheDependencyPath: string
 | 
				
			||||||
 | 
					): Promise<string[]> => {
 | 
				
			||||||
 | 
					  if (projectDirectoriesMemoized !== null) {
 | 
				
			||||||
 | 
					    return projectDirectoriesMemoized;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  core.debug(`${packageManager} path is ${stdOut}`);
 | 
					  const globber = await glob.create(cacheDependencyPath);
 | 
				
			||||||
 | 
					  const cacheDependenciesPaths = await globber.glob();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return stdOut.trim();
 | 
					  const existingDirectories: string[] = cacheDependenciesPaths
 | 
				
			||||||
 | 
					    .map(path.dirname)
 | 
				
			||||||
 | 
					    .filter(unique())
 | 
				
			||||||
 | 
					    .filter(directory => fs.lstatSync(directory).isDirectory());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!existingDirectories.length)
 | 
				
			||||||
 | 
					    core.warning(
 | 
				
			||||||
 | 
					      `No existing directories found containing cache-dependency-path="${cacheDependencyPath}"`
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  projectDirectoriesMemoized = existingDirectories;
 | 
				
			||||||
 | 
					  return existingDirectories;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Finds the cache directories configured for the repo if cache-dependency-path is not empty
 | 
				
			||||||
 | 
					 * @param packageManagerInfo - an object having getCacheFolderPath method specific to given PM
 | 
				
			||||||
 | 
					 * @param cacheDependencyPath - either a single string or multiline string with possible glob patterns
 | 
				
			||||||
 | 
					 *                              expected to be the result of `core.getInput('cache-dependency-path')`
 | 
				
			||||||
 | 
					 * @return list of files on which the cache depends
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const getCacheDirectoriesFromCacheDependencyPath = async (
 | 
				
			||||||
 | 
					  packageManagerInfo: PackageManagerInfo,
 | 
				
			||||||
 | 
					  cacheDependencyPath: string
 | 
				
			||||||
 | 
					): Promise<string[]> => {
 | 
				
			||||||
 | 
					  const projectDirectories = await getProjectDirectoriesFromCacheDependencyPath(
 | 
				
			||||||
 | 
					    cacheDependencyPath
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  const cacheFoldersPaths = await Promise.all(
 | 
				
			||||||
 | 
					    projectDirectories.map(async projectDirectory => {
 | 
				
			||||||
 | 
					      const cacheFolderPath = await packageManagerInfo.getCacheFolderPath(
 | 
				
			||||||
 | 
					        projectDirectory
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      core.debug(
 | 
				
			||||||
 | 
					        `${packageManagerInfo.name}'s cache folder "${cacheFolderPath}" configured for the directory "${projectDirectory}"`
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      return cacheFolderPath;
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  // uniq in order to do not cache the same directories twice
 | 
				
			||||||
 | 
					  return cacheFoldersPaths.filter(unique());
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Finds the cache directories configured for the repo ignoring cache-dependency-path
 | 
				
			||||||
 | 
					 * @param packageManagerInfo - an object having getCacheFolderPath method specific to given PM
 | 
				
			||||||
 | 
					 * @return list of files on which the cache depends
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const getCacheDirectoriesForRootProject = async (
 | 
				
			||||||
 | 
					  packageManagerInfo: PackageManagerInfo
 | 
				
			||||||
 | 
					): Promise<string[]> => {
 | 
				
			||||||
 | 
					  const cacheFolderPath = await packageManagerInfo.getCacheFolderPath();
 | 
				
			||||||
 | 
					  core.debug(
 | 
				
			||||||
 | 
					    `${packageManagerInfo.name}'s cache folder "${cacheFolderPath}" configured for the root directory`
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  return [cacheFolderPath];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A function to find the cache directories configured for the repo
 | 
				
			||||||
 | 
					 * currently it handles only the case of PM=yarn && cacheDependencyPath is not empty
 | 
				
			||||||
 | 
					 * @param packageManagerInfo - an object having getCacheFolderPath method specific to given PM
 | 
				
			||||||
 | 
					 * @param cacheDependencyPath - either a single string or multiline string with possible glob patterns
 | 
				
			||||||
 | 
					 *                              expected to be the result of `core.getInput('cache-dependency-path')`
 | 
				
			||||||
 | 
					 * @return list of files on which the cache depends
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const getCacheDirectories = async (
 | 
				
			||||||
 | 
					  packageManagerInfo: PackageManagerInfo,
 | 
				
			||||||
 | 
					  cacheDependencyPath: string
 | 
				
			||||||
 | 
					): Promise<string[]> => {
 | 
				
			||||||
 | 
					  // For yarn, if cacheDependencyPath is set, ask information about cache folders in each project
 | 
				
			||||||
 | 
					  // folder satisfied by cacheDependencyPath https://github.com/actions/setup-node/issues/488
 | 
				
			||||||
 | 
					  if (packageManagerInfo.name === 'yarn' && cacheDependencyPath) {
 | 
				
			||||||
 | 
					    return getCacheDirectoriesFromCacheDependencyPath(
 | 
				
			||||||
 | 
					      packageManagerInfo,
 | 
				
			||||||
 | 
					      cacheDependencyPath
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return getCacheDirectoriesForRootProject(packageManagerInfo);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A function to check if the directory is a yarn project configured to manage
 | 
				
			||||||
 | 
					 * obsolete dependencies in the local cache
 | 
				
			||||||
 | 
					 * @param directory - a path to the folder
 | 
				
			||||||
 | 
					 * @return - true if the directory's project is yarn managed
 | 
				
			||||||
 | 
					 *  - if there's .yarn/cache folder do not mess with the dependencies kept in the repo, return false
 | 
				
			||||||
 | 
					 *  - global cache is not managed by yarn @see https://yarnpkg.com/features/offline-cache, return false
 | 
				
			||||||
 | 
					 *  - if local cache is not explicitly enabled (not yarn3), return false
 | 
				
			||||||
 | 
					 *  - return true otherwise
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const projectHasYarnBerryManagedDependencies = async (
 | 
				
			||||||
 | 
					  directory: string
 | 
				
			||||||
 | 
					): Promise<boolean> => {
 | 
				
			||||||
 | 
					  const workDir = directory || process.env.GITHUB_WORKSPACE || '.';
 | 
				
			||||||
 | 
					  core.debug(`check if "${workDir}" has locally managed yarn3 dependencies`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // if .yarn/cache directory exists the cache is managed by version control system
 | 
				
			||||||
 | 
					  const yarnCacheFile = path.join(workDir, '.yarn', 'cache');
 | 
				
			||||||
 | 
					  if (
 | 
				
			||||||
 | 
					    fs.existsSync(yarnCacheFile) &&
 | 
				
			||||||
 | 
					    fs.lstatSync(yarnCacheFile).isDirectory()
 | 
				
			||||||
 | 
					  ) {
 | 
				
			||||||
 | 
					    core.debug(
 | 
				
			||||||
 | 
					      `"${workDir}" has .yarn/cache - dependencies are kept in the repository`
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    return Promise.resolve(false);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // NOTE: yarn1 returns 'undefined' with return code = 0
 | 
				
			||||||
 | 
					  const enableGlobalCache = await getCommandOutput(
 | 
				
			||||||
 | 
					    'yarn config get enableGlobalCache',
 | 
				
			||||||
 | 
					    workDir
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  // only local cache is not managed by yarn
 | 
				
			||||||
 | 
					  const managed = enableGlobalCache.includes('false');
 | 
				
			||||||
 | 
					  if (managed) {
 | 
				
			||||||
 | 
					    core.debug(`"${workDir}" dependencies are managed by yarn 3 locally`);
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    core.debug(`"${workDir}" dependencies are not managed by yarn 3 locally`);
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A function to report the repo contains Yarn managed projects
 | 
				
			||||||
 | 
					 * @param packageManagerInfo - used to make sure current package manager is yarn
 | 
				
			||||||
 | 
					 * @param cacheDependencyPath - either a single string or multiline string with possible glob patterns
 | 
				
			||||||
 | 
					 *                              expected to be the result of `core.getInput('cache-dependency-path')`
 | 
				
			||||||
 | 
					 * @return - true if all project directories configured to be Yarn managed
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const repoHasYarnBerryManagedDependencies = async (
 | 
				
			||||||
 | 
					  packageManagerInfo: PackageManagerInfo,
 | 
				
			||||||
 | 
					  cacheDependencyPath: string
 | 
				
			||||||
 | 
					): Promise<boolean> => {
 | 
				
			||||||
 | 
					  if (packageManagerInfo.name !== 'yarn') return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const yarnDirs = cacheDependencyPath
 | 
				
			||||||
 | 
					    ? await getProjectDirectoriesFromCacheDependencyPath(cacheDependencyPath)
 | 
				
			||||||
 | 
					    : [''];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const isManagedList = await Promise.all(
 | 
				
			||||||
 | 
					    yarnDirs.map(projectHasYarnBerryManagedDependencies)
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return isManagedList.every(Boolean);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function isGhes(): boolean {
 | 
					export function isGhes(): boolean {
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,8 @@ export enum LockType {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export enum State {
 | 
					export enum State {
 | 
				
			||||||
  CachePrimaryKey = 'CACHE_KEY',
 | 
					  CachePrimaryKey = 'CACHE_KEY',
 | 
				
			||||||
  CacheMatchedKey = 'CACHE_RESULT'
 | 
					  CacheMatchedKey = 'CACHE_RESULT',
 | 
				
			||||||
 | 
					  CachePaths = 'CACHE_PATHS'
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export enum Outputs {
 | 
					export enum Outputs {
 | 
				
			||||||
 | 
				
			|||||||
@ -61,3 +61,12 @@ async function getToolVersion(tool: string, options: string[]) {
 | 
				
			|||||||
    return '';
 | 
					    return '';
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const unique = () => {
 | 
				
			||||||
 | 
					  const encountered = new Set();
 | 
				
			||||||
 | 
					  return (value: unknown): boolean => {
 | 
				
			||||||
 | 
					    if (encountered.has(value)) return false;
 | 
				
			||||||
 | 
					    encountered.add(value);
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user