Merge remote-tracking branch 'upstream/main' into suggest-clear-cache-after-dependency-update
This commit is contained in:
commit
fa0272551b
|
@ -111,3 +111,99 @@ jobs:
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
ls ~/.m2/repository
|
ls ~/.m2/repository
|
||||||
|
sbt-save:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
working-directory: __tests__/cache/sbt
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Run setup-java with the cache for sbt
|
||||||
|
uses: ./
|
||||||
|
id: setup-java
|
||||||
|
with:
|
||||||
|
distribution: 'adopt'
|
||||||
|
java-version: '11'
|
||||||
|
cache: sbt
|
||||||
|
- name: Create files to cache
|
||||||
|
run: sbt update
|
||||||
|
|
||||||
|
- name: Check files to cache on macos-latest
|
||||||
|
if: matrix.os == 'macos-latest'
|
||||||
|
run: |
|
||||||
|
if [ ! -d ~/Library/Caches/Coursier ]; then
|
||||||
|
echo "::error::The ~/Library/Caches/Coursier directory does not exist unexpectedly"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Check files to cache on windows-latest
|
||||||
|
if: matrix.os == 'windows-latest'
|
||||||
|
run: |
|
||||||
|
if [ ! -d ~/AppData/Local/Coursier/Cache ]; then
|
||||||
|
echo "::error::The ~/AppData/Local/Coursier/Cache directory does not exist unexpectedly"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
- name: Check files to cache on ubuntu-latest
|
||||||
|
if: matrix.os == 'ubuntu-latest'
|
||||||
|
run: |
|
||||||
|
if [ ! -d ~/.cache/coursier ]; then
|
||||||
|
echo "::error::The ~/.cache/coursier directory does not exist unexpectedly"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sbt-restore:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
working-directory: __tests__/cache/sbt
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||||
|
needs: sbt-save
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Run setup-java with the cache for sbt
|
||||||
|
uses: ./
|
||||||
|
id: setup-java
|
||||||
|
with:
|
||||||
|
distribution: 'adopt'
|
||||||
|
java-version: '11'
|
||||||
|
cache: sbt
|
||||||
|
|
||||||
|
- name: Confirm that ~/Library/Caches/Coursier directory has been made
|
||||||
|
if: matrix.os == 'macos-latest'
|
||||||
|
run: |
|
||||||
|
if [ ! -d ~/Library/Caches/Coursier ]; then
|
||||||
|
echo "::error::The ~/Library/Caches/Coursier directory does not exist unexpectedly"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
ls ~/Library/Caches/Coursier
|
||||||
|
|
||||||
|
- name: Confirm that ~/AppData/Local/Coursier/Cache directory has been made
|
||||||
|
if: matrix.os == 'windows-latest'
|
||||||
|
run: |
|
||||||
|
if [ ! -d ~/AppData/Local/Coursier/Cache ]; then
|
||||||
|
echo "::error::The ~/AppData/Local/Coursier/Cache directory does not exist unexpectedly"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
ls ~/AppData/Local/Coursier/Cache
|
||||||
|
|
||||||
|
- name: Confirm that ~/.cache/coursier directory has been made
|
||||||
|
if: matrix.os == 'ubuntu-latest'
|
||||||
|
run: |
|
||||||
|
if [ ! -d ~/.cache/coursier ]; then
|
||||||
|
echo "::error::The ~/.cache/coursier directory does not exist unexpectedly"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
ls ~/.cache/coursier
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
In the interest of fostering an open and welcoming environment, we as
|
||||||
|
contributors and maintainers pledge to make participation in our project and
|
||||||
|
our community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||||
|
level of experience, education, socio-economic status, nationality, personal
|
||||||
|
appearance, race, religion, or sexual identity and orientation.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment
|
||||||
|
include:
|
||||||
|
|
||||||
|
* Using welcoming and inclusive language
|
||||||
|
* Being respectful of differing viewpoints and experiences
|
||||||
|
* Gracefully accepting constructive criticism
|
||||||
|
* Focusing on what is best for the community
|
||||||
|
* Showing empathy towards other community members
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||||
|
advances
|
||||||
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or electronic
|
||||||
|
address, without explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Our Responsibilities
|
||||||
|
|
||||||
|
Project maintainers are responsible for clarifying the standards of acceptable
|
||||||
|
behavior and are expected to take appropriate and fair corrective action in
|
||||||
|
response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or
|
||||||
|
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||||
|
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||||
|
permanently any contributor for other behaviors that they deem inappropriate,
|
||||||
|
threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all project spaces, and it also applies when
|
||||||
|
an individual is representing the project or its community in public spaces.
|
||||||
|
Examples of representing a project or community include using an official
|
||||||
|
project e-mail address, posting via an official social media account, or acting
|
||||||
|
as an appointed representative at an online or offline event. Representation of
|
||||||
|
a project may be further defined and clarified by project maintainers.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported by contacting the project team at opensource+actions/setup-java@github.com. All
|
||||||
|
complaints will be reviewed and investigated and will result in a response that
|
||||||
|
is deemed necessary and appropriate to the circumstances. The project team is
|
||||||
|
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||||
|
Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
|
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||||
|
faith may face temporary or permanent repercussions as determined by other
|
||||||
|
members of the project's leadership.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||||
|
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see
|
||||||
|
https://www.contributor-covenant.org/faq
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
### NCC
|
### NCC
|
||||||
|
|
||||||
In order to avoid uploading `node_modules` to the repository, we use [zeit/ncc](https://github.com/zeit/ncc) to create multiple `index.js` files that gets saved under `dist/`.
|
In order to avoid uploading `node_modules` to the repository, we use [vercel/ncc](https://github.com/vercel/ncc) to create multiple `index.js` files that gets saved under `dist/`.
|
||||||
There are two main files that get created
|
There are two main files that get created
|
||||||
- `dist/setup/index.js`
|
- `dist/setup/index.js`
|
||||||
- Core `setup-java` logic that downloads and installs an appropriate version of Java
|
- Core `setup-java` logic that downloads and installs an appropriate version of Java
|
||||||
|
|
16
README.md
16
README.md
|
@ -66,9 +66,10 @@ Currently, the following distributions are supported:
|
||||||
**NOTE:** Adopt OpenJDK got moved to Eclipse Temurin and won't be updated anymore. It is highly recommended to migrate workflows from `adopt` to `temurin` to keep receiving software and security updates. See more details in the [Good-bye AdoptOpenJDK post](https://blog.adoptopenjdk.net/2021/08/goodbye-adoptopenjdk-hello-adoptium/).
|
**NOTE:** Adopt OpenJDK got moved to Eclipse Temurin and won't be updated anymore. It is highly recommended to migrate workflows from `adopt` to `temurin` to keep receiving software and security updates. See more details in the [Good-bye AdoptOpenJDK post](https://blog.adoptopenjdk.net/2021/08/goodbye-adoptopenjdk-hello-adoptium/).
|
||||||
|
|
||||||
### Caching packages dependencies
|
### Caching packages dependencies
|
||||||
The action has a built-in functionality for caching and restoring dependencies. It uses [actions/cache](https://github.com/actions/cache) under hood for caching dependencies but requires less configuration settings. Supported package managers are gradle and maven. The format of the used cache key is `setup-java-${{ platform }}-${{ packageManager }}-${{ fileHash }}`, where the hash is based on the following files:
|
The action has a built-in functionality for caching and restoring dependencies. It uses [actions/cache](https://github.com/actions/cache) under hood for caching dependencies but requires less configuration settings. Supported package managers are gradle, maven and sbt. The format of the used cache key is `setup-java-${{ platform }}-${{ packageManager }}-${{ fileHash }}`, where the hash is based on the following files:
|
||||||
- gradle: `**/*.gradle*`, `**/gradle-wrapper.properties`
|
- gradle: `**/*.gradle*`, `**/gradle-wrapper.properties`
|
||||||
- maven: `**/pom.xml`
|
- maven: `**/pom.xml`
|
||||||
|
- sbt: `**/build.sbt`
|
||||||
|
|
||||||
The workflow output `cache-hit` is set to indicate if an exact match was found for the key [as actions/cache does](https://github.com/actions/cache/tree/main#outputs).
|
The workflow output `cache-hit` is set to indicate if an exact match was found for the key [as actions/cache does](https://github.com/actions/cache/tree/main#outputs).
|
||||||
|
|
||||||
|
@ -99,6 +100,19 @@ steps:
|
||||||
run: mvn -B package --file pom.xml
|
run: mvn -B package --file pom.xml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Caching sbt dependencies
|
||||||
|
```yaml
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: '11'
|
||||||
|
cache: 'sbt'
|
||||||
|
- name: Build with SBT
|
||||||
|
run: sbt package
|
||||||
|
```
|
||||||
|
|
||||||
### Check latest
|
### Check latest
|
||||||
In the basic examples above, the `check-latest` flag defaults to `false`. When set to `false`, the action tries to first resolve a version of Java from the local tool cache on the runner. If unable to find a specific version in the cache, the action will download a version of Java. Use the default or set `check-latest` to `false` if you prefer a faster more consistent setup experience that prioritizes trying to use the cached versions at the expense of newer versions sometimes being available for download.
|
In the basic examples above, the `check-latest` flag defaults to `false`. When set to `false`, the action tries to first resolve a version of Java from the local tool cache on the runner. If unable to find a specific version in the cache, the action will download a version of Java. Use the default or set `check-latest` to `false` if you prefer a faster more consistent setup experience that prioritizes trying to use the cached versions at the expense of newer versions sometimes being available for download.
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,23 @@ describe('dependency cache', () => {
|
||||||
expect(spyInfo).toBeCalledWith('gradle cache is not found');
|
expect(spyInfo).toBeCalledWith('gradle cache is not found');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('for sbt', () => {
|
||||||
|
it('throws error if no build.sbt found', async () => {
|
||||||
|
await expect(restore('sbt')).rejects.toThrowError(
|
||||||
|
`No file in ${projectRoot(
|
||||||
|
workspace
|
||||||
|
)} matched to [**/*.sbt,**/project/build.properties,**/project/**.{scala,sbt}], make sure you have checked out the target repository`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('downloads cache', async () => {
|
||||||
|
createFile(join(workspace, 'build.sbt'));
|
||||||
|
|
||||||
|
await restore('sbt');
|
||||||
|
expect(spyCacheRestore).toBeCalled();
|
||||||
|
expect(spyWarning).not.toBeCalled();
|
||||||
|
expect(spyInfo).toBeCalledWith('sbt cache is not found');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe('save', () => {
|
describe('save', () => {
|
||||||
let spyCacheSave: jest.SpyInstance<
|
let spyCacheSave: jest.SpyInstance<
|
||||||
|
@ -194,6 +211,30 @@ describe('dependency cache', () => {
|
||||||
expect(spyInfo).toBeCalledWith(expect.stringMatching(/^Cache saved with the key:.*/));
|
expect(spyInfo).toBeCalledWith(expect.stringMatching(/^Cache saved with the key:.*/));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('for sbt', () => {
|
||||||
|
it('uploads cache even if no build.sbt found', async () => {
|
||||||
|
createStateForMissingBuildFile();
|
||||||
|
await save('sbt');
|
||||||
|
expect(spyCacheSave).toBeCalled();
|
||||||
|
expect(spyWarning).not.toBeCalled();
|
||||||
|
});
|
||||||
|
it('does not upload cache if no restore run before', async () => {
|
||||||
|
createFile(join(workspace, 'build.sbt'));
|
||||||
|
|
||||||
|
await save('sbt');
|
||||||
|
expect(spyCacheSave).not.toBeCalled();
|
||||||
|
expect(spyWarning).toBeCalledWith('Error retrieving key from state.');
|
||||||
|
});
|
||||||
|
it('uploads cache', async () => {
|
||||||
|
createFile(join(workspace, 'build.sbt'));
|
||||||
|
createStateForSuccessfulRestore();
|
||||||
|
|
||||||
|
await save('sbt');
|
||||||
|
expect(spyCacheSave).toBeCalled();
|
||||||
|
expect(spyWarning).not.toBeCalled();
|
||||||
|
expect(spyInfo).toBeCalledWith(expect.stringMatching(/^Cache saved with the key:.*/));
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
target/
|
|
@ -0,0 +1,3 @@
|
||||||
|
ThisBuild / scalaVersion := "2.12.15"
|
||||||
|
|
||||||
|
libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2"
|
|
@ -0,0 +1 @@
|
||||||
|
sbt.version=1.6.2
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -23,7 +23,7 @@
|
||||||
"@types/jest": "^27.0.2",
|
"@types/jest": "^27.0.2",
|
||||||
"@types/node": "^16.11.25",
|
"@types/node": "^16.11.25",
|
||||||
"@types/semver": "^7.3.4",
|
"@types/semver": "^7.3.4",
|
||||||
"@zeit/ncc": "^0.20.5",
|
"@vercel/ncc": "^0.33.4",
|
||||||
"jest": "^27.2.5",
|
"jest": "^27.2.5",
|
||||||
"jest-circus": "^27.2.5",
|
"jest-circus": "^27.2.5",
|
||||||
"prettier": "^1.19.1",
|
"prettier": "^1.19.1",
|
||||||
|
@ -1893,11 +1893,10 @@
|
||||||
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==",
|
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@zeit/ncc": {
|
"node_modules/@vercel/ncc": {
|
||||||
"version": "0.20.5",
|
"version": "0.33.4",
|
||||||
"resolved": "https://registry.npmjs.org/@zeit/ncc/-/ncc-0.20.5.tgz",
|
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.33.4.tgz",
|
||||||
"integrity": "sha512-XU6uzwvv95DqxciQx+aOLhbyBx/13ky+RK1y88Age9Du3BlA4mMPCy13BGjayOrrumOzlq1XV3SD/BWiZENXlw==",
|
"integrity": "sha512-ln18hs7dMffelP47tpkaR+V5Tj6coykNyxJrlcmCormPqRQjB/Gv4cu2FfBG+PMzIfdZp2CLDsrrB1NPU22Qhg==",
|
||||||
"deprecated": "@zeit/ncc is no longer maintained. Please use @vercel/ncc instead.",
|
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"ncc": "dist/ncc/cli.js"
|
"ncc": "dist/ncc/cli.js"
|
||||||
|
@ -8210,10 +8209,10 @@
|
||||||
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==",
|
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@zeit/ncc": {
|
"@vercel/ncc": {
|
||||||
"version": "0.20.5",
|
"version": "0.33.4",
|
||||||
"resolved": "https://registry.npmjs.org/@zeit/ncc/-/ncc-0.20.5.tgz",
|
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.33.4.tgz",
|
||||||
"integrity": "sha512-XU6uzwvv95DqxciQx+aOLhbyBx/13ky+RK1y88Age9Du3BlA4mMPCy13BGjayOrrumOzlq1XV3SD/BWiZENXlw==",
|
"integrity": "sha512-ln18hs7dMffelP47tpkaR+V5Tj6coykNyxJrlcmCormPqRQjB/Gv4cu2FfBG+PMzIfdZp2CLDsrrB1NPU22Qhg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"abab": {
|
"abab": {
|
||||||
|
|
|
@ -38,9 +38,9 @@
|
||||||
"@types/jest": "^27.0.2",
|
"@types/jest": "^27.0.2",
|
||||||
"@types/node": "^16.11.25",
|
"@types/node": "^16.11.25",
|
||||||
"@types/semver": "^7.3.4",
|
"@types/semver": "^7.3.4",
|
||||||
"@zeit/ncc": "^0.20.5",
|
|
||||||
"jest": "^27.2.5",
|
"jest": "^27.2.5",
|
||||||
"jest-circus": "^27.2.5",
|
"jest-circus": "^27.2.5",
|
||||||
|
"@vercel/ncc": "^0.33.4",
|
||||||
"prettier": "^1.19.1",
|
"prettier": "^1.19.1",
|
||||||
"ts-jest": "^27.0.5",
|
"ts-jest": "^27.0.5",
|
||||||
"typescript": "^4.2.3"
|
"typescript": "^4.2.3"
|
||||||
|
|
17
src/cache.ts
17
src/cache.ts
|
@ -13,7 +13,7 @@ const CACHE_MATCHED_KEY = 'cache-matched-key';
|
||||||
const CACHE_KEY_PREFIX = 'setup-java';
|
const CACHE_KEY_PREFIX = 'setup-java';
|
||||||
|
|
||||||
interface PackageManager {
|
interface PackageManager {
|
||||||
id: 'maven' | 'gradle';
|
id: 'maven' | 'gradle' | 'sbt';
|
||||||
/**
|
/**
|
||||||
* Paths of the file that specify the files to cache.
|
* Paths of the file that specify the files to cache.
|
||||||
*/
|
*/
|
||||||
|
@ -32,9 +32,24 @@ const supportedPackageManager: PackageManager[] = [
|
||||||
path: [join(os.homedir(), '.gradle', 'caches'), join(os.homedir(), '.gradle', 'wrapper')],
|
path: [join(os.homedir(), '.gradle', 'caches'), join(os.homedir(), '.gradle', 'wrapper')],
|
||||||
// https://github.com/actions/cache/blob/0638051e9af2c23d10bb70fa9beffcad6cff9ce3/examples.md#java---gradle
|
// https://github.com/actions/cache/blob/0638051e9af2c23d10bb70fa9beffcad6cff9ce3/examples.md#java---gradle
|
||||||
pattern: ['**/*.gradle*', '**/gradle-wrapper.properties']
|
pattern: ['**/*.gradle*', '**/gradle-wrapper.properties']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'sbt',
|
||||||
|
path: [
|
||||||
|
join(os.homedir(), '.ivy2', 'cache'),
|
||||||
|
join(os.homedir(), '.sbt'),
|
||||||
|
getCoursierCachePath()
|
||||||
|
],
|
||||||
|
pattern: ['**/*.sbt', '**/project/build.properties', '**/project/**.{scala,sbt}']
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
function getCoursierCachePath(): string {
|
||||||
|
if (os.type() === 'Linux') return join(os.homedir(), '.cache', 'coursier');
|
||||||
|
if (os.type() === 'Darwin') return join(os.homedir(), 'Library', 'Caches', 'Coursier');
|
||||||
|
return join(os.homedir(), 'AppData', 'Local', 'Coursier', 'Cache');
|
||||||
|
}
|
||||||
|
|
||||||
function findPackageManager(id: string): PackageManager {
|
function findPackageManager(id: string): PackageManager {
|
||||||
const packageManager = supportedPackageManager.find(packageManager => packageManager.id === id);
|
const packageManager = supportedPackageManager.find(packageManager => packageManager.id === id);
|
||||||
if (packageManager === undefined) {
|
if (packageManager === undefined) {
|
||||||
|
|
Loading…
Reference in New Issue