diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index c0b87e4faac295..b1930fcb1fa3c9 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -37,7 +37,7 @@ Copy/paste any log here, between the starting and ending backticks **Have you created a minimal reproduction repository?** -Please read the [minimal reproductions documentation](https://github.com/renovatebot/renovate/blob/master/docs/development/minimal-reproductions.md) to learn how to make a good minimal reproduction repository. +Please read the [minimal reproductions documentation](https://github.com/renovatebot/renovate/blob/main/docs/development/minimal-reproductions.md) to learn how to make a good minimal reproduction repository. - [ ] I have provided a minimal reproduction repository - [ ] I don't have time for that, but it happens in a public repository I have linked to diff --git a/.github/auto-cancel-actions.yml b/.github/auto-cancel-actions.yml index 901ddfc5ee6c61..cfdd9c1527ce0b 100644 --- a/.github/auto-cancel-actions.yml +++ b/.github/auto-cancel-actions.yml @@ -1,5 +1,5 @@ version: 1 push: branches: - - '!master' + - '!main' pull_request: diff --git a/.github/contributing.md b/.github/contributing.md index ad9f3418782832..2a3f581c9bd126 100644 --- a/.github/contributing.md +++ b/.github/contributing.md @@ -16,7 +16,7 @@ If you've found a **bug** or have a **feature request** then please create an is ## Code If you would like to fix a bug or implement a feature, please fork the repository and create a Pull Request. -More information on getting set up locally can be found in [docs/development/local-development.md](https://github.com/renovatebot/renovate/blob/master/docs/development/local-development.md). +More information on getting set up locally can be found in [docs/development/local-development.md](https://github.com/renovatebot/renovate/blob/main/docs/development/local-development.md). Before you start any Pull Request, it's recommended that you create an issue to discuss first if you have any doubts about requirement or implementation. That way you can be sure that the maintainer(s) agree on what to change and how, and you can hopefully get a quick merge afterwards. diff --git a/.github/label-actions.yml b/.github/label-actions.yml index c1fc61728c79d0..0a9f4560ed87e7 100644 --- a/.github/label-actions.yml +++ b/.github/label-actions.yml @@ -8,7 +8,7 @@ A minimal reproduction helps us with this. - To get started, please read our guide on [minimal reproductions](https://github.com/renovatebot/renovate/blob/master/docs/development/minimal-reproductions.md) to understand what is needed. + To get started, please read our guide on [minimal reproductions](https://github.com/renovatebot/renovate/blob/main/docs/development/minimal-reproductions.md) to understand what is needed. We may close the issue if you have not provided a minimal reproduction within two weeks. diff --git a/.github/prettifier.yml b/.github/prettifier.yml index b947472423e4c3..f05a3bc764aae2 100644 --- a/.github/prettifier.yml +++ b/.github/prettifier.yml @@ -1,4 +1,4 @@ commitMessage: 'Apply prettier formatting fix' excludeBranches: - - master + - main pullsOnly: true diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 119d5e8a2dc122..04df248f5066c7 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -24,7 +24,7 @@ I have verified these changes via: - [ ] No new tests but ran on a real repository, or - [ ] Both unit tests + ran on a real repository - + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c7825e1b9754d5..841316ae3ffce8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,15 +3,23 @@ name: build on: push: branches: - - master + - main + - v24 workflow_dispatch: + inputs: + dryRun: + description: 'Dry-Run' + default: 'true' env: + # Currently no way to detect automatically (#8153) + DEFAULT_BRANCH: main YARN_MODULES_CACHE_KEY: v1 YARN_PACKAGE_CACHE_KEY: v1 YARN_CACHE_FOLDER: .cache/yarn NODE_VERSION: 14 + DRY_RUN: true jobs: test: @@ -97,7 +105,8 @@ jobs: uses: codecov/codecov-action@v1.4.1 if: always() && env.coverage == 'true' - # build after tests to exclude files + # build after tests to exclude build files from tests + # TODO: check if build before test speeds up tests - name: Build run: yarn build @@ -178,6 +187,16 @@ jobs: yarn config set version-git-tag false npm config set scripts-prepend-node-path true + - name: Check dry run + run: | + if [[ "${{github.event_name}}" == "workflow_dispatch" && "${{ github.event.inputs.dryRun }}" != "true" ]]; then + echo "DRY_RUN=false" >> $GITHUB_ENV + elif [[ "${{github.ref}}" == "refs/heads/${{env.DEFAULT_BRANCH}}" ]]; then + echo "DRY_RUN=false" >> $GITHUB_ENV + elif [[ "${{github.ref}}" =~ ^refs/heads/v[0-9]+(\.[0-9]+)?$ ]]; then + echo "DRY_RUN=false" >> $GITHUB_ENV + fi + # full checkout for semantic-release - uses: actions/checkout@v2.3.4 with: @@ -193,10 +212,9 @@ jobs: run: yarn install --frozen-lockfile - name: semantic-release - if: github.ref == 'refs/heads/master' run: | echo '//registry.npmjs.org/:_authToken=${NPM_TOKEN}' >> ~/.npmrc - npx semantic-release --dry-run ${{github.ref != 'refs/heads/master'}} --ci ${{github.ref == 'refs/heads/master'}} + npx semantic-release --dry-run ${{env.DRY_RUN}} env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e2fed2d20a604b..03e6566f709937 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -2,10 +2,10 @@ name: 'Code scanning - action' on: push: - branches: [master] + branches: [main] pull_request: # The branches below must be a subset of the branches above - branches: [master] + branches: [main] schedule: - cron: '0 13 * * 1' diff --git a/.github/workflows/release-npm.yml b/.github/workflows/release-npm.yml index fac7bcb140545e..c718fb45dc9d5b 100644 --- a/.github/workflows/release-npm.yml +++ b/.github/workflows/release-npm.yml @@ -1,13 +1,29 @@ name: release-npm + on: repository_dispatch: types: [renovate-release] + workflow_dispatch: + inputs: + sha: + description: 'Git sha to checkout' + required: true + version: + description: 'Version to release' + required: true + tag: + description: 'Npm dist-tag' + default: 'latest' + env: YARN_MODULES_CACHE_KEY: v1 YARN_PACKAGE_CACHE_KEY: v1 YARN_CACHE_FOLDER: .cache/yarn NODE_VERSION: 14 + GIT_SHA: ${{ github.event.client_payload.sha }} + NPM_VERSION: ${{ github.event.client_payload.version }} + NPM_TAG: ${{ github.event.client_payload.tag }} jobs: release-npm: @@ -27,9 +43,17 @@ jobs: yarn config set version-git-tag false npm config set scripts-prepend-node-path true + - name: Prepare env + run: | + if [[ "${{github.event_name}}" == "workflow_dispatch" ]]; then + echo "GIT_SHA=${{ github.event.inputs.sha }}" >> $GITHUB_ENV + echo "NPM_VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV + echo "NPM_TAG=${{ github.event.inputs.tag }}" >> $GITHUB_ENV + fi + - uses: actions/checkout@v2.3.4 with: - ref: ${{ github.event.client_payload.sha }} + ref: ${{ env.GIT_SHA }} - name: Cache Yarn packages id: yarn_cache_packages @@ -41,16 +65,16 @@ jobs: - name: Installing dependencies run: yarn install --frozen-lockfile - - name: Build ${{ github.event.client_payload.version }} + - name: Build ${{ env.NPM_VERSION }} run: yarn build - - name: Prepare ${{ github.event.client_payload.version }} + - name: Prepare ${{ env.NPM_VERSION }} run: | - npm --no-git-tag-version version ${{ github.event.client_payload.version }} + npm --no-git-tag-version version ${{ env.NPM_VERSION }} - - name: Publish ${{ github.event.client_payload.version }} + - name: Publish ${{ env.NPM_VERSION }} run: | echo '//registry.npmjs.org/:_authToken=${NPM_TOKEN}' >> ~/.npmrc - npm publish + npm publish --tag ${NPM_TAG:-latest} env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/ws_scan.yaml b/.github/workflows/ws_scan.yaml index d264533f6132b5..b4b6003775ead5 100644 --- a/.github/workflows/ws_scan.yaml +++ b/.github/workflows/ws_scan.yaml @@ -2,7 +2,7 @@ name: whitesource-scan on: push: - branches: [master] + branches: [main] jobs: WS_SCAN: @@ -14,4 +14,4 @@ jobs: run: curl -LJO https://github.com/whitesource/unified-agent-distribution/releases/latest/download/wss-unified-agent.jar - name: Run UA scan - run: java -jar wss-unified-agent.jar -d $GITHUB_WORKSPACE -noConfig true -apiKey ${{ secrets.WS_ORG_TOKEN }} -product W4D -project "Renovate OS - master" -resolveAllDependencies false -npm_resolveDependencies true + run: java -jar wss-unified-agent.jar -d $GITHUB_WORKSPACE -noConfig true -apiKey ${{ secrets.WS_ORG_TOKEN }} -product W4D -project "Renovate OS - main" -resolveAllDependencies false -npm_resolveDependencies true diff --git a/.releaserc b/.releaserc index 625c7479a8e760..9b2d1fa5f896d6 100644 --- a/.releaserc +++ b/.releaserc @@ -12,7 +12,7 @@ "@semantic-release/exec", { "verifyConditionsCmd": "run-s verify", - "publishCmd": "run-s \"release -- {@}\" -- --release=${nextRelease.version} --sha=${nextRelease.gitHead}" + "publishCmd": "run-s \"release -- {@}\" -- --release=${nextRelease.version} --sha=${nextRelease.gitHead} --tag=${nextRelease.channel}" } ] ], @@ -82,5 +82,15 @@ } ] }, - "tagFormat": "${version}" + "tagFormat": "${version}", + "branches": [ + { + "name": "v24", + "range": "24.x", + "channel": "v24" + }, + { + "name": "main" + } + ] } diff --git a/docs/development/design-decisions.md b/docs/development/design-decisions.md index 51526ce7d3c3d8..240640799f4f96 100644 --- a/docs/development/design-decisions.md +++ b/docs/development/design-decisions.md @@ -80,7 +80,7 @@ This allows users to close unwelcome upgrade PRs and not worry about them being With the default behavior of one branch per dependency, it's often the case that a PR gets merge conflicts after an adjacent dependency update is merged. Although platforms often have a web interface for simple merge conflicts, this is still annoying to resolve manually. -`renovate` will rebase any unmergeable branches and add the latest necessary commit on top of the most recent `master` commit. +`renovate` will rebase any unmergeable branches and add the latest necessary commit on top of the most recent `main` commit. Note: `renovate` will only do this if the original branch hasn't been modified by anyone else. diff --git a/docs/development/local-development.md b/docs/development/local-development.md index 06de394c7a06bf..75c10b72ea6b2b 100644 --- a/docs/development/local-development.md +++ b/docs/development/local-development.md @@ -75,7 +75,6 @@ The Renovate project uses the [Yarn](https://github.com/yarnpkg/yarn) package ma To ensure everything is working properly on your end, you must: -1. Make sure you don't have a local `.npmrc` file that overrides npm's default registry 1. Install all dependencies with `yarn install` 1. Make a build with `yarn build`, which should pass with no errors 1. Verify all tests pass and have 100% test coverage, by running `yarn test` @@ -150,9 +149,9 @@ You usually don't need to fix any Prettier errors by hand. ## Keeping your Renovate fork up to date -First of all, never commit to the `master` branch of your fork - always use a "feature" branch like `feat/1234-add-yarn-parsing`. +First of all, never commit to the `main` branch of your fork - always use a "feature" branch like `feat/1234-add-yarn-parsing`. -Make sure your fork is up to date with the Renovate `master` branch, check this each time before you create a new branch. +Make sure your fork is up to date with the Renovate `main` branch, check this each time before you create a new branch. To do this, see these GitHub guides: [Configuring a remote for a fork](https://help.github.com/articles/configuring-a-remote-for-a-fork/) diff --git a/docs/development/triage-guide.md b/docs/development/triage-guide.md index 10f42c79bdc8b0..796863a58c4dcb 100644 --- a/docs/development/triage-guide.md +++ b/docs/development/triage-guide.md @@ -26,7 +26,7 @@ Don't be afraid to ask for help. ### Apply labels to issues All issues should have labels attached to them. -Read the [issue-labeling guide](https://github.com/renovatebot/renovate/blob/master/docs/development/issue-labeling.md) to get all the necessary info. +Read the [issue-labeling guide](https://github.com/renovatebot/renovate/blob/main/docs/development/issue-labeling.md) to get all the necessary info. In general try to make a good-faith effort to label things correctly. diff --git a/docs/usage/config-presets.md b/docs/usage/config-presets.md index 33e3ec8ad446b8..29a7962d5ef162 100644 --- a/docs/usage/config-presets.md +++ b/docs/usage/config-presets.md @@ -119,45 +119,6 @@ Parameters must be strings, non-quoted, and separated by commas if there are mor If you find that you are repeating config a lot, you might consider publishing one of these types of parameterised presets yourself. Or if you think your preset would be valuable for others, please contribute a PR to the Renovate repository. -## How to Publish Preset Configs - -If you manage multiple repositories using Renovate and want the same custom config across all or most of them, then you might want to consider publishing your own preset config so that you can "extend" it in every applicable repository. -That way when you want to change your Renovate configuration you can make the change in one location rather than having to copy/paste it to every repository individually. - -Let's say that your username on npm and elsewhere is "fastcore". -In that case, you can choose between publishing your preset config package as `@fastcore/renovate-config` or `renovate-config-fastcore`. -Let's assume you choose `renovate-config-fastcore` as the package name: - -You then need to publish the `renovate-config-fastcore` package where the `package.json` contains the field `renovate-config` and then put your config under the field `default`. -For example: - -```json -{ - "name": "renovate-config-fastcore", - "version": "0.0.1", - ... - "renovate-config": { - "default": { - "extends": ["config:base", "schedule:nonOfficeHours"] - } - } -} -``` - -Then in each of your repositories you can add your Renovate config like: - -```json - "extends": ["fastcore"] -``` - -Any repository including this config will then adopt the rules of the default `library` preset but schedule it on weeknights or weekends. - -Note: if you prefer to publish using the namespace `@fastcore/renovate-config` then you would use the `@` prefix instead: - -```json - "extends": ["@fastcore"] -``` - ## GitHub-hosted Presets It is also possible to host your preset config using just a regular GitHub repository and without needing to publish it to npmjs. @@ -236,3 +197,44 @@ For example the result may be: "extends": ["local>myorgname/.github:renovate-config"] } ``` + +## npm-hosted presets + +Using npm-hosted presets is deprecated, we recommend you do not follow these instructions and instead use a `local` preset. + +If you manage multiple repositories using Renovate and want the same custom config across all or most of them, then you might want to consider publishing your own preset config so that you can "extend" it in every applicable repository. +That way when you want to change your Renovate configuration you can make the change in one location rather than having to copy/paste it to every repository individually. + +Let's say that your username on npm and elsewhere is "fastcore". +In that case, you can choose between publishing your preset config package as `@fastcore/renovate-config` or `renovate-config-fastcore`. +Let's assume you choose `renovate-config-fastcore` as the package name. + +You then need to publish the `renovate-config-fastcore` package where the `package.json` contains the field `renovate-config` and then put your config under the field `default`. +For example: + +```json +{ + "name": "renovate-config-fastcore", + "version": "0.0.1", + ... + "renovate-config": { + "default": { + "extends": ["config:base", "schedule:nonOfficeHours"] + } + } +} +``` + +Then in each of your repositories you can add your Renovate config like: + +```json + "extends": ["fastcore"] +``` + +Any repository including this config will then adopt the rules of the default `library` preset but schedule it on weeknights or weekends. + +Note: if you prefer to publish using the namespace `@fastcore/renovate-config` then you would use the `@` prefix instead: + +```json + "extends": ["@fastcore"] +``` diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 522eb4fe24a59d..cf9b4062f3ac60 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -69,7 +69,7 @@ With the above config: ## additionalBranchPrefix This value defaults to an empty string, and is typically not necessary. -Some managers populate this field for historical reasons, for example we use `docker-` for Docker branches, so they may look like `renovate/docker-ubuntu-16.x`. +Some managers previously populated this field, but they no longer do so by default. You normally don't need to configure this, but one example where it can be useful is combining with `parentDir` in monorepos to split PRs based on where the package definition is located, e.g. ```json @@ -631,6 +631,12 @@ Because `fileMatch` is mergeable, you don't need to duplicate the defaults and c If you configure `fileMatch` then it must be within a manager object (e.g. `dockerfile` in the above example). The full list of supported managers can be found [here](https://docs.renovatebot.com/modules/manager/). +## filterUnavailableUsers + +When this option is enabled PRs are not assigned to users that are unavailable. +This option only works on platforms that support the concept of user availability. +For now, you can only use this option on the GitLab platform. + ## followTag Caution: advanced functionality. Only use it if you're sure you know what you're doing. @@ -969,13 +975,6 @@ The above is the same as if you wrote this package rule: } ``` -## ignoreNpmrcFile - -By default, Renovate will look for and use any `.npmrc` file it finds in a repository. -Additionally, it will be read in by `npm` or `yarn` at the time of lock file generation. -Sometimes this causes problems, for example if the file contains placeholder values, so you can configure this to `true` and Renovate will ignore any `.npmrc` files it finds and temporarily remove the file before running `npm install` or `yarn install`. -Renovate will try to configure this to `true` also if you have configured any `npmrc` string within your config file. - ## ignorePaths Using this setting, you can selectively ignore package files that you don't want Renovate autodiscovering. @@ -1517,7 +1516,6 @@ For example to apply a special label for Major updates: ## patch Add to this object if you wish to define rules that apply only to patch updates. -Only applies if `separateMinorPatch` is set to true. ## php @@ -1542,7 +1540,6 @@ If enabled Renovate will pin Docker images by means of their SHA256 digest and n Post-upgrade tasks are commands that are executed by Renovate after a dependency has been updated but before the commit is created. The intention is to run any additional command line tools that would modify existing files or generate new files when a dependency changes. -This is only available on Renovate instances that have a `trustLevel` of 'high'. Each command must match at least one of the patterns defined in `allowedPostUpgradeTasks` in order to be executed. If the list of allowed tasks is empty then no tasks will be executed. diff --git a/docs/usage/configuration-templates.md b/docs/usage/configuration-templates.md index 10911f76f2857f..c239ac69fe898a 100644 --- a/docs/usage/configuration-templates.md +++ b/docs/usage/configuration-templates.md @@ -21,8 +21,7 @@ Most users will be happy with the default `branchPrefix` of `renovate/`, but you Say you don't want the forward slashes, in that case you would use `renovate-` as your `branchPrefix`. The onboarding PR will always use `renovate/configure`. -`additionalBranchPrefix` is optional and by default is empty for all JavaScript dependencies. -We use `docker-` for all Docker updates, branches will look like this: `renovate/docker-ubuntu-16.x`. +`additionalBranchPrefix` is optional and by default is empty. `branchTopic` depends on the package manager and upgrade type, so you will see a lot of variety. This is probably a setting you want to change yourself. diff --git a/docs/usage/dependency-pinning.md b/docs/usage/dependency-pinning.md index 5329ab5a7e3a49..909f647984b5d4 100644 --- a/docs/usage/dependency-pinning.md +++ b/docs/usage/dependency-pinning.md @@ -223,6 +223,6 @@ If/when this starts bothering you, add Renovate rules to reduce the volume, such ## References This is a "living" document and we plan to update it whenever we think of something new or someone makes a valid point we've missed or misunderstood. -[GitHub Location](https://github.com/renovatebot/renovate/blob/master/website/docs/dependency-pinning.md) +[GitHub Location](https://github.com/renovatebot/renovate/blob/main/website/docs/dependency-pinning.md) Updated 2018-01-19 after [excellent feedback on lockfiles](https://github.com/commitizen/cz-conventional-changelog-default-export/pull/4#issuecomment-358038966) by [@LinusU](https://github.com/LinusU) diff --git a/docs/usage/faq.md b/docs/usage/faq.md index bcf253b27896bf..5c71756c2c5e31 100644 --- a/docs/usage/faq.md +++ b/docs/usage/faq.md @@ -208,10 +208,7 @@ To learn more read the section below. You can see in the example above that Renovate won't normally open a PR for the `snorgleborf` patch release. -There are 2 ways to tell Renovate to open a separate PR for the patch release: - -- Set `separateMinorPatch` to `true` -- Set `automerge` to the value: `"patch"` +You can tell Renovate to open a separate PR for the patch release by setting `separateMinorPatch` to `true`. In both cases, Renovate will open 3 PRs: diff --git a/docs/usage/node.md b/docs/usage/node.md index b665bfb1fbb384..6ac798e6759952 100644 --- a/docs/usage/node.md +++ b/docs/usage/node.md @@ -30,18 +30,18 @@ When Renovate processes your project's repository it will look for the files lis ## Configuring Support Policy -Renovate supports a [`supportPolicy`](/configuration-options/#supportpolicy) option that can be passed the following values and associated versions (current as of Feb 2021): +Renovate supports a [`supportPolicy`](/configuration-options/#supportpolicy) option that can be passed the following values and associated versions (current as of April 2021): **Default:** `lts` | supportPolicy | versions | description | | ------------- | -------------- | -------------------------------------------------------- | -| all | 10, 12, 14, 15 | All releases that have not passed their end date | -| lts | 10, 12, 14 | All releases classified as LTS, including in maintenance | -| active | 14, 15 | All releases not in maintenance | +| all | 12, 14, 15, 16 | All releases that have not passed their end date | +| lts | 12, 14 | All releases classified as LTS, including in maintenance | +| active | 14, 16 | All releases not in maintenance | | lts_active | 14 | All releases both LTS and active | | lts_latest | 14 | The latest LTS release | -| current | 15 | The latest release from "all" | +| current | 16 | The latest release from "all" | The version numbers associated with each support policy will be updated as new versions of Node.js are released, moved to LTS or maintenance, etc. diff --git a/docs/usage/private-modules.md b/docs/usage/private-modules.md index 44d95db472515c..b132990ba4d5a8 100644 --- a/docs/usage/private-modules.md +++ b/docs/usage/private-modules.md @@ -1,152 +1,214 @@ --- -title: Private npm module support -description: How to support private npm modules when using Renovate +title: Private module support +description: How to support private modules when using Renovate --- -# Private npm module support +# Private module support -## When are npm private modules used? +It's a very common requirement to be able to support private module/dependency lookups. +This page describes Renovate's approach to authentication. -Private npm modules are used at two times during Renovate's process. +First, a quick note on terminology: -### 1. Module lookup +- The terms `module`, `package` and `dependency` can mostly be used interchangeably below +- The terms `credentials`, `secrets` and `authentication` are also used interchangeably -If a private npm module is listed as a dependency in a `package.json`, then Renovate will attempt to keep it up-to-date by querying the npm registry like it would for any other package. -Hence, by default with no configuration a private package lookup will fail, because of lack of credentials. -This means it won't be "renovated" and its version will remain unchanged in the package file unless you update it manually. -These failures don't affect Renovate's ability to look up _other_ modules in the same package file. +## When does Renovate need credentials? -Assuming the private module lookup succeeds (solutions for that are described later in this document) then private package versions will be kept up-to-date like public package versions are. +By default, the only credentials Renovate has are those for the "platform", i.e. GitHub, GitLab, etc. +If the token used has sufficient permissions, this will enable Renovate to lookup dependencies located in alternative repositories on the same host or any hosted on any embedded package registry on the same host. -### 2. Lock file generation +It's also quite common to need to look up packages on other protected hosts, including npmjs, Docker Hub, or private registries like Nexus or Artifactory. +Any time you need Renovate to access such registries with credentials then you will need to provision them as part of your config. -If you are using a lock file (e.g. Yarn's `yarn.lock` or npm's `package-lock.json`) then Renovate needs to update that lock file whenever _any_ package listed in your package file is updated to a new version. +There are four times in Renovate's behavior when it may need credentials: -To do this, Renovate will run `npm install` or equivalent and save the resulting lock file. -If a private module hasn't been updated, it _usually_ won't matter to npm/Yarn because they won't attempt to update its lock file entry anyway. -However it's possible that the install will fail if it attempts to look up that private module for some reason, even when that private module is not the main one being updated. -It's therefore better to provide Renovate with all the credentials it needs to look up private packages. +- Resolving private config presets +- Looking up dependency versions +- Looking up release notes +- Passing to package managers when updating lock files or checksums -## Supported npm authentication approaches +Note: if you self-host Renovate, and have a self-hosted registry which _doesn't_ require authentication to access, then such modules/packages are not considered "private" to Renovate. -The recommended approaches in order of preference are: +## Private Config Presets -**Self-hosted hostRules**: Configure a hostRules entry in the bot's `config.js` with the `hostType`, `hostName` and `token` specified +Renovate supports config presets, including those which are private. -**Self-hosted .npmrc**: copy an `.npmrc` file to the home dir of the bot. +Although npm presets were the first type supported, they are now deprecated and it is recommend that all users migrate to git-hosted "local" presets instead. +However if you do still use them, private modules should work if you configure the `npmrc` file including token credentials in your bot admin config. +Credentials stored on disk (e.g. in `~/.npmrc`) are no longer supported. -**Renovate App with private modules from npmjs.org**: Add an encrypted `npmToken` to your Renovate config +The recommended way of using local presets is to configure then using "local" presets, e.g. `"extends": ["local>myorg/renovate-config"]`, and ensure that the platform token has access to that repo. -**Renovate App with a private registry**: Add an unencrypted `npmrc` plus an encrypted `npmToken` in config +It's not recommended that you use a private repository to host your config while then extending it from a public repository. +If your preset doesn't contain secrets then you should make it public, while if it does contain secrets then it's better to split your preset between a public one which all repos extend, and a private one with secrets which only other private repos extend. -All the various approaches are described below: +In summary, the recommended approach to private presets is: -### Add hostRule to bots config +- Host the presets on the same server/platform as other repositories +- Make sure you install Renovate into the preset repository so that it has credentials to access it from other private repos +- Use `local>....` syntax to refer to private presets -Define `hostRules` like this: +## Dependency Version Lookups -```js -module.exports = { - hostRules: [ +Whenever Renovate detects that a project uses a particular dependency, it attempts to look up that dependency to see if any new versions exist. +If such a package is private, then Renovate must be configured with the relevant credentials. +Renovate does not use any package managers for this step and performs all HTTP(S) lookups itself, including insertion of authentication headers. + +Configuring Renovate with credentials requires `hostRules`. +Each host rule consists of a `hostType` value and/or a way to match against hosts using `baseUrl`, `hostName` or `domainName`. + +`hostType` is not particularly important at this step unless you have different credentials for the same host, however it is sometimes useful in later steps so is good to include if you can. +It can be either a "platform" name (e.g. `github`, `azure`, etc) or a "datasource" name (e.g. `npm`, `maven`, `github-tags`, etc). + +`baseUrl` can be used if you want to only apply the credentials for a nested path within the host, e.g. `https://registry.company.com/nested/path/`. +If the same credentials apply to all paths on a host, then use `hostName` instead, e.g. `registry.company.com`. +Finally, to apply credentials to all hosts within the domain, use `domainName`, e.g. `company.com`. +You need to pick _only one_ of these and not configure more than one of these fields within the same host rule, otherwise it will error. + +In addition to the above options to match against a host, you need to add the credentials. +Typically they are either `token`, or `username` + `password`. +Other credential terms are not supported yet. + +Here is an example of some host rules: + +```json +{ + "hostRules": [ { - hostType: 'npm', - hostName: 'registry.npmjs.org', - token: process.env.NPMJS_TOKEN, + "hostName": "registry.npmjs.org", + "token": "abc123" }, { - hostType: 'npm', - baseUrl: - 'https://pkgs.dev.azure.com/{organization}/_packaging/{feed}/npm/registry/', - username: 'VssSessionToken', - password: process.env.AZURE_NPM_TOKEN, - }, - ], -}; + "baseUrl": "https://registry.company.com/pypi-simple/", + "username": "engineering", + "password": "abc123" + } + ] +} ``` -**NOTE:** Do not use `NPM_TOKEN` as an environment variable, it's incompatible with `hostRules` and will be deprecated soon. +Renovate applies theses `hostRules` to every HTTP(s) request which is sent, so they are largely independent of any platform or datasource logic. +With `hostRules` in place, private package lookups should all work. -### Commit .npmrc file into repository +## Looking up Release Notes -One approach that many projects use for private repositories is to simply check in an authenticated `.npmrc` into the repository that is then shared between all developers. -Therefore anyone running `npm install` or `yarn install` from the project root will be automatically authenticated with npm without having to distribute npm logins to every developer and make sure they've run `npm login` first before installing. +When Renovate creates Pull Requests, its default behavior is to locate and embed release notes/changelogs of packages. +These release notes are fetched from the source repository of packages and not from the registries themselves, so if they are private then they will require different credentials. -The good news is that this works for Renovate too. -If Renovate detects a `.npmrc` or `.yarnrc` file then it will use it for its install. +When it comes to open source, most packages host their source on `github.com` in public repositories. +However, GitHub greatly rate limits unauthenticated API requests so there is a need to configure credentials for github.com as otherwise the bot will get rate limited quickly. +It can be confusing for people who host their own source code privately to be asked to configure a `github.com` token but without it Release Notes for most open source packages will be blocked. -Does not work if using binarySource=docker. -_This method will be deprecated soon_ +Currently the preferred way to configure `github.com` credentials for self-hosted Renovate is: -### Add npmrc string to Renovate config +- Create a read-only Personal Access Token (PAT) for a `github.com` account. This can be any GitHub account, it might be better to create a "empty" account just for this purpose. +- Add the PAT to Renovate using the environment variable `GITHUB_COM_TOKEN` -The above solution maybe have a downside that all users of the repository (e.g. developers) will also use any `.npmrc` that is checked into the repository, instead of their own one in `~/.npmrc`. -To avoid this, you can instead add your `.npmrc` authentication line to your Renovate config under the field `npmrc`. e.g. a `renovate.json` might look like this: +## Package Manager Credentials for Artifact Updating -```json -{ - "npmrc": "//some.registry.com/:_authToken=abcdefghi-1234-jklmno-aac6-12345567889" -} -``` +In Renovate terminology, "artifacts" includes lock files, checksum files, and vendored dependencies. +One way of understanding artifacts is: "everything else that needs to be updated when the dependency version changes". -If configured like this, Renovate will use this to authenticate with npm and will ignore any `.npmrc` files(s) it finds checked into the repository. +Not all package managers supported by Renovate require artifact updating, because not all use lock or checksum files. +But when such files need updating, Renovate does so by using the package managers themselves instead of trying to "reverse engineer" each package manager's file formats and behavior. +Importantly, such package managers are run via shell commands and do not understand Renovate's `hostRules` objects, so Renovate needs to reformat the credentials into formats (such as environment variables or configuration files) which the package manager understands. -### Add npmToken to Renovate config +Because of this need to convert `hostRules` credentials into a format which package managers understand, sometimes artifact updating can fail due to missing credentials. +Sometimes this can be resolved by changing Renovate configuration, but other times it may be due to a feature gap. +The following details the most common/popular manager artifacts updating and how credentials are passed: -If you are using the main npmjs registry then you can configure just the npmToken instead: +### bundler -```json -{ - "npmToken": "abcdefghi-1234-jklmno-aac6-12345567889" -} -``` +`hostRules` with `hostType=rubygems` are converted into environment variables which Bundler supports. -### Add an encrypted npm token to Renovate config +### composer -If you don't wish for all users of the repository to be able to see the unencrypted token, you can encrypt it with Renovate's public key instead, so that only Renovate can decrypt it. +Any `hostRules` token for `github.com` or `gitlab.com` are found and written out to `COMPOSER_AUTH` in env for Composer to parse. +Any `hostRules` with `hostType=packagist` are also included. -Go to , paste in your npm token, click "Encrypt", then copy the encrypted result. +### gomod -Add the encrypted result inside an `encrypted` object like this: +If a `github.com` token is found in `hostRules`, then it is written out to local git config prior to running `go` commands. +The command run is `git config --global url."https://${token}@github.com/".insteadOf "https://github.com/"`. -```json -{ - "encrypted": { - "npmToken": "xxT19RIdhAh09lkhdrK39HzKNBn3etoLZAwHdeJ25cX+5y52a9kAC7flXmdw5JrkciN08aQuRNqDaKxp53IVptB5AYOnQPrt8MCT+x0zHgp4A1zv1QOV84I6uugdWpFSjPUkmLGMgULudEZJMlY/dAn/IVwf/IImqwazY8eHyJAA4vyUqKkL9SXzHjvS+OBonQ/9/AHYYKmDJwT8vLSRCKrXxJCdUfH7ZnikZbFqjnURJ9nGUHP44rlYJ7PFl05RZ+X5WuZG/A27S5LuBvguyQGcw8A2AZilHSDta9S/4eG6kb22jX87jXTrT6orUkxh2WHI/xvNUEout0gxwWMDkA==" - } -} -``` +### npm -If you have no `.npmrc` file then Renovate will create one for you, pointing to the default npmjs registry. -If instead you use an alternative registry or need an `.npmrc` file for some other reason, you should configure it too and substitute the npm token with `${NPM_TOKEN}` for it to be replaced. e.g. +The best way to do this now is using `hostRules` and no longer via `.npmrc` files on disk or in config. +`hostRules` credentials with `hostType=npm` are written to a `.npmrc` file in the same directory as the `package.json` being updated. +See [private npm modules](./private-npm-modules) for more details. -```json -{ - "encrypted": { - "npmToken": "xxT19RIdhAh09lkhdrK39HzKNBn3etoLZAwHdeJ25cX+5y52a9kAC7flXmdw5JrkciN08aQuRNqDaKxp53IVptB5AYOnQPrt8MCT+x0zHgp4A1zv1QOV84I6uugdWpFSjPUkmLGMgULudEZJMlY/dAn/IVwf/IImqwazY8eHyJAA4vyUqKkL9SXzHjvS+OBonQ/9/AHYYKmDJwT8vLSRCKrXxJCdUfH7ZnikZbFqjnURJ9nGUHP44rlYJ7PFl05RZ+X5WuZG/A27S5LuBvguyQGcw8A2AZilHSDta9S/4eG6kb22jX87jXTrT6orUkxh2WHI/xvNUEout0gxwWMDkA==" - }, - "npmrc": "registry=https://my.custom.registry/npm\n//my.custom.registry/npm:_authToken=${NPM_TOKEN}" -} -``` +### nuget + +For each known NuGet registry, Renovate searches for `hostRules` with `hostType=nuget` and matching host. +For those found, a command similar to the following is run: `dotnet nuget add source ${registryInfo.feedUrl} --configfile ${nugetConfigFile} --username ${username} --password ${password} --store-password-in-clear-text` + +### poetry + +For every poetry source, a `hostRules` search is done and then any found credentials are added to env like `POETRY_HTTP_BASIC_X_USERNAME` and `POETRY_HTTP_BASIC_X_PASSWORD`. + +## WhiteSource Renovate Hosted App Encryption + +The popular [Renovate App on GitHub](https://github.com/apps/renovate) is hosted by WhiteSource. +If you are a user of this app, and have private modules, then the following is applicable. + +### Private presets with public repositories + +If you have a preset in a private repo but reference ("extend") it from a public repository then it won't work. +This is because public repositories are provided with a token scoped to only that particular repository, and not for all repositories within the organization. +This is a security measure so that if a the token is accidentally leaked publicly, the damage is limited to the public repository it leaked to and not to every repository within the organization. -Renovate will then use the following logic: +The solution to this is that you should break your presets into public and private ones, and reference only the public ones from public repositories. -1. If no `npmrc` string is present in config then one will be created with the `_authToken` pointing to the default npmjs registry -2. If an `npmrc` string is present and contains `${NPM_TOKEN}` then that placeholder will be replaced with the decrypted token -3. If an `npmrc` string is present but doesn't contain `${NPM_TOKEN}` then the file will have `_authToken=` appended to it +### Encrypting secrets -### Encrypted entire .npmrc file into config +It is strongly recommended that you don't commit secrets to repositories, including private ones, and this includes secrets needed by Renovate to access private modules. +Therefore the preferred approach to secrets is that the bot administrator configures them as `hostRules` which are then applied to all repositories which the bot accesses. -Copy the entire .npmrc, replace newlines with `\n` chars, and then try encrypting it at +If you need to provide credentials to the hosted Renovate App, please do this: -You will then get an encrypted string that you can substitute into your renovate.json instead. -The result will now look something like this: +- Encrypt each secret string using . Note: this encrypts using the app's public key fully in the browser and does not send the original secret to any server. You can download this file and perform the encryption fully offline if you like. +- Wrap each secret field in an [encrypted](https://docs.renovatebot.com/configuration-options/#encrypted) object and paste in the encrypted secret value instead. An example is shown below: ```json { - "encrypted": { - "npmrc": "WOTWu+jliBtXYz3CU2eI7dDyMIvSJKS2N5PEHZmLB3XKT3vLaaYTGCU6m92Q9FgdaM/q2wLYun2JrTP4GPaW8eGZ3iiG1cm7lgOR5xPnkCzz0DUmSf6Cc/6geeVeSFdJ0zqlEAhdNMyJ4pUW6iQxC3WJKgM/ADvFtme077Acvc0fhCXv0XvbNSbtUwHF/gD6OJ0r2qlIzUMGJk/eI254xo5SwWVctc1iZS9LW+L0/CKjqhWh4SbyglP3lKE5shg3q7mzWDZepa/nJmAnNmXdoVO2aPPeQCG3BKqCtCfvLUUU/0LvnJ2SbQ1obyzL7vhh2OF/VsATS5cxbHvoX/hxWQ==" - } + "hostRules": [ + { + "hostName": "registry.npmjs.org", + "encrypted": { + "token": "3f832f2983yf89hsd98ahadsjfasdfjaslf............" + } + }, + { + "baseUrl": "https://custom.registry.company.com/pypi/", + "username": "bot1", + "encrypted": { + "password": "p278djfdsi9832jnfdshufwji2r389fdskj........." + } + } + ] } ``` -However be aware that if your `.npmrc` is too long to encrypt then the above command will fail. +### Access to GitHub Actions Secrets + +The WhiteSource Renovate App does not run using GitHub Actions, but such secrets would be a bad fit for the app anyway for the following reasons: + +- The app would be granted access to _all_ the repository/org secrets, not just the ones you want +- If Renovate wants access to such secrets, it would need to ask for them from every user, not just the ones who want to use this approach (GitHub does not support the concept of optional permissions for Apps, so people do not have the option to decline) + +## Admin/Bot config vs User/Repository config for Self-hosted users + +"AdminBot config" refers to the config which the Renovate Bot administrator provides at bot startup, e.g. using environment variables, CLI parameters, or the `config.js` configuration file. +User/Repository config refers to the in-repository config file which defaults to `renovate.json` but has a large number of alternative filenames supported. + +If there is a need to supply custom rules for certain repository, it can still be done using the `config.js` file and the `repositories` array. + +If per-repository config must be done within the repository, it is still recommended against committing secrets directly (including e.g. `.npmrc` files with tokens) and instead encrypting them with a custom public key first. +For instructions on this, see the above section on encrypting secrets for the WhiteSource Renovate App but instead: + +- Save a copy of the HTML file locally, or host it locally +- Generate a public/private key pair for the app using the instructions in [privateKey](https://docs.renovatebot.com/self-hosted-configuration/#privatekey) +- Replace the existing public key in the HTML with the public key you generated in the step prior +- Use the resulting HTML encrypt page to encrypt secrets for your app before adding them to user/repository config +- Configure the app to run with `privateKey` set to the private key you generated above diff --git a/docs/usage/private-npm-modules.md b/docs/usage/private-npm-modules.md new file mode 100644 index 00000000000000..d7efa9c7fad7f5 --- /dev/null +++ b/docs/usage/private-npm-modules.md @@ -0,0 +1,145 @@ +--- +title: Private npm module support +description: How to support private npm modules when using Renovate +--- + +# Private npm module support + +## When are npm private modules used? + +Private npm modules are used at two times during Renovate's process: + +1. Module lookup +1. Lock file generation + +This is explained in more detail below. + +### Module lookup + +If a private npm module is listed as a dependency in the `package.json` file Renovate attempts to keep it up-to-date. +Renovate queries the npm registry like it does for any other package. +By default Renovate runs without any credentials, and so any private package lookup will fail. +This means, that any private package will not be renovated, and must be updated manually. +The failure to authenticate doesn't affect Renovate's ability to look up _other_ modules in the same package file. + +You can fix the private package lookup problem by providing the Renovate bot with the proper credentials. +This is described later in this document. + +Assuming the private module lookup succeeds then private package versions will be kept up-to-date like the public package versions are. + +### Lock file generation + +If you use a lock file (e.g. Yarn's `yarn.lock` or npm's `package-lock.json`) then Renovate must update that lock file whenever _any_ package listed in your package file is updated to a new version. + +To do this, Renovate runs `npm install` or equivalent and saves the resulting lock file. +If a private module hasn't been updated, it _usually_ won't matter to npm/Yarn because they won't attempt to update its lock file entry anyway. +However it's possible that the install will fail if it attempts to look up that private module for some reason, even when that private module is not the main one being updated. +It's therefore better to provide Renovate with all the credentials it needs to look up private packages. + +## Supported npm authentication approaches + +The recommended approaches in order of preference are: + +1. **Self-hosted hostRules**: Configure a hostRules entry in the bot's `config.js` with the `hostType`, `hostName` and `token` specified +1. **Renovate App with private modules from npmjs.org**: Add an encrypted `npmToken` to your Renovate config +1. **Renovate App with a private registry**: Add an unencrypted `npmrc` plus an encrypted `npmToken` in config + +These approaches are described in full below. + +### Add hostRule to bots config + +Define `hostRules` like this: + +```js +module.exports = { + hostRules: [ + { + hostType: 'npm', + hostName: 'registry.npmjs.org', + token: process.env.NPMJS_TOKEN, + }, + { + hostType: 'npm', + baseUrl: + 'https://pkgs.dev.azure.com/{organization}/_packaging/{feed}/npm/registry/', + username: 'VssSessionToken', + password: process.env.AZURE_NPM_TOKEN, + }, + ], +}; +``` + +**NOTE:** Do not use `NPM_TOKEN` as an environment variable. + +### Add npmrc string to Renovate config + +You can add an `.npmrc` authentication line to your Renovate config under the field `npmrc`. e.g. a `renovate.json` might look like this: + +```json +{ + "npmrc": "//some.registry.com/:_authToken=abcdefghi-1234-jklmno-aac6-12345567889" +} +``` + +If configured like this, Renovate will use this to authenticate with npm and will ignore any `.npmrc` files(s) it finds checked into the repository. + +### Add npmToken to Renovate config + +If you are using the main npmjs registry then you can configure just the `npmToken` instead: + +```json +{ + "npmToken": "abcdefghi-1234-jklmno-aac6-12345567889" +} +``` + +### Add an encrypted npm token to Renovate config + +If you don't want all users of the repository to see the unencrypted token, you can encrypt it with Renovate's public key instead, so that only Renovate can decrypt it. + +Go to , paste in your npm token, click "Encrypt", then copy the encrypted result. + +Paste the encrypted result inside an `encrypted` object like this: + +```json +{ + "encrypted": { + "npmToken": "xxT19RIdhAh09lkhdrK39HzKNBn3etoLZAwHdeJ25cX+5y52a9kAC7flXmdw5JrkciN08aQuRNqDaKxp53IVptB5AYOnQPrt8MCT+x0zHgp4A1zv1QOV84I6uugdWpFSjPUkmLGMgULudEZJMlY/dAn/IVwf/IImqwazY8eHyJAA4vyUqKkL9SXzHjvS+OBonQ/9/AHYYKmDJwT8vLSRCKrXxJCdUfH7ZnikZbFqjnURJ9nGUHP44rlYJ7PFl05RZ+X5WuZG/A27S5LuBvguyQGcw8A2AZilHSDta9S/4eG6kb22jX87jXTrT6orUkxh2WHI/xvNUEout0gxwWMDkA==" + } +} +``` + +If you have no `.npmrc` file then Renovate creates one for you, pointing to the default npmjs registry. +If instead you use an alternative registry or need an `.npmrc` file for some other reason, you should configure it too and substitute the npm token with `${NPM_TOKEN}` for it to be replaced. e.g. + +```json +{ + "encrypted": { + "npmToken": "xxT19RIdhAh09lkhdrK39HzKNBn3etoLZAwHdeJ25cX+5y52a9kAC7flXmdw5JrkciN08aQuRNqDaKxp53IVptB5AYOnQPrt8MCT+x0zHgp4A1zv1QOV84I6uugdWpFSjPUkmLGMgULudEZJMlY/dAn/IVwf/IImqwazY8eHyJAA4vyUqKkL9SXzHjvS+OBonQ/9/AHYYKmDJwT8vLSRCKrXxJCdUfH7ZnikZbFqjnURJ9nGUHP44rlYJ7PFl05RZ+X5WuZG/A27S5LuBvguyQGcw8A2AZilHSDta9S/4eG6kb22jX87jXTrT6orUkxh2WHI/xvNUEout0gxwWMDkA==" + }, + "npmrc": "registry=https://my.custom.registry/npm\n//my.custom.registry/npm:_authToken=${NPM_TOKEN}" +} +``` + +Renovate will then use the following logic: + +1. If no `npmrc` string is present in config then one will be created with the `_authToken` pointing to the default npmjs registry +1. If an `npmrc` string is present and contains `${NPM_TOKEN}` then that placeholder will be replaced with the decrypted token +1. If an `npmrc` string is present but doesn't contain `${NPM_TOKEN}` then the file will have `_authToken=` appended to it + +### Encrypted entire .npmrc file into config + +Copy the entire `.npmrc`, replace newlines with `\n` characters , and then try encrypting it at . + +You will then get an encrypted string that you can substitute into your `renovate.json` instead. +The end-result looks like this: + +```json +{ + "encrypted": { + "npmrc": "WOTWu+jliBtXYz3CU2eI7dDyMIvSJKS2N5PEHZmLB3XKT3vLaaYTGCU6m92Q9FgdaM/q2wLYun2JrTP4GPaW8eGZ3iiG1cm7lgOR5xPnkCzz0DUmSf6Cc/6geeVeSFdJ0zqlEAhdNMyJ4pUW6iQxC3WJKgM/ADvFtme077Acvc0fhCXv0XvbNSbtUwHF/gD6OJ0r2qlIzUMGJk/eI254xo5SwWVctc1iZS9LW+L0/CKjqhWh4SbyglP3lKE5shg3q7mzWDZepa/nJmAnNmXdoVO2aPPeQCG3BKqCtCfvLUUU/0LvnJ2SbQ1obyzL7vhh2OF/VsATS5cxbHvoX/hxWQ==" + } +} +``` + +However be aware that if your `.npmrc` is too long to encrypt then the above command will fail. diff --git a/docs/usage/python.md b/docs/usage/python.md index 50ac4a2d5f43b6..b753e4e990b02b 100644 --- a/docs/usage/python.md +++ b/docs/usage/python.md @@ -9,7 +9,8 @@ Renovate supports the following Python package managers: - `pip` (e.g. `requirements.txt`, `requirements.pip`) files - `pipenv` (e.g. `Pipfile`) -- `setup.py` +- `setup.py` file +- `setup.cfg` file ## Versioning support diff --git a/docs/usage/self-hosted-configuration.md b/docs/usage/self-hosted-configuration.md index b6673d42fc629a..4021d45353eb11 100644 --- a/docs/usage/self-hosted-configuration.md +++ b/docs/usage/self-hosted-configuration.md @@ -9,6 +9,8 @@ The configuration options listed in this document are applicable to self-hosted Please also see [Self-Hosted Experimental Options](./self-hosted-experimental.md). +## allowCustomCrateRegistries + ## allowPostUpgradeCommandTemplating Set to true to allow templating of dependency level post-upgrade commands. @@ -52,18 +54,18 @@ npm ci --ignore-scripts npx ng update @angular/core --from=10.0.0 --to=11.0.0 --migrate-only --allow-dirty --force ``` +## allowScripts + ## allowedPostUpgradeCommands A list of regular expressions that determine which commands in `postUpgradeTasks` are allowed to be executed. If this list is empty then no tasks will be executed. -Also you need to have `"trustLevel": "high"`, otherwise these tasks will be ignored. e.g. ```json { - "allowedPostUpgradeCommands": ["^tslint --fix$", "^tslint --[a-z]+$"], - "trustLevel": "high" + "allowedPostUpgradeCommands": ["^tslint --fix$", "^tslint --[a-z]+$"] } ``` @@ -156,17 +158,6 @@ You would use put this in your configuration file: If you pulled a new `node` image, the final image would be `ghcr.io/renovatebot/node` instead of `docker.io/renovate/node`. -## dockerMapDotfiles - -This is used if you want to map "dotfiles" from your host computer home directory to containers that Renovate creates, e.g. for updating lock files. -Currently applicable to `.npmrc` only. - -```json -{ - "dockerMapDotfiles": true -} -``` - ## dockerUser Override default user and group used by Docker-based binaries. @@ -186,6 +177,14 @@ e.g. ## endpoint +## exposeAllEnv + +By default, Renovate only passes a limited set of environment variables to package managers. +Confidential data can be leaked if a malicious script enumerates all environment variables. +Set `exposeAllEnv` to `true` only if you have reviewed (and trust) the repositories which Renovate bot runs against. + +Setting this to `true` will also allow for variable substitution in `.npmrc` files. + ## force This object is used as a "force override" when you need to make sure certain configuration overrides whatever is configured in the repository. @@ -201,6 +200,14 @@ It will also override any settings in `packageRules`. ## forkMode You probably have no need for this option - it is an experimental setting for the Renovate hosted GitHub App. +If this is set to `true` then Renovate will fork the repository into the personal space of the person owning the Personal Access Token. + +## forkToken + +You probably have no need for this option - it is an experimental setting for the Renovate hosted GitHub App. +This should be set to a Personal Access Token (GitHub only) when `forkMode` is set to `true`. +Renovate will use this token to fork the repository into the personal space of the person owning the Personal Access Token. +Renovate will then create branches on the fork and opens Pull Requests on the parent repository. ## gitAuthor @@ -233,18 +240,6 @@ If left as default (null), a random short ID will be selected. ## logFileLevel -## logLevel - -We recommend that you run the Renovate bot at the debug level if you can. -Use the environment variable `LOG_LEVEL=debug` to run Renovate at the debug level. - -When you use `LOG_LEVEL=debug`, debug logging starts from the beginning of the app. -If you had configured debug logging in a file config, then the debug logging starts _after_ the file config is parsed. - -Additionally, if you configure `LOG_FORMAT=json` in env then logging will be done in JSON format instead of "pretty" format, which is usually better if you're doing any ingestion or parsing of the logs. - -Warning: Configuring `logLevel` config option or `--log-level` cli option is deprecated and will be removed in a major version. - ## onboarding Set this to `false` only if all three statements are true: @@ -387,13 +382,4 @@ This is currently applicable to `npm` and `lerna`/`npm` only, and only used in c ## token -## trustLevel - -Setting trustLevel to `"high"` can make sense in many self-hosted cases where the bot operator trusts the content in each repository. - -Setting trustLevel=high means: - -- Child processes are run with full access to `env` -- `.npmrc` files can have environment variable substitution performed - ## username diff --git a/docs/usage/self-hosted-experimental.md b/docs/usage/self-hosted-experimental.md index 1151bd65d624ac..2f00716900c3b6 100644 --- a/docs/usage/self-hosted-experimental.md +++ b/docs/usage/self-hosted-experimental.md @@ -27,11 +27,6 @@ If set to any integer, Renovate will use this integer instead of the default npm If set to any value, Renovate will skip its default artifacts filter check in the Maven datasource. Skiping the check will speed things up, but may result in versions being returned which don't properly exist on the server. -## RENOVATE_LEGACY_GIT_AUTHOR_EMAIL - -An additional `gitAuthor` email to ignore. -This variable is deprecated: use `ignoredAuthors` instead. - ## RENOVATE_PAGINATE_ALL If set to any value, Renovate will always paginate requests to GitHub fully, instead of stopping after 10 pages. diff --git a/docs/usage/self-hosting.md b/docs/usage/self-hosting.md index d17d179c95bc14..199b3c3965debb 100644 --- a/docs/usage/self-hosting.md +++ b/docs/usage/self-hosting.md @@ -20,7 +20,7 @@ The same goes for any other third party binary tool like `gradle` or `poetry` - ### Docker Renovate is available for Docker via an automated build [renovate/renovate](https://hub.docker.com/r/renovate/renovate/). -It builds `latest` based on the `master` branch and all semver tags are published too. +It builds `latest` based on the `main` branch and all semver tags are published too. For example, all the following are valid tags: ```sh diff --git a/lib/config/__snapshots__/migration.spec.ts.snap b/lib/config/__snapshots__/migration.spec.ts.snap index 48456d788edf78..7713dfac4bc167 100644 --- a/lib/config/__snapshots__/migration.spec.ts.snap +++ b/lib/config/__snapshots__/migration.spec.ts.snap @@ -78,6 +78,8 @@ Array [ exports[`config/migration migrateConfig(config, parentConfig) migrates config 1`] = ` Object { "additionalBranchPrefix": "{{parentDir}}-", + "allowCustomCrateRegistries": true, + "allowScripts": true, "autodiscover": true, "automerge": false, "automergeType": "branch", @@ -94,6 +96,7 @@ Object { "dependencyDashboard": true, "dependencyDashboardTitle": "foo", "enabled": true, + "exposeAllEnv": true, "extends": Array [ ":automergeBranch", "config:js-app", @@ -109,8 +112,8 @@ Object { "includeForks": true, "lockFileMaintenance": Object { "automerge": true, + "exposeAllEnv": false, "schedule": "before 5am", - "trustLevel": "low", }, "major": Object { "automerge": false, @@ -121,6 +124,7 @@ Object { "minor": Object { "automerge": true, }, + "npmrc": "", "nvmrc": Object { "packageRules": Array [ Object { @@ -243,7 +247,6 @@ Object { "travis": Object { "enabled": true, }, - "trustLevel": "high", } `; diff --git a/lib/config/__snapshots__/validation.spec.ts.snap b/lib/config/__snapshots__/validation.spec.ts.snap index c13b732365e535..6ae432f8ec8c02 100644 --- a/lib/config/__snapshots__/validation.spec.ts.snap +++ b/lib/config/__snapshots__/validation.spec.ts.snap @@ -164,6 +164,15 @@ Array [ ] `; +exports[`config/validation validateConfig(config) errors if invalid combinations in packageRules 1`] = ` +Array [ + Object { + "message": "packageRules[0]: packageRules cannot combine both matchUpdateTypes and registryUrls. Rule: {\\"matchUpdateTypes\\":[\\"major\\"],\\"registryUrls\\":[\\"https://registry.npmjs.org\\"]}", + "topic": "Configuration Error", + }, +] +`; + exports[`config/validation validateConfig(config) errors if language or manager objects are nested 1`] = ` Array [ Object { diff --git a/lib/config/admin.ts b/lib/config/admin.ts index 529aa966aacf88..14ba0eac59fd47 100644 --- a/lib/config/admin.ts +++ b/lib/config/admin.ts @@ -4,15 +4,17 @@ let adminConfig: RepoAdminConfig = {}; // TODO: https://github.com/renovatebot/renovate/issues/9603 export const repoAdminOptions = [ + 'allowCustomCrateRegistries', 'allowPostUpgradeCommandTemplating', + 'allowScripts', 'allowedPostUpgradeCommands', 'customEnvVariables', 'dockerChildPrefix', 'dockerImagePrefix', 'dockerUser', 'dryRun', + 'exposeAllEnv', 'privateKey', - 'trustLevel', ]; export function setAdminConfig(config: RenovateConfig = {}): void { diff --git a/lib/config/decrypt.spec.ts b/lib/config/decrypt.spec.ts index f0f604e60a3a18..c79072a5159fab 100644 --- a/lib/config/decrypt.spec.ts +++ b/lib/config/decrypt.spec.ts @@ -1,10 +1,9 @@ -import fs from 'fs'; -import { getName } from '../../test/util'; +import { getName, loadFixture } from '../../test/util'; import { setAdminConfig } from './admin'; import { decryptConfig } from './decrypt'; import type { RenovateConfig } from './types'; -const privateKey = fs.readFileSync('lib/config/keys/__fixtures__/private.pem'); +const privateKey = loadFixture(__filename, 'private.pem', 'keys'); describe(getName(__filename), () => { describe('decryptConfig()', () => { diff --git a/lib/config/definitions.ts b/lib/config/definitions.ts index ecc1d455c5f7b1..f03a692e3b37b4 100644 --- a/lib/config/definitions.ts +++ b/lib/config/definitions.ts @@ -254,14 +254,6 @@ const options: RenovateOptions[] = [ type: 'object', default: false, }, - { - name: 'dockerMapDotfiles', - description: - 'Map relevant home directory dotfiles into containers when binarySource=docker.', - admin: true, - type: 'boolean', - default: false, - }, { name: 'dockerChildPrefix', description: @@ -294,13 +286,6 @@ const options: RenovateOptions[] = [ admin: true, }, // Log options - { - name: 'logLevel', - description: 'Logging level. Deprecated, use `LOG_LEVEL` environment.', - stage: 'global', - type: 'string', - allowedValues: ['fatal', 'error', 'warn', 'info', 'debug', 'trace'], - }, { name: 'logFile', description: 'Log file path.', @@ -355,6 +340,15 @@ const options: RenovateOptions[] = [ default: false, admin: true, }, + { + name: 'forkToken', + description: + 'Will be used on GitHub when `forkMode` is set to `true` to clone the repositories.', + stage: 'repository', + type: 'string', + default: '', + admin: true, + }, { name: 'requireConfig', description: 'Set to true if repositories must have a config to activate.', @@ -480,17 +474,33 @@ const options: RenovateOptions[] = [ default: false, }, { - name: 'trustLevel', + name: 'exposeAllEnv', description: - 'Set this to "high" if the bot should trust the repository owners/contents.', + 'Configure this to true to allow passing of all env variables to package managers.', admin: true, - type: 'string', - default: 'low', + type: 'boolean', + default: false, + }, + { + name: 'allowScripts', + description: + 'Configure this to true if repositories are allowed to run install scripts.', + admin: true, + type: 'boolean', + default: false, + }, + { + name: 'allowCustomCrateRegistries', + description: + 'Configure this to true if custom crate registries are allowed.', + admin: true, + type: 'boolean', + default: false, }, { name: 'ignoreScripts', description: - 'Configure this to true if trustLevel is high but you wish to skip running scripts when updating lock files.', + 'Configure this to true if allowScripts=true but you wish to skip running scripts when updating lock files.', type: 'boolean', default: false, }, @@ -562,12 +572,6 @@ const options: RenovateOptions[] = [ default: null, admin: true, }, - { - name: 'ignoreNpmrcFile', - description: 'Whether to ignore any .npmrc file found in repository.', - type: 'boolean', - default: false, - }, { name: 'autodiscover', description: 'Autodiscover all repositories.', @@ -1068,8 +1072,7 @@ const options: RenovateOptions[] = [ }, { name: 'patch', - description: - 'Configuration to apply when an update type is patch. Only applies if `separateMinorPatch` is set to true.', + description: 'Configuration to apply when an update type is patch.', stage: 'package', type: 'object', default: {}, @@ -1503,6 +1506,12 @@ const options: RenovateOptions[] = [ type: 'boolean', default: false, }, + { + name: 'filterUnavailableUsers', + description: 'Filter reviewers and assignees based on their availability.', + type: 'boolean', + default: false, + }, { name: 'reviewersSampleSize', description: 'Take a random sample of given size from reviewers.', diff --git a/lib/config/index.ts b/lib/config/index.ts index 6fbe43fc3c351c..366813c25a0c80 100644 --- a/lib/config/index.ts +++ b/lib/config/index.ts @@ -1,4 +1,4 @@ -import { addStream, levels, logger, setContext } from '../logger'; +import { addStream, logger, setContext } from '../logger'; import { get, getLanguageList, getManagerList } from '../manager'; import { ensureDir, getSubDirectory, readFile } from '../util/fs'; import { ensureTrailingSlash } from '../util/url'; @@ -7,7 +7,6 @@ import * as defaultsParser from './defaults'; import * as definitions from './definitions'; import * as envParser from './env'; import * as fileParser from './file'; -import { resolveConfigPresets } from './presets'; import type { GlobalConfig, ManagerConfig, @@ -47,10 +46,10 @@ export async function parseConfigs( logger.debug('Parsing configs'); // Get configs - const defaultConfig = await resolveConfigPresets(defaultsParser.getConfig()); - const fileConfig = await resolveConfigPresets(fileParser.getConfig(env)); - const cliConfig = await resolveConfigPresets(cliParser.getConfig(argv)); - const envConfig = await resolveConfigPresets(envParser.getConfig(env)); + const defaultConfig = defaultsParser.getConfig(); + const fileConfig = fileParser.getConfig(env); + const cliConfig = cliParser.getConfig(argv); + const envConfig = envParser.getConfig(env); let config: GlobalConfig = mergeChildConfig(fileConfig, envConfig); config = mergeChildConfig(config, cliConfig); @@ -75,15 +74,6 @@ export async function parseConfigs( delete config.privateKeyPath; } - // Deprecated set log level: https://github.com/renovatebot/renovate/issues/8291 - // istanbul ignore if - if (config.logLevel) { - logger.warn( - 'Configuring logLevel in CLI or file is deprecated. Use LOG_LEVEL environment variable instead' - ); - levels('stdout', config.logLevel); - } - if (config.logContext) { // This only has an effect if logContext was defined via file or CLI, otherwise it would already have been detected in env setContext(config.logContext); diff --git a/lib/config/migration.spec.ts b/lib/config/migration.spec.ts index 7bd348c5ea4996..eb384c3abe331e 100644 --- a/lib/config/migration.spec.ts +++ b/lib/config/migration.spec.ts @@ -44,6 +44,7 @@ describe(getName(__filename), () => { onboarding: 'false' as never, multipleMajorPrs: true, gitFs: false, + ignoreNpmrcFile: true, separateMajorReleases: true, separatePatchReleases: true, suppressNotifications: ['lockFileErrors', 'prEditNotification'], @@ -56,6 +57,7 @@ describe(getName(__filename), () => { masterIssueTitle: 'foo', gomodTidy: true, upgradeInRange: true, + trustLevel: 'high', automergeType: 'branch-push', branchName: '{{{branchPrefix}}}{{{managerBranchPrefix}}}{{{branchTopic}}}{{{baseDir}}}', diff --git a/lib/config/migration.ts b/lib/config/migration.ts index 0cda3402888aaf..ee2418d89365b9 100644 --- a/lib/config/migration.ts +++ b/lib/config/migration.ts @@ -191,11 +191,19 @@ export function migrateConfig( migratedConfig.rebaseWhen = 'never'; } } else if (key === 'exposeEnv') { + migratedConfig.exposeAllEnv = val; delete migratedConfig.exposeEnv; - if (val === true) { - migratedConfig.trustLevel = 'high'; - } else if (val === false) { - migratedConfig.trustLevel = 'low'; + } else if (key === 'trustLevel') { + delete migratedConfig.trustLevel; + if (val === 'high') { + migratedConfig.allowCustomCrateRegistries ??= true; + migratedConfig.allowScripts ??= true; + migratedConfig.exposeAllEnv ??= true; + } + } else if (key === 'ignoreNpmrcFile') { + delete migratedConfig.ignoreNpmrcFile; + if (!is.string(migratedConfig.npmrc)) { + migratedConfig.npmrc = ''; } } else if ( key === 'branchName' && diff --git a/lib/config/presets/index.spec.ts b/lib/config/presets/index.spec.ts index 08acc21349fc43..38e7e4f982ad51 100644 --- a/lib/config/presets/index.spec.ts +++ b/lib/config/presets/index.spec.ts @@ -1,6 +1,5 @@ -import { getName, mocked } from '../../../test/util'; +import { getName, loadJsonFixture, mocked } from '../../../test/util'; import type { RenovateConfig } from '../types'; -import presetIkatyang from './__fixtures__/renovate-config-ikatyang.json'; import * as _local from './local'; import * as _npm from './npm'; import { @@ -17,6 +16,11 @@ jest.mock('./local'); const npm = mocked(_npm); const local = mocked(_local); +const presetIkatyang = loadJsonFixture( + __filename, + 'renovate-config-ikatyang.json' +); + npm.getPreset = jest.fn(({ packageName, presetName }) => { if (packageName === 'renovate-config-ikatyang') { return presetIkatyang.versions[presetIkatyang['dist-tags'].latest][ diff --git a/lib/config/presets/index.ts b/lib/config/presets/index.ts index 356d47782ecccd..7e71fc68e1716f 100644 --- a/lib/config/presets/index.ts +++ b/lib/config/presets/index.ts @@ -100,6 +100,7 @@ export function parsePreset(input: string): ParsedPreset { str = str.slice(0, str.indexOf('(')); } const presetsPackages = [ + 'compatibility', 'config', 'default', 'docker', diff --git a/lib/config/presets/internal/compatibility.ts b/lib/config/presets/internal/compatibility.ts new file mode 100644 index 00000000000000..ce1175f569fb34 --- /dev/null +++ b/lib/config/presets/internal/compatibility.ts @@ -0,0 +1,24 @@ +import { Preset } from '../types'; + +export const presets: Record = { + additionalBranchPrefix: { + buildkite: { + additionalBranchPrefix: 'buildkite-', + }, + cargo: { + additionalBranchPrefix: 'rust-', + }, + docker: { + additionalBranchPrefix: 'docker-', + }, + homebrew: { + additionalBranchPrefix: 'homebrew-', + }, + packageRules: [ + { + matchDatasources: ['helm'], + additionalBranchPrefix: 'helm-', + }, + ], + }, +}; diff --git a/lib/config/presets/internal/group.ts b/lib/config/presets/internal/group.ts index edfcd3b643464b..20a4c9a135f8b7 100644 --- a/lib/config/presets/internal/group.ts +++ b/lib/config/presets/internal/group.ts @@ -29,10 +29,24 @@ const staticGroups = { }, ], }, + nodeJs: { + description: + "Group anything that looks like Node.js together so that it's updated together", + packageRules: [ + { + matchDatasources: ['docker'], + matchPackageNames: ['node'], + matchPackagePatterns: ['/node$'], + excludePackageNames: ['calico/node'], + commitMessageTopic: 'Node.js', + }, + ], + }, recommended: { description: 'Use curated list of recommended non-monorepo package groupings', extends: [ + 'group:nodeJs', 'group:allApollographql', 'group:fortawesome', 'group:fusionjs', diff --git a/lib/config/presets/internal/index.ts b/lib/config/presets/internal/index.ts index fbbdd6a790ede3..e152b9747e19d7 100644 --- a/lib/config/presets/internal/index.ts +++ b/lib/config/presets/internal/index.ts @@ -1,4 +1,5 @@ import type { Preset, PresetConfig } from '../types'; +import * as compatibilityPreset from './compatibility'; import * as configPreset from './config'; import * as defaultPreset from './default'; import * as dockerPreset from './docker'; @@ -13,6 +14,7 @@ import * as schedulePreset from './schedule'; import * as workaroundsPreset from './workarounds'; export const groups: Record> = { + compatibility: compatibilityPreset.presets, config: configPreset.presets, default: defaultPreset.presets, docker: dockerPreset.presets, diff --git a/lib/config/presets/internal/monorepo.ts b/lib/config/presets/internal/monorepo.ts index caa89112cee590..bb13b6f8813db1 100644 --- a/lib/config/presets/internal/monorepo.ts +++ b/lib/config/presets/internal/monorepo.ts @@ -88,6 +88,7 @@ const repoGroups = { hamcrest: 'https://github.com/hamcrest/JavaHamcrest', Hangfire: 'https://github.com/HangfireIO/Hangfire', hapijs: 'https://github.com/hapijs', + HotChocolate: 'https://github.com/ChilliCream/hotchocolate', infrastructure: 'https://github.com/instructure/instructure-ui', istanbuljs: 'https://github.com/istanbuljs/istanbuljs', jasmine: 'https://github.com/jasmine/jasmine', @@ -118,6 +119,7 @@ const repoGroups = { nuxtjs: 'https://github.com/nuxt/nuxt.js', openfeign: 'https://github.com/OpenFeign/feign', opentelemetry: 'https://github.com/open-telemetry/opentelemetry-js', + OpenTelemetryDotnet: 'https://github.com/open-telemetry/opentelemetry-dotnet', picasso: 'https://github.com/qlik-oss/picasso.js', pnpjs: 'https://github.com/pnp/pnpjs', playwright: 'https://github.com/Microsoft/playwright', diff --git a/lib/config/presets/npm/index.spec.ts b/lib/config/presets/npm/index.spec.ts index 931ae3d39d6c60..fa5bd9afd76e95 100644 --- a/lib/config/presets/npm/index.spec.ts +++ b/lib/config/presets/npm/index.spec.ts @@ -7,7 +7,6 @@ jest.mock('registry-auth-token'); jest.mock('delay'); describe(getName(__filename), () => { - delete process.env.NPM_TOKEN; beforeEach(() => { jest.resetAllMocks(); setAdminConfig(); diff --git a/lib/config/types.ts b/lib/config/types.ts index 21806dd46c7ec6..cbbbd973379c4e 100644 --- a/lib/config/types.ts +++ b/lib/config/types.ts @@ -74,7 +74,6 @@ export interface GlobalOnlyConfig { gitPrivateKey?: string; logFile?: string; logFileLevel?: LogLevel; - logLevel?: LogLevel; prCommitsPerRunLimit?: number; privateKeyPath?: string; redisUrl?: string; @@ -84,15 +83,17 @@ export interface GlobalOnlyConfig { // Config options used within the repository worker, but not user configurable // The below should contain config options where admin=true export interface RepoAdminConfig { + allowCustomCrateRegistries?: boolean; allowPostUpgradeCommandTemplating?: boolean; + allowScripts?: boolean; allowedPostUpgradeCommands?: string[]; customEnvVariables?: Record; dockerChildPrefix?: string; dockerImagePrefix?: string; dockerUser?: string; dryRun?: boolean; + exposeAllEnv?: boolean; privateKey?: string | Buffer; - trustLevel?: 'low' | 'high'; } export interface LegacyAdminConfig { @@ -206,6 +207,7 @@ export interface AssigneesAndReviewersConfig { reviewers?: string[]; reviewersSampleSize?: number; additionalReviewers?: string[]; + filterUnavailableUsers?: boolean; } export type UpdateType = diff --git a/lib/config/validation.spec.ts b/lib/config/validation.spec.ts index fe9582f4b37b71..2535fa4318097a 100644 --- a/lib/config/validation.spec.ts +++ b/lib/config/validation.spec.ts @@ -585,5 +585,22 @@ describe(getName(__filename), () => { expect(warnings).toMatchSnapshot(); expect(errors).toHaveLength(0); }); + it('errors if invalid combinations in packageRules', async () => { + const config = { + packageRules: [ + { + matchUpdateTypes: ['major'], + registryUrls: ['https://registry.npmjs.org'], + }, + ], + } as any; + const { warnings, errors } = await configValidation.validateConfig( + config, + true + ); + expect(warnings).toHaveLength(0); + expect(errors).toHaveLength(1); + expect(errors).toMatchSnapshot(); + }); }); }); diff --git a/lib/config/validation.ts b/lib/config/validation.ts index 2fed4ee6a6d85d..abecfb0fcd9418 100644 --- a/lib/config/validation.ts +++ b/lib/config/validation.ts @@ -325,6 +325,35 @@ export async function validateConfig( message, }); } + // It's too late to apply any of these options once you already have updates determined + const preLookupOptions = [ + 'allowedVersions', + 'extractVersion', + 'followTag', + 'ignoreDeps', + 'ignoreUnstable', + 'rangeStrategy', + 'registryUrls', + 'respectLatest', + 'rollbackPrs', + 'separateMajorMinor', + 'separateMinorPatch', + 'separateMultipleMajor', + 'versioning', + ]; + if (is.nonEmptyArray(resolvedRule.matchUpdateTypes)) { + for (const option of preLookupOptions) { + if (resolvedRule[option] !== undefined) { + const message = `${currentPath}[${subIndex}]: packageRules cannot combine both matchUpdateTypes and ${option}. Rule: ${JSON.stringify( + packageRule + )}`; + errors.push({ + topic: 'Configuration Error', + message, + }); + } + } + } } else { errors.push({ topic: 'Configuration Error', diff --git a/lib/constants/error-messages.ts b/lib/constants/error-messages.ts index b032e18fcee8a2..eec1bbff1ecdff 100644 --- a/lib/constants/error-messages.ts +++ b/lib/constants/error-messages.ts @@ -12,6 +12,7 @@ export const PLATFORM_RATE_LIMIT_EXCEEDED = 'rate-limit-exceeded'; // Config Error export const CONFIG_VALIDATION = 'config-validation'; +export const CONFIG_PRESETS_INVALID = 'config-presets-invalid'; export const CONFIG_SECRETS_EXPOSED = 'config-secrets-exposed'; export const CONFIG_SECRETS_INVALID = 'config-secrets-invalid'; diff --git a/lib/datasource/cdnjs/index.spec.ts b/lib/datasource/cdnjs/index.spec.ts index 8535027de59767..6e6165ee1f647d 100644 --- a/lib/datasource/cdnjs/index.spec.ts +++ b/lib/datasource/cdnjs/index.spec.ts @@ -1,21 +1,11 @@ -import fs from 'fs'; import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { EXTERNAL_HOST_ERROR } from '../../constants/error-messages'; import { id as datasource } from '.'; -let res1 = fs.readFileSync( - 'lib/datasource/cdnjs/__fixtures__/d3-force.json', - 'utf8' -); -res1 = JSON.parse(res1); - -let res2 = fs.readFileSync( - 'lib/datasource/cdnjs/__fixtures__/bulma.json', - 'utf8' -); -res2 = JSON.parse(res2); +const res1 = loadFixture(__filename, 'd3-force.json'); +const res2 = loadFixture(__filename, 'bulma.json'); const baseUrl = 'https://api.cdnjs.com/'; diff --git a/lib/datasource/crate/__snapshots__/index.spec.ts.snap b/lib/datasource/crate/__snapshots__/index.spec.ts.snap index 48572b6e73a18d..6e8b60c6991564 100644 --- a/lib/datasource/crate/__snapshots__/index.spec.ts.snap +++ b/lib/datasource/crate/__snapshots__/index.spec.ts.snap @@ -331,7 +331,7 @@ Array [ ] `; -exports[`datasource/crate/index getReleases refuses to clone if trustLevel is not high 1`] = `null`; +exports[`datasource/crate/index getReleases refuses to clone if allowCustomCrateRegistries is not true 1`] = `null`; exports[`datasource/crate/index getReleases returns null for 404 1`] = ` Array [ diff --git a/lib/datasource/crate/index.spec.ts b/lib/datasource/crate/index.spec.ts index a83b9f6293da56..8bcf8fe19c08b0 100644 --- a/lib/datasource/crate/index.spec.ts +++ b/lib/datasource/crate/index.spec.ts @@ -5,7 +5,7 @@ import { DirectoryResult, dir } from 'tmp-promise'; import { dirname, join } from 'upath'; import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { setAdminConfig } from '../../config/admin'; import * as memCache from '../../util/cache/memory'; import { setFsConfig } from '../../util/fs'; @@ -20,12 +20,9 @@ import { jest.mock('simple-git'); const simpleGit: any = _simpleGit; -const res1 = fs.readFileSync('lib/datasource/crate/__fixtures__/libc', 'utf8'); -const res2 = fs.readFileSync( - 'lib/datasource/crate/__fixtures__/amethyst', - 'utf8' -); -const res3 = fs.readFileSync('lib/datasource/crate/__fixtures__/mypkg', 'utf8'); +const res1 = loadFixture(__filename, 'libc'); +const res2 = loadFixture(__filename, 'amethyst'); +const res3 = loadFixture(__filename, 'mypkg'); const baseUrl = 'https://raw.githubusercontent.com/rust-lang/crates.io-index/master/'; @@ -225,7 +222,7 @@ describe(getName(__filename), () => { expect(res).toBeDefined(); expect(httpMock.getTrace()).toMatchSnapshot(); }); - it('refuses to clone if trustLevel is not high', async () => { + it('refuses to clone if allowCustomCrateRegistries is not true', async () => { const { mockClone } = setupGitMocks(); const url = 'https://dl.cloudsmith.io/basic/myorg/myrepo/cargo/index.git'; @@ -240,7 +237,7 @@ describe(getName(__filename), () => { }); it('clones cloudsmith private registry', async () => { const { mockClone } = setupGitMocks(); - setAdminConfig({ trustLevel: 'high' }); + setAdminConfig({ allowCustomCrateRegistries: true }); const url = 'https://dl.cloudsmith.io/basic/myorg/myrepo/cargo/index.git'; const res = await getPkgReleases({ datasource, @@ -254,7 +251,7 @@ describe(getName(__filename), () => { }); it('clones other private registry', async () => { const { mockClone } = setupGitMocks(); - setAdminConfig({ trustLevel: 'high' }); + setAdminConfig({ allowCustomCrateRegistries: true }); const url = 'https://github.com/mcorbin/testregistry'; const res = await getPkgReleases({ datasource, @@ -268,7 +265,7 @@ describe(getName(__filename), () => { }); it('clones once then reuses the cache', async () => { const { mockClone } = setupGitMocks(); - setAdminConfig({ trustLevel: 'high' }); + setAdminConfig({ allowCustomCrateRegistries: true }); const url = 'https://github.com/mcorbin/othertestregistry'; await getPkgReleases({ datasource, @@ -284,7 +281,7 @@ describe(getName(__filename), () => { }); it('guards against race conditions while cloning', async () => { const { mockClone } = setupGitMocks(250); - setAdminConfig({ trustLevel: 'high' }); + setAdminConfig({ allowCustomCrateRegistries: true }); const url = 'https://github.com/mcorbin/othertestregistry'; await Promise.all([ @@ -310,7 +307,7 @@ describe(getName(__filename), () => { }); it('returns null when git clone fails', async () => { setupErrorGitMock(); - setAdminConfig({ trustLevel: 'high' }); + setAdminConfig({ allowCustomCrateRegistries: true }); const url = 'https://github.com/mcorbin/othertestregistry'; const result = await getPkgReleases({ diff --git a/lib/datasource/crate/index.ts b/lib/datasource/crate/index.ts index cce827f726b39f..44d39cb1852829 100644 --- a/lib/datasource/crate/index.ts +++ b/lib/datasource/crate/index.ts @@ -163,9 +163,9 @@ async function fetchRegistryInfo( }; if (flavor !== RegistryFlavor.CratesIo) { - if (getAdminConfig().trustLevel !== 'high') { + if (!getAdminConfig().allowCustomCrateRegistries) { logger.warn( - 'crate datasource: trustLevel=high is required for registries other than crates.io, bailing out' + 'crate datasource: allowCustomCrateRegistries=true is required for registries other than crates.io, bailing out' ); return null; } diff --git a/lib/datasource/dart/index.spec.ts b/lib/datasource/dart/index.spec.ts index 5228b332bf5ca1..abc986a028b1bc 100644 --- a/lib/datasource/dart/index.spec.ts +++ b/lib/datasource/dart/index.spec.ts @@ -1,15 +1,9 @@ -import fs from 'fs'; import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadJsonFixture } from '../../../test/util'; import { id as datasource } from '.'; -const body: any = JSON.parse( - fs.readFileSync( - 'lib/datasource/dart/__fixtures__/shared_preferences.json', - 'utf8' - ) -); +const body = loadJsonFixture(__filename, 'shared_preferences.json'); const baseUrl = 'https://pub.dartlang.org/api/packages/'; diff --git a/lib/datasource/docker/index.ts b/lib/datasource/docker/index.ts index 89d76e53ce8b10..0c4af2fbe75b7a 100644 --- a/lib/datasource/docker/index.ts +++ b/lib/datasource/docker/index.ts @@ -26,9 +26,7 @@ export const defaultVersioning = dockerVersioning.id; export const registryStrategy = 'first'; export const defaultConfig = { - additionalBranchPrefix: 'docker-', commitMessageTopic: '{{{depName}}} Docker tag', - major: { enabled: false }, commitMessageExtra: 'to v{{#if isMajor}}{{{newMajor}}}{{else}}{{{newVersion}}}{{/if}}', digest: { diff --git a/lib/datasource/galaxy-collection/index.spec.ts b/lib/datasource/galaxy-collection/index.spec.ts index b7583d605de991..32acd8d69a10a1 100644 --- a/lib/datasource/galaxy-collection/index.spec.ts +++ b/lib/datasource/galaxy-collection/index.spec.ts @@ -1,29 +1,28 @@ -import fs from 'fs'; import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { id as datasource } from '.'; -const communityKubernetesBase = fs.readFileSync( - 'lib/datasource/galaxy-collection/__fixtures__/community_kubernetes_base.json', - 'utf8' +const communityKubernetesBase = loadFixture( + __filename, + 'community_kubernetes_base.json' ); -const communityKubernetesVersions = fs.readFileSync( - 'lib/datasource/galaxy-collection/__fixtures__/community_kubernetes_versions.json', - 'utf8' +const communityKubernetesVersions = loadFixture( + __filename, + 'community_kubernetes_versions.json' ); -const communityKubernetesDetails121 = fs.readFileSync( - 'lib/datasource/galaxy-collection/__fixtures__/community_kubernetes_version_details_1.2.1.json', - 'utf8' +const communityKubernetesDetails121 = loadFixture( + __filename, + 'community_kubernetes_version_details_1.2.1.json' ); -const communityKubernetesDetails120 = fs.readFileSync( - 'lib/datasource/galaxy-collection/__fixtures__/community_kubernetes_version_details_1.2.0.json', - 'utf8' +const communityKubernetesDetails120 = loadFixture( + __filename, + 'community_kubernetes_version_details_1.2.0.json' ); -const communityKubernetesDetails0111 = fs.readFileSync( - 'lib/datasource/galaxy-collection/__fixtures__/community_kubernetes_version_details_0.11.1.json', - 'utf8' +const communityKubernetesDetails0111 = loadFixture( + __filename, + 'community_kubernetes_version_details_0.11.1.json' ); const baseUrl = 'https://galaxy.ansible.com'; diff --git a/lib/datasource/galaxy/index.spec.ts b/lib/datasource/galaxy/index.spec.ts index 6fb54511189fad..4786daa7281fa5 100644 --- a/lib/datasource/galaxy/index.spec.ts +++ b/lib/datasource/galaxy/index.spec.ts @@ -1,18 +1,11 @@ -import fs from 'fs'; import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { id as datasource } from '.'; -const res1 = fs.readFileSync( - 'lib/datasource/galaxy/__fixtures__/timezone', - 'utf8' -); -const empty = fs.readFileSync( - 'lib/datasource/galaxy/__fixtures__/empty', - 'utf8' -); +const res1 = loadFixture(__filename, 'timezone'); +const empty = loadFixture(__filename, 'empty'); const baseUrl = 'https://galaxy.ansible.com/'; diff --git a/lib/datasource/git-refs/index.spec.ts b/lib/datasource/git-refs/index.spec.ts index c60b8eb241bbe2..5e0dc5c31faac9 100644 --- a/lib/datasource/git-refs/index.spec.ts +++ b/lib/datasource/git-refs/index.spec.ts @@ -1,7 +1,6 @@ -import fs from 'fs-extra'; import _simpleGit from 'simple-git'; import { getPkgReleases } from '..'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { id as datasource, getDigest } from '.'; jest.mock('simple-git'); @@ -9,10 +8,7 @@ const simpleGit: any = _simpleGit; const depName = 'https://github.com/example/example.git'; -const lsRemote1 = fs.readFileSync( - 'lib/datasource/git-refs/__fixtures__/ls-remote-1.txt', - 'utf8' -); +const lsRemote1 = loadFixture(__filename, 'ls-remote-1.txt'); describe(getName(__filename), () => { describe('getReleases', () => { diff --git a/lib/datasource/git-tags/index.spec.ts b/lib/datasource/git-tags/index.spec.ts index c449c78d429562..d1309fa51d89c8 100644 --- a/lib/datasource/git-tags/index.spec.ts +++ b/lib/datasource/git-tags/index.spec.ts @@ -1,7 +1,6 @@ -import fs from 'fs-extra'; import _simpleGit from 'simple-git'; import { getPkgReleases } from '..'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { id as datasource, getDigest } from '.'; jest.mock('simple-git'); @@ -9,10 +8,7 @@ const simpleGit: any = _simpleGit; const depName = 'https://github.com/example/example.git'; -const lsRemote1 = fs.readFileSync( - 'lib/datasource/git-refs/__fixtures__/ls-remote-1.txt', - 'utf8' -); +const lsRemote1 = loadFixture(__filename, 'ls-remote-1.txt', '../git-refs'); describe(getName(__filename), () => { describe('getReleases', () => { diff --git a/lib/datasource/gradle-version/index.spec.ts b/lib/datasource/gradle-version/index.spec.ts index fc9ac0b290a3f8..dd527dc0e1396f 100644 --- a/lib/datasource/gradle-version/index.spec.ts +++ b/lib/datasource/gradle-version/index.spec.ts @@ -1,14 +1,11 @@ -import fs from 'fs'; import { GetPkgReleasesConfig, GetReleasesConfig, getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName, partial } from '../../../test/util'; +import { getName, loadJsonFixture, partial } from '../../../test/util'; import { ExternalHostError } from '../../types/errors/external-host-error'; import { id as versioning } from '../../versioning/gradle'; import { id as datasource, getReleases } from '.'; -const allResponse: any = fs.readFileSync( - 'lib/datasource/gradle-version/__fixtures__/all.json' -); +const allResponse: any = loadJsonFixture(__filename, 'all.json'); let config: GetPkgReleasesConfig; @@ -32,7 +29,7 @@ describe(getName(__filename), () => { httpMock .scope('https://services.gradle.org/') .get('/versions/all') - .reply(200, JSON.parse(allResponse)); + .reply(200, allResponse); const res = await getPkgReleases(config); expect(res).toMatchSnapshot(); expect(res).not.toBeNull(); @@ -44,10 +41,7 @@ describe(getName(__filename), () => { }); it('calls configured registryUrls', async () => { - httpMock - .scope('https://foo.bar') - .get('/') - .reply(200, JSON.parse(allResponse)); + httpMock.scope('https://foo.bar').get('/').reply(200, allResponse); httpMock .scope('http://baz.qux') diff --git a/lib/datasource/helm/index.spec.ts b/lib/datasource/helm/index.spec.ts index 5e572990251bee..37e9a119201c45 100644 --- a/lib/datasource/helm/index.spec.ts +++ b/lib/datasource/helm/index.spec.ts @@ -1,14 +1,10 @@ -import fs from 'fs'; import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { id as datasource } from '.'; // Truncated index.yaml file -const indexYaml = fs.readFileSync( - 'lib/datasource/helm/__fixtures__/index.yaml', - 'utf8' -); +const indexYaml = loadFixture(__filename, 'index.yaml'); describe(getName(__filename), () => { describe('getReleases', () => { diff --git a/lib/datasource/helm/index.ts b/lib/datasource/helm/index.ts index ea1105841ac2d0..af28e7caee5fbe 100644 --- a/lib/datasource/helm/index.ts +++ b/lib/datasource/helm/index.ts @@ -17,7 +17,6 @@ export const defaultRegistryUrls = ['https://charts.helm.sh/stable']; export const registryStrategy = 'first'; export const defaultConfig = { - additionalBranchPrefix: 'helm-', commitMessageTopic: 'Helm release {{depName}}', group: { commitMessageTopic: '{{{groupName}}} Helm releases', diff --git a/lib/datasource/hex/index.spec.ts b/lib/datasource/hex/index.spec.ts index 44f72778b8f92d..4357cf966fe18c 100644 --- a/lib/datasource/hex/index.spec.ts +++ b/lib/datasource/hex/index.spec.ts @@ -1,18 +1,13 @@ -import fs from 'fs'; import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadJsonFixture } from '../../../test/util'; import { EXTERNAL_HOST_ERROR } from '../../constants/error-messages'; import * as _hostRules from '../../util/host-rules'; import { id as datasource } from '.'; const hostRules: any = _hostRules; -let res1 = fs.readFileSync( - 'lib/datasource/hex/__fixtures__/certifi.json', - 'utf8' -); -res1 = JSON.parse(res1); +const res1 = loadJsonFixture(__filename, 'certifi.json'); jest.mock('../../util/host-rules'); diff --git a/lib/datasource/jenkins-plugins/index.spec.ts b/lib/datasource/jenkins-plugins/index.spec.ts index 8de09d668839ad..3943760e88860d 100644 --- a/lib/datasource/jenkins-plugins/index.spec.ts +++ b/lib/datasource/jenkins-plugins/index.spec.ts @@ -1,12 +1,19 @@ import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadJsonFixture } from '../../../test/util'; import * as versioning from '../../versioning/docker'; -import jenkinsPluginsVersions from './__fixtures__/plugin-versions.json'; -import jenkinsPluginsInfo from './__fixtures__/update-center.actual.json'; import { resetCache } from './get'; import * as jenkins from '.'; +const jenkinsPluginsVersions = loadJsonFixture( + __filename, + 'plugin-versions.json' +); +const jenkinsPluginsInfo = loadJsonFixture( + __filename, + 'update-center.actual.json' +); + describe(getName(__filename), () => { describe('getReleases', () => { const SKIP_CACHE = process.env.RENOVATE_SKIP_CACHE; diff --git a/lib/datasource/maven/index.spec.ts b/lib/datasource/maven/index.spec.ts index 9eb446dbf8816e..9a411bb8e26bad 100644 --- a/lib/datasource/maven/index.spec.ts +++ b/lib/datasource/maven/index.spec.ts @@ -1,8 +1,6 @@ -import fs from 'fs'; import nock from 'nock'; -import { resolve } from 'upath'; import { Release, getPkgReleases } from '..'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { EXTERNAL_HOST_ERROR } from '../../constants/error-messages'; import * as hostRules from '../../util/host-rules'; import * as mavenVersioning from '../../versioning/maven'; @@ -10,20 +8,14 @@ import { id as datasource } from '.'; const MYSQL_VERSIONS = ['6.0.5', '6.0.6', '8.0.7', '8.0.8', '8.0.9']; -const MYSQL_MAVEN_METADATA = fs.readFileSync( - resolve( - __dirname, - './__fixtures__/repo1.maven.org/maven2/mysql/mysql-connector-java/maven-metadata.xml' - ), - 'utf8' +const MYSQL_MAVEN_METADATA = loadFixture( + __filename, + 'repo1.maven.org/maven2/mysql/mysql-connector-java/maven-metadata.xml' ); -const MYSQL_MAVEN_MYSQL_POM = fs.readFileSync( - resolve( - __dirname, - './__fixtures__/repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.12/mysql-connector-java-8.0.12.pom' - ), - 'utf8' +const MYSQL_MAVEN_MYSQL_POM = loadFixture( + __filename, + 'repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.12/mysql-connector-java-8.0.12.pom' ); const config = { diff --git a/lib/datasource/npm/__snapshots__/index.spec.ts.snap b/lib/datasource/npm/__snapshots__/index.spec.ts.snap index 85d618101b79ab..847462a985443d 100644 --- a/lib/datasource/npm/__snapshots__/index.spec.ts.snap +++ b/lib/datasource/npm/__snapshots__/index.spec.ts.snap @@ -519,49 +519,10 @@ Array [ ] `; -exports[`datasource/npm/index should use NPM_TOKEN if provided 1`] = ` -Object { - "name": "@foobar/core", - "registryUrl": "https://registry.npmjs.org/", - "releases": Array [ - Object { - "releaseTimestamp": "2018-05-06T05:21:53.000Z", - "version": "0.0.1", - }, - Object { - "releaseTimestamp": "2018-05-07T05:21:53.000Z", - "version": "0.0.2", - }, - ], - "sourceDirectory": "src/a", - "sourceUrl": "https://github.com/renovateapp/dummy", - "tags": Object { - "latest": "0.0.1", - }, - "versions": Object {}, -} -`; - -exports[`datasource/npm/index should use NPM_TOKEN if provided 2`] = ` -Array [ - Object { - "headers": Object { - "accept": "application/json", - "accept-encoding": "gzip, deflate, br", - "authorization": "Bearer some-token", - "host": "registry.npmjs.org", - "user-agent": "https://github.com/renovatebot/renovate", - }, - "method": "GET", - "url": "https://registry.npmjs.org/@foobar%2Fcore", - }, -] -`; - exports[`datasource/npm/index should use default registry if missing from npmrc 1`] = ` Object { "name": "foobar", - "registryUrl": "https://registry.npmjs.org", + "registryUrl": "https://registry.npmjs.org/", "releases": Array [ Object { "releaseTimestamp": "2018-05-06T05:21:53.000Z", diff --git a/lib/datasource/npm/index.spec.ts b/lib/datasource/npm/index.spec.ts index a4979577cf60cb..d398428ebf8c67 100644 --- a/lib/datasource/npm/index.spec.ts +++ b/lib/datasource/npm/index.spec.ts @@ -15,7 +15,6 @@ const registryAuthToken: jest.Mock<_registryAuthToken.NpmCredentials> = _registr let npmResponse: any; describe(getName(__filename), () => { - delete process.env.NPM_TOKEN; beforeEach(() => { jest.resetAllMocks(); httpMock.setup(); @@ -269,21 +268,6 @@ describe(getName(__filename), () => { expect(httpMock.getTrace()).toMatchSnapshot(); }); - it('should use NPM_TOKEN if provided', async () => { - httpMock - .scope('https://registry.npmjs.org', { - reqheaders: { authorization: 'Bearer some-token' }, - }) - .get('/@foobar%2Fcore') - .reply(200, { ...npmResponse, name: '@foobar/core' }); - const oldToken = process.env.NPM_TOKEN; - process.env.NPM_TOKEN = 'some-token'; - const res = await getPkgReleases({ datasource, depName: '@foobar/core' }); - process.env.NPM_TOKEN = oldToken; - expect(res).toMatchSnapshot(); - expect(httpMock.getTrace()).toMatchSnapshot(); - }); - it('should use host rules by hostName if provided', async () => { hostRules.add({ hostType: 'npm', @@ -330,7 +314,7 @@ describe(getName(__filename), () => { setNpmrc(npmrcContent); setNpmrc(npmrcContent); setNpmrc(); - expect(getNpmrc()).toBeNull(); + expect(getNpmrc()).toEqual({}); }); it('should use default registry if missing from npmrc', async () => { @@ -375,7 +359,7 @@ describe(getName(__filename), () => { .reply(200, npmResponse); process.env.REGISTRY = 'https://registry.from-env.com'; process.env.RENOVATE_CACHE_NPM_MINUTES = '15'; - setAdminConfig({ trustLevel: 'high' }); + setAdminConfig({ exposeAllEnv: true }); // eslint-disable-next-line no-template-curly-in-string const npmrc = 'registry=${REGISTRY}'; const res = await getPkgReleases({ datasource, depName: 'foobar', npmrc }); @@ -384,7 +368,7 @@ describe(getName(__filename), () => { }); it('should throw error if necessary env var is not present', () => { - setAdminConfig({ trustLevel: 'high' }); + setAdminConfig({ exposeAllEnv: true }); // eslint-disable-next-line no-template-curly-in-string expect(() => setNpmrc('registry=${REGISTRY_MISSING}')).toThrow( Error('env-replace') diff --git a/lib/datasource/npm/npmrc.spec.ts b/lib/datasource/npm/npmrc.spec.ts index d340093435907f..ed44bfee821bb1 100644 --- a/lib/datasource/npm/npmrc.spec.ts +++ b/lib/datasource/npm/npmrc.spec.ts @@ -9,7 +9,6 @@ const sanitize = mocked(_sanitize); describe(getName(__filename), () => { beforeEach(() => { - delete process.env.NPM_TOKEN; setNpmrc(''); setAdminConfig(); jest.resetAllMocks(); @@ -39,7 +38,7 @@ describe(getName(__filename), () => { }); it('sanitize _authtoken with high trust', () => { - setAdminConfig({ trustLevel: 'high' }); + setAdminConfig({ exposeAllEnv: true }); process.env.TEST_TOKEN = 'test'; setNpmrc( // eslint-disable-next-line no-template-curly-in-string @@ -52,6 +51,6 @@ describe(getName(__filename), () => { it('ignores localhost', () => { setNpmrc(`registry=http://localhost`); expect(sanitize.add).toHaveBeenCalledTimes(0); - expect(getNpmrc()).toBeNull(); + expect(getNpmrc()).toEqual({}); }); }); diff --git a/lib/datasource/npm/npmrc.ts b/lib/datasource/npm/npmrc.ts index 673ce0eec5ebea..03698762d9c5ed 100644 --- a/lib/datasource/npm/npmrc.ts +++ b/lib/datasource/npm/npmrc.ts @@ -9,8 +9,8 @@ import type { OutgoingHttpHeaders } from '../../util/http/types'; import { maskToken } from '../../util/mask'; import { add } from '../../util/sanitize'; -let npmrc: Record | null = null; -let npmrcRaw: string; +let npmrc: Record = {}; +let npmrcRaw = ''; export type Npmrc = Record; @@ -61,13 +61,13 @@ export function setNpmrc(input?: string): void { npmrcRaw = input; logger.debug('Setting npmrc'); npmrc = ini.parse(input.replace(/\\n/g, '\n')); - const { trustLevel } = getAdminConfig(); + const { exposeAllEnv } = getAdminConfig(); for (const [key, val] of Object.entries(npmrc)) { - if (trustLevel !== 'high') { + if (!exposeAllEnv) { sanitize(key, val); } if ( - trustLevel !== 'high' && + !exposeAllEnv && key.endsWith('registry') && val && val.includes('localhost') @@ -80,7 +80,7 @@ export function setNpmrc(input?: string): void { return; } } - if (trustLevel !== 'high') { + if (!exposeAllEnv) { return; } for (const key of Object.keys(npmrc)) { @@ -89,8 +89,8 @@ export function setNpmrc(input?: string): void { } } else if (npmrc) { logger.debug('Resetting npmrc'); - npmrc = null; - npmrcRaw = null; + npmrc = {}; + npmrcRaw = ''; } } @@ -106,7 +106,7 @@ export function resolvePackage(packageName: string): PackageResolution { try { registryUrl = getRegistryUrl(scope, getNpmrc()); } catch (err) { - registryUrl = 'https://registry.npmjs.org'; + registryUrl = 'https://registry.npmjs.org/'; } const packageUrl = url.resolve( registryUrl, @@ -129,11 +129,6 @@ export function resolvePackage(packageName: string): PackageResolution { { token: maskToken(authInfo.token), npmName: packageName }, 'Using auth (via npmrc) for npm lookup' ); - } else if (process.env.NPM_TOKEN && process.env.NPM_TOKEN !== 'undefined') { - logger.warn( - 'Support for NPM_TOKEN in env will be dropped in the next major release' - ); - headers.authorization = `Bearer ${process.env.NPM_TOKEN}`; } return { headers, packageUrl, registryUrl }; } diff --git a/lib/datasource/nuget/index.spec.ts b/lib/datasource/nuget/index.spec.ts index c8ecb5a1da68d8..777089b4ec3f87 100644 --- a/lib/datasource/nuget/index.spec.ts +++ b/lib/datasource/nuget/index.spec.ts @@ -1,7 +1,6 @@ -import fs from 'fs'; import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import * as _hostRules from '../../util/host-rules'; import { id as versioning } from '../../versioning/nuget'; import { id as datasource, parseRegistryUrl } from '.'; @@ -10,81 +9,48 @@ const hostRules: any = _hostRules; jest.mock('../../util/host-rules'); -const pkgInfoV3FromNuget = fs.readFileSync( - 'lib/datasource/nuget/__fixtures__/nunit/v3_nuget_org.xml', - 'utf8' -); -const pkgListV3Registration = fs.readFileSync( - 'lib/datasource/nuget/__fixtures__/nunit/v3_registration.json', - 'utf8' +const pkgInfoV3FromNuget = loadFixture(__filename, 'nunit/v3_nuget_org.xml'); +const pkgListV3Registration = loadFixture( + __filename, + 'nunit/v3_registration.json' ); -const pkgListV2 = fs.readFileSync( - 'lib/datasource/nuget/__fixtures__/nunit/v2.xml', - 'utf8' -); -const pkgListV2NoGitHubProjectUrl = fs.readFileSync( - 'lib/datasource/nuget/__fixtures__/nunit/v2_noGitHubProjectUrl.xml', - 'utf8' -); -const pkgListV2NoRelease = fs.readFileSync( - 'lib/datasource/nuget/__fixtures__/nunit/v2_no_release.xml', - 'utf8' +const pkgListV2 = loadFixture(__filename, 'nunit/v2.xml'); +const pkgListV2NoGitHubProjectUrl = loadFixture( + __filename, + 'nunit/v2_noGitHubProjectUrl.xml' ); -const pkgListV2WithoutProjectUrl = fs.readFileSync( - 'lib/datasource/nuget/__fixtures__/nunit/v2_withoutProjectUrl.xml', - 'utf8' +const pkgListV2NoRelease = loadFixture(__filename, 'nunit/v2_no_release.xml'); +const pkgListV2WithoutProjectUrl = loadFixture( + __filename, + 'nunit/v2_withoutProjectUrl.xml' ); -const pkgListV2Page1of2 = fs.readFileSync( - 'lib/datasource/nuget/__fixtures__/nunit/v2_paginated_1.xml', - 'utf8' -); -const pkgListV2Page2of2 = fs.readFileSync( - 'lib/datasource/nuget/__fixtures__/nunit/v2_paginated_2.xml', - 'utf8' -); +const pkgListV2Page1of2 = loadFixture(__filename, 'nunit/v2_paginated_1.xml'); +const pkgListV2Page2of2 = loadFixture(__filename, 'nunit/v2_paginated_2.xml'); -const nugetIndexV3 = fs.readFileSync( - 'lib/datasource/nuget/__fixtures__/v3_index.json', - 'utf8' -); +const nugetIndexV3 = loadFixture(__filename, 'v3_index.json'); const nlogMocks = [ { url: '/v3/registration5-gz-semver2/nlog/index.json', - result: fs.readFileSync( - 'lib/datasource/nuget/__fixtures__/nlog/v3_registration.json', - 'utf8' - ), + result: loadFixture(__filename, 'nlog/v3_registration.json'), }, { url: '/v3/registration5-gz-semver2/nlog/page/1.0.0.505/4.4.0-beta5.json', - result: fs.readFileSync( - 'lib/datasource/nuget/__fixtures__/nlog/v3_catalog_1.json', - 'utf8' - ), + result: loadFixture(__filename, 'nlog/v3_catalog_1.json'), }, { url: '/v3/registration5-gz-semver2/nlog/page/4.4.0-beta6/4.6.0-rc2.json', - result: fs.readFileSync( - 'lib/datasource/nuget/__fixtures__/nlog/v3_catalog_2.json', - 'utf8' - ), + result: loadFixture(__filename, 'nlog/v3_catalog_2.json'), }, { url: '/v3/registration5-gz-semver2/nlog/page/4.6.0-rc3/5.0.0-beta11.json', - result: fs.readFileSync( - 'lib/datasource/nuget/__fixtures__/nlog/v3_catalog_3.json', - 'utf8' - ), + result: loadFixture(__filename, 'nlog/v3_catalog_3.json'), }, { url: '/v3-flatcontainer/nlog/4.7.3/nlog.nuspec', - result: fs.readFileSync( - 'lib/datasource/nuget/__fixtures__/nlog/nuspec.xml', - 'utf8' - ), + result: loadFixture(__filename, 'nlog/nuspec.xml'), }, ]; diff --git a/lib/datasource/packagist/index.spec.ts b/lib/datasource/packagist/index.spec.ts index 33132089277815..556339f47b8b59 100644 --- a/lib/datasource/packagist/index.spec.ts +++ b/lib/datasource/packagist/index.spec.ts @@ -1,7 +1,6 @@ -import fs from 'fs'; import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadJsonFixture } from '../../../test/util'; import * as _hostRules from '../../util/host-rules'; import * as composerVersioning from '../../versioning/composer'; import { id as versioning } from '../../versioning/loose'; @@ -11,15 +10,9 @@ jest.mock('../../util/host-rules'); const hostRules = _hostRules; -const includesJson: any = fs.readFileSync( - 'lib/datasource/packagist/__fixtures__/includes.json' -); -const beytJson: any = fs.readFileSync( - 'lib/datasource/packagist/__fixtures__/1beyt.json' -); -const mailchimpJson: any = fs.readFileSync( - 'lib/datasource/packagist/__fixtures__/mailchimp-api.json' -); +const includesJson: any = loadJsonFixture(__filename, 'includes.json'); +const beytJson: any = loadJsonFixture(__filename, '1beyt.json'); +const mailchimpJson: any = loadJsonFixture(__filename, 'mailchimp-api.json'); const baseUrl = 'https://packagist.org'; @@ -143,7 +136,7 @@ describe(getName(__filename), () => { .get('/packages.json') .reply(200, packagesJson) .get('/include/all$afbf74d51f31c7cbb5ff10304f9290bfb4f4e68b.json') - .reply(200, JSON.parse(includesJson)); + .reply(200, includesJson); const res = await getPkgReleases({ ...config, datasource, @@ -227,7 +220,7 @@ describe(getName(__filename), () => { .get( '/p/wpackagist-plugin/1beyt$b574a802b5bf20a58c0f027e73aea2a75d23a6f654afc298a8dc467331be316a.json' ) - .reply(200, JSON.parse(beytJson)); + .reply(200, beytJson); const res = await getPkgReleases({ ...config, datasource, @@ -269,10 +262,7 @@ describe(getName(__filename), () => { '/p/providers-2018-09$14346045d7a7261cb3a12a6b7a1a7c4151982530347b115e5e277d879cad1942.json' ) .reply(200, fileJson); - httpMock - .scope(baseUrl) - .get('/p/some/other.json') - .reply(200, JSON.parse(beytJson)); + httpMock.scope(baseUrl).get('/p/some/other.json').reply(200, beytJson); const res = await getPkgReleases({ ...config, datasource, @@ -304,7 +294,7 @@ describe(getName(__filename), () => { .get( '/p/wpackagist-plugin/1beyt$b574a802b5bf20a58c0f027e73aea2a75d23a6f654afc298a8dc467331be316a.json' ) - .reply(200, JSON.parse(beytJson)); + .reply(200, beytJson); const res = await getPkgReleases({ ...config, datasource, @@ -334,10 +324,7 @@ describe(getName(__filename), () => { .scope('https://composer.renovatebot.com') .get('/packages.json') .reply(200, packagesJson); - httpMock - .scope(baseUrl) - .get('/p/some/other.json') - .reply(200, JSON.parse(beytJson)); + httpMock.scope(baseUrl).get('/p/some/other.json').reply(200, beytJson); const res = await getPkgReleases({ ...config, datasource, @@ -351,7 +338,7 @@ describe(getName(__filename), () => { httpMock .scope(baseUrl) .get('/p/drewm/mailchimp-api.json') - .reply(200, JSON.parse(mailchimpJson)); + .reply(200, mailchimpJson); config.registryUrls = ['https://packagist.org']; expect( await getPkgReleases({ @@ -367,7 +354,7 @@ describe(getName(__filename), () => { httpMock .scope(baseUrl) .get('/p/drewm/mailchimp-api.json') - .reply(200, JSON.parse(mailchimpJson)); + .reply(200, mailchimpJson); config.registryUrls = []; expect( await getPkgReleases({ diff --git a/lib/datasource/pypi/index.spec.ts b/lib/datasource/pypi/index.spec.ts index 75c8c8efcc6b43..6a36bba660daa5 100644 --- a/lib/datasource/pypi/index.spec.ts +++ b/lib/datasource/pypi/index.spec.ts @@ -1,27 +1,20 @@ -import fs from 'fs'; import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import * as hostRules from '../../util/host-rules'; import { id as datasource } from '.'; -const res1: any = fs.readFileSync( - 'lib/datasource/pypi/__fixtures__/azure-cli-monitor.json' +const res1: any = loadFixture(__filename, 'azure-cli-monitor.json'); +const res2: any = loadFixture(__filename, 'azure-cli-monitor-updated.json'); +const htmlResponse = loadFixture(__filename, 'versions-html.html'); +const badResponse = loadFixture(__filename, 'versions-html-badfile.html'); +const dataRequiresPythonResponse = loadFixture( + __filename, + 'versions-html-data-requires-python.html' ); -const res2: any = fs.readFileSync( - 'lib/datasource/pypi/__fixtures__/azure-cli-monitor-updated.json' -); -const htmlResponse = fs.readFileSync( - 'lib/datasource/pypi/__fixtures__/versions-html.html' -); -const badResponse = fs.readFileSync( - 'lib/datasource/pypi/__fixtures__/versions-html-badfile.html' -); -const dataRequiresPythonResponse = fs.readFileSync( - 'lib/datasource/pypi/__fixtures__/versions-html-data-requires-python.html' -); -const mixedHyphensResponse = fs.readFileSync( - 'lib/datasource/pypi/__fixtures__/versions-html-mixed-hyphens.html' +const mixedHyphensResponse = loadFixture( + __filename, + 'versions-html-mixed-hyphens.html' ); const baseUrl = 'https://pypi.org/pypi'; diff --git a/lib/datasource/repology/index.spec.ts b/lib/datasource/repology/index.spec.ts index 1079805e3a709c..9323908ac1642f 100644 --- a/lib/datasource/repology/index.spec.ts +++ b/lib/datasource/repology/index.spec.ts @@ -1,7 +1,6 @@ -import fs from 'fs'; import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { EXTERNAL_HOST_ERROR } from '../../constants/error-messages'; import { id as versioning } from '../../versioning/loose'; import { RepologyPackage, id as datasource } from '.'; @@ -46,26 +45,11 @@ const mockResolverCall = ( } }; -const fixtureNginx = fs.readFileSync( - `${__dirname}/__fixtures__/nginx.json`, - 'utf8' -); -const fixtureGccDefaults = fs.readFileSync( - `${__dirname}/__fixtures__/gcc-defaults.json`, - 'utf8' -); -const fixtureGcc = fs.readFileSync( - `${__dirname}/__fixtures__/gcc.json`, - 'utf8' -); -const fixturePulseaudio = fs.readFileSync( - `${__dirname}/__fixtures__/pulseaudio.json`, - 'utf8' -); -const fixtureJdk = fs.readFileSync( - `${__dirname}/__fixtures__/openjdk.json`, - 'utf8' -); +const fixtureNginx = loadFixture(__filename, `nginx.json`); +const fixtureGccDefaults = loadFixture(__filename, `gcc-defaults.json`); +const fixtureGcc = loadFixture(__filename, `gcc.json`); +const fixturePulseaudio = loadFixture(__filename, `pulseaudio.json`); +const fixtureJdk = loadFixture(__filename, `openjdk.json`); describe(getName(__filename), () => { describe('getReleases', () => { diff --git a/lib/datasource/ruby-version/index.spec.ts b/lib/datasource/ruby-version/index.spec.ts index 759931897df364..2f95bcfa918996 100644 --- a/lib/datasource/ruby-version/index.spec.ts +++ b/lib/datasource/ruby-version/index.spec.ts @@ -1,13 +1,9 @@ -import fs from 'fs'; import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { id as datasource } from '.'; -const rubyReleasesHtml = fs.readFileSync( - 'lib/datasource/ruby-version/__fixtures__/releases.html', - 'utf8' -); +const rubyReleasesHtml = loadFixture(__filename, 'releases.html'); describe(getName(__filename), () => { describe('getReleases', () => { diff --git a/lib/datasource/rubygems/__fixtures__/rubygems-org.txt b/lib/datasource/rubygems/__fixtures__/rubygems-org.txt new file mode 100644 index 00000000000000..69564ff592b916 --- /dev/null +++ b/lib/datasource/rubygems/__fixtures__/rubygems-org.txt @@ -0,0 +1,18 @@ +created_at: 2017-03-27T04:38:13+00:00 +--- +- 1 05d0116933ba44b0b5d0ee19bfd35ccc +.cat 0.0.1 631fd60a806eaf5026c86fff3155c289 +0mq 0.1.0,0.1.1,0.1.2,0.2.0,0.2.1,0.3.0,0.4.0,0.4.1,0.5.0,0.5.1,0.5.2,0.5.3 6146193f8f7e944156b0b42ec37bad3e +0xffffff 0.0.1,0.1.0 0a4a9aeae24152cdb467be02f40482f9 +10to1-crack 0.1.1,0.1.2,0.1.3 e7218e76477e2137355d2e7ded094925 +1234567890_ 1.0,1.1 233e818c2db65d2dad9f9ea9a27b1a30 +12_hour_time 0.0.2,0.0.3,0.0.4 4e58bc03e301f704950410b713c20b69 +16watts-fluently 0.3.0,0.3.1 555088e2b18e97e0293cab1d90dbb0d2 +189seg 0.0.1 c4d329f7d3eb88b6e602358968be0242 +196demo 0.0.0 e00c558565f7b03a438fbd93d854b7de +1_as_identity_function 1.0.0,1.0.1 bee2f0fbbc3c5c83008c0b8fc64cb168 +1and1 1.1 1853e4495b036ddc5da2035523d48f0d +1hdoc 0.1.3,0.2.0,0.2.2,0.2.3,0.2.4 7076f29c196df12047a3700c4d6e5915 +1pass 0.1.0,0.1.1,0.1.2 d209547aae4b8f3d67123f18f738ac99 +1pass -0.1.2 abcdef +21-day-challenge-countdown 0.1.0,0.1.1,0.1.2 57e8873fe713063f4e54e85bbbd709bb diff --git a/lib/datasource/rubygems/index.spec.ts b/lib/datasource/rubygems/index.spec.ts index 29c849d9f289c3..92df66b559aba3 100644 --- a/lib/datasource/rubygems/index.spec.ts +++ b/lib/datasource/rubygems/index.spec.ts @@ -1,30 +1,13 @@ import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadFixture, loadJsonFixture } from '../../../test/util'; import * as rubyVersioning from '../../versioning/ruby'; -import railsInfo from './__fixtures__/rails/info.json'; -import railsVersions from './__fixtures__/rails/versions.json'; import { resetCache } from './get-rubygems-org'; import * as rubygems from '.'; -const rubygemsOrgVersions = `created_at: 2017-03-27T04:38:13+00:00 ---- -- 1 05d0116933ba44b0b5d0ee19bfd35ccc -.cat 0.0.1 631fd60a806eaf5026c86fff3155c289 -0mq 0.1.0,0.1.1,0.1.2,0.2.0,0.2.1,0.3.0,0.4.0,0.4.1,0.5.0,0.5.1,0.5.2,0.5.3 6146193f8f7e944156b0b42ec37bad3e -0xffffff 0.0.1,0.1.0 0a4a9aeae24152cdb467be02f40482f9 -10to1-crack 0.1.1,0.1.2,0.1.3 e7218e76477e2137355d2e7ded094925 -1234567890_ 1.0,1.1 233e818c2db65d2dad9f9ea9a27b1a30 -12_hour_time 0.0.2,0.0.3,0.0.4 4e58bc03e301f704950410b713c20b69 -16watts-fluently 0.3.0,0.3.1 555088e2b18e97e0293cab1d90dbb0d2 -189seg 0.0.1 c4d329f7d3eb88b6e602358968be0242 -196demo 0.0.0 e00c558565f7b03a438fbd93d854b7de -1_as_identity_function 1.0.0,1.0.1 bee2f0fbbc3c5c83008c0b8fc64cb168 -1and1 1.1 1853e4495b036ddc5da2035523d48f0d -1hdoc 0.1.3,0.2.0,0.2.2,0.2.3,0.2.4 7076f29c196df12047a3700c4d6e5915 -1pass 0.1.0,0.1.1,0.1.2 d209547aae4b8f3d67123f18f738ac99 -1pass -0.1.2 abcdef -21-day-challenge-countdown 0.1.0,0.1.1,0.1.2 57e8873fe713063f4e54e85bbbd709bb`; +const rubygemsOrgVersions = loadFixture(__filename, 'rubygems-org.txt'); +const railsInfo = loadJsonFixture(__filename, 'rails/info.json'); +const railsVersions = loadJsonFixture(__filename, 'rails/versions.json'); describe(getName(__filename), () => { describe('getReleases', () => { diff --git a/lib/datasource/sbt-package/index.spec.ts b/lib/datasource/sbt-package/index.spec.ts index ba30b93ad56bfd..2616a41293cae8 100644 --- a/lib/datasource/sbt-package/index.spec.ts +++ b/lib/datasource/sbt-package/index.spec.ts @@ -1,22 +1,13 @@ -import fs from 'fs'; import nock from 'nock'; -import upath from 'upath'; import { getPkgReleases } from '..'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import * as mavenVersioning from '../../versioning/maven'; import { MAVEN_REPO } from '../maven/common'; import { parseIndexDir } from '../sbt-plugin/util'; import * as sbtPlugin from '.'; -const mavenIndexHtml = fs.readFileSync( - upath.resolve(__dirname, `./__fixtures__/maven-index.html`), - 'utf8' -); - -const sbtPluginIndex = fs.readFileSync( - upath.resolve(__dirname, `./__fixtures__/sbt-plugins-index.html`), - 'utf8' -); +const mavenIndexHtml = loadFixture(__filename, `maven-index.html`); +const sbtPluginIndex = loadFixture(__filename, `sbt-plugins-index.html`); describe(getName(__filename), () => { it('parses Maven index directory', () => { diff --git a/lib/datasource/sbt-plugin/index.spec.ts b/lib/datasource/sbt-plugin/index.spec.ts index ab8cd3e9f7cc07..b8228ab50091c8 100644 --- a/lib/datasource/sbt-plugin/index.spec.ts +++ b/lib/datasource/sbt-plugin/index.spec.ts @@ -1,22 +1,13 @@ -import fs from 'fs'; import nock from 'nock'; -import upath from 'upath'; import { getPkgReleases } from '..'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import * as mavenVersioning from '../../versioning/maven'; import { MAVEN_REPO } from '../maven/common'; import { parseIndexDir } from './util'; import * as sbtPlugin from '.'; -const mavenIndexHtml = fs.readFileSync( - upath.resolve(__dirname, `./__fixtures__/maven-index.html`), - 'utf8' -); - -const sbtPluginIndex = fs.readFileSync( - upath.resolve(__dirname, `./__fixtures__/sbt-plugins-index.html`), - 'utf8' -); +const mavenIndexHtml = loadFixture(__filename, `maven-index.html`); +const sbtPluginIndex = loadFixture(__filename, `sbt-plugins-index.html`); describe(getName(__filename), () => { it('parses Maven index directory', () => { diff --git a/lib/datasource/terraform-module/index.spec.ts b/lib/datasource/terraform-module/index.spec.ts index d7d1d0b7abac6d..2d08c2dd29677e 100644 --- a/lib/datasource/terraform-module/index.spec.ts +++ b/lib/datasource/terraform-module/index.spec.ts @@ -1,17 +1,16 @@ -import fs from 'fs'; import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { id as datasource } from '.'; -const consulData: any = fs.readFileSync( - 'lib/datasource/terraform-module/__fixtures__/registry-consul.json' +const consulData: any = loadFixture(__filename, 'registry-consul.json'); +const serviceDiscoveryResult: any = loadFixture( + __filename, + 'service-discovery.json' ); -const serviceDiscoveryResult: any = fs.readFileSync( - 'lib/datasource/terraform-module/__fixtures__/service-discovery.json' -); -const serviceDiscoveryCustomResult: any = fs.readFileSync( - 'lib/datasource/terraform-module/__fixtures__/service-custom-discovery.json' +const serviceDiscoveryCustomResult: any = loadFixture( + __filename, + 'service-custom-discovery.json' ); const baseUrl = 'https://registry.terraform.io'; diff --git a/lib/datasource/terraform-provider/index.spec.ts b/lib/datasource/terraform-provider/index.spec.ts index c7725e2c744573..44dfa44b294f2e 100644 --- a/lib/datasource/terraform-provider/index.spec.ts +++ b/lib/datasource/terraform-provider/index.spec.ts @@ -1,17 +1,16 @@ -import fs from 'fs'; import { getPkgReleases } from '..'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { id as datasource, defaultRegistryUrls } from '.'; -const consulData: any = fs.readFileSync( - 'lib/datasource/terraform-provider/__fixtures__/azurerm-provider.json' +const consulData: any = loadFixture(__filename, 'azurerm-provider.json'); +const hashicorpReleases: any = loadFixture( + __filename, + 'releaseBackendIndex.json' ); -const hashicorpReleases: any = fs.readFileSync( - 'lib/datasource/terraform-provider/__fixtures__/releaseBackendIndex.json' -); -const serviceDiscoveryResult: any = fs.readFileSync( - 'lib/datasource/terraform-module/__fixtures__/service-discovery.json' +const serviceDiscoveryResult: any = loadFixture( + __filename, + 'service-discovery.json' ); const primaryUrl = defaultRegistryUrls[0]; diff --git a/lib/manager/ansible-galaxy/extract.spec.ts b/lib/manager/ansible-galaxy/extract.spec.ts index b4f68b6f10abc8..dd3593801e3754 100644 --- a/lib/manager/ansible-galaxy/extract.spec.ts +++ b/lib/manager/ansible-galaxy/extract.spec.ts @@ -1,31 +1,12 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import extractPackageFile, { getSliceEndNumber } from './extract'; -const yamlFile1 = readFileSync( - 'lib/manager/ansible-galaxy/__fixtures__/requirements01.yml', - 'utf8' -); -const yamlFile2 = readFileSync( - 'lib/manager/ansible-galaxy/__fixtures__/requirements02.yml', - 'utf8' -); -const helmRequirements = readFileSync( - 'lib/manager/ansible-galaxy/__fixtures__/helmRequirements.yml', - 'utf8' -); -const collections1 = readFileSync( - 'lib/manager/ansible-galaxy/__fixtures__/collections1.yml', - 'utf8' -); -const collections2 = readFileSync( - 'lib/manager/ansible-galaxy/__fixtures__/collections2.yml', - 'utf8' -); -const galaxy = readFileSync( - 'lib/manager/ansible-galaxy/__fixtures__/galaxy.yml', - 'utf8' -); +const yamlFile1 = loadFixture(__filename, 'requirements01.yml'); +const yamlFile2 = loadFixture(__filename, 'requirements02.yml'); +const helmRequirements = loadFixture(__filename, 'helmRequirements.yml'); +const collections1 = loadFixture(__filename, 'collections1.yml'); +const collections2 = loadFixture(__filename, 'collections2.yml'); +const galaxy = loadFixture(__filename, 'galaxy.yml'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/ansible/extract.spec.ts b/lib/manager/ansible/extract.spec.ts index 8b96d583d5fe98..3e068cf4062230 100644 --- a/lib/manager/ansible/extract.spec.ts +++ b/lib/manager/ansible/extract.spec.ts @@ -1,15 +1,8 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import extractPackageFile from './extract'; -const yamlFile1 = readFileSync( - 'lib/manager/ansible/__fixtures__/main1.yaml', - 'utf8' -); -const yamlFile2 = readFileSync( - 'lib/manager/ansible/__fixtures__/main2.yaml', - 'utf8' -); +const yamlFile1 = loadFixture(__filename, 'main1.yaml'); +const yamlFile2 = loadFixture(__filename, 'main2.yaml'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/azure-pipelines/extract.spec.ts b/lib/manager/azure-pipelines/extract.spec.ts index 5ac96ae7ecf416..72dd4fcfad25d8 100644 --- a/lib/manager/azure-pipelines/extract.spec.ts +++ b/lib/manager/azure-pipelines/extract.spec.ts @@ -1,5 +1,4 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractContainer, extractPackageFile, @@ -7,19 +6,16 @@ import { parseAzurePipelines, } from './extract'; -const azurePipelines = readFileSync( - 'lib/manager/azure-pipelines/__fixtures__/azure-pipelines.yaml', - 'utf8' -); +const azurePipelines = loadFixture(__filename, 'azure-pipelines.yaml'); -const azurePipelinesInvalid = readFileSync( - 'lib/manager/azure-pipelines/__fixtures__/azure-pipelines-invalid.yaml', - 'utf8' +const azurePipelinesInvalid = loadFixture( + __filename, + 'azure-pipelines-invalid.yaml' ); -const azurePipelinesNoDependency = readFileSync( - 'lib/manager/azure-pipelines/__fixtures__/azure-pipelines-no-dependency.yaml', - 'utf8' +const azurePipelinesNoDependency = loadFixture( + __filename, + 'azure-pipelines-no-dependency.yaml' ); describe(getName(__filename), () => { diff --git a/lib/manager/batect-wrapper/extract.spec.ts b/lib/manager/batect-wrapper/extract.spec.ts index fe854eb3692511..06393f3cd2f7e5 100644 --- a/lib/manager/batect-wrapper/extract.spec.ts +++ b/lib/manager/batect-wrapper/extract.spec.ts @@ -1,19 +1,11 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { id as githubReleaseDatasource } from '../../datasource/github-releases'; import { id as semverVersioning } from '../../versioning/semver'; import type { PackageDependency } from '../types'; import { extractPackageFile } from './extract'; -const validWrapperContent = readFileSync( - 'lib/manager/batect-wrapper/__fixtures__/valid-wrapper', - 'utf8' -); - -const malformedWrapperContent = readFileSync( - 'lib/manager/batect-wrapper/__fixtures__/malformed-wrapper', - 'utf8' -); +const validWrapperContent = loadFixture(__filename, 'valid-wrapper'); +const malformedWrapperContent = loadFixture(__filename, 'malformed-wrapper'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/bazel/extract.spec.ts b/lib/manager/bazel/extract.spec.ts index 23523f8359ca0f..be6a208c17bbfd 100644 --- a/lib/manager/bazel/extract.spec.ts +++ b/lib/manager/bazel/extract.spec.ts @@ -1,26 +1,10 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const workspaceFile = readFileSync( - 'lib/manager/bazel/__fixtures__/WORKSPACE1', - 'utf8' -); - -const workspace2File = readFileSync( - 'lib/manager/bazel/__fixtures__/WORKSPACE2', - 'utf8' -); - -const workspace3File = readFileSync( - 'lib/manager/bazel/__fixtures__/WORKSPACE3', - 'utf8' -); - -const fileWithBzlExtension = readFileSync( - 'lib/manager/bazel/__fixtures__/repositories.bzl', - 'utf8' -); +const workspaceFile = loadFixture(__filename, 'WORKSPACE1'); +const workspace2File = loadFixture(__filename, 'WORKSPACE2'); +const workspace3File = loadFixture(__filename, 'WORKSPACE3'); +const fileWithBzlExtension = loadFixture(__filename, 'repositories.bzl'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/bazel/extract.ts b/lib/manager/bazel/extract.ts index 874a6625b95863..331453e329941e 100644 --- a/lib/manager/bazel/extract.ts +++ b/lib/manager/bazel/extract.ts @@ -53,7 +53,7 @@ function parseUrl(urlString: string): UrlParsedResult | null { return null; } -const dummyLexer = { +const lexer = moo.states({ main: { lineComment: { match: /#.*?$/ }, leftParen: { match: '(' }, @@ -103,11 +103,11 @@ const dummyLexer = { stringFinish: { match: "'", pop: 1 }, char: { match: /[^]/, lineBreaks: true }, }, -}; +}); function parseContent(content: string): string[] { - const lexer = moo.states(dummyLexer); lexer.reset(content); + let balance = 0; let def: null | string = null; diff --git a/lib/manager/bazel/update.spec.ts b/lib/manager/bazel/update.spec.ts index 41d5fadef24fb0..db2b6bc82a6009 100644 --- a/lib/manager/bazel/update.spec.ts +++ b/lib/manager/bazel/update.spec.ts @@ -1,25 +1,12 @@ -import { readFileSync } from 'fs'; import { Readable } from 'stream'; -import { resolve } from 'upath'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import type { UpdateType } from '../../config/types'; import { updateDependency } from './update'; -const content = readFileSync( - resolve('lib/manager/bazel/__fixtures__/WORKSPACE1'), - 'utf8' -); - -const contentContainerPull = readFileSync( - resolve('lib/manager/bazel/__fixtures__/container_pull'), - 'utf8' -); - -const fileWithBzlExtension = readFileSync( - 'lib/manager/bazel/__fixtures__/repositories.bzl', - 'utf8' -); +const content = loadFixture(__filename, 'WORKSPACE1'); +const contentContainerPull = loadFixture(__filename, 'container_pull'); +const fileWithBzlExtension = loadFixture(__filename, 'repositories.bzl'); /* git_repository( diff --git a/lib/manager/buildkite/extract.spec.ts b/lib/manager/buildkite/extract.spec.ts index 3d9704d1733425..911da7d3c9bf3a 100644 --- a/lib/manager/buildkite/extract.spec.ts +++ b/lib/manager/buildkite/extract.spec.ts @@ -1,23 +1,10 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const pipeline1 = readFileSync( - 'lib/manager/buildkite/__fixtures__/pipeline1.yml', - 'utf8' -); -const pipeline2 = readFileSync( - 'lib/manager/buildkite/__fixtures__/pipeline2.yml', - 'utf8' -); -const pipeline3 = readFileSync( - 'lib/manager/buildkite/__fixtures__/pipeline3.yml', - 'utf8' -); -const pipeline4 = readFileSync( - 'lib/manager/buildkite/__fixtures__/pipeline4.yml', - 'utf8' -); +const pipeline1 = loadFixture(__filename, 'pipeline1.yml'); +const pipeline2 = loadFixture(__filename, 'pipeline2.yml'); +const pipeline3 = loadFixture(__filename, 'pipeline3.yml'); +const pipeline4 = loadFixture(__filename, 'pipeline4.yml'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/buildkite/index.ts b/lib/manager/buildkite/index.ts index a97b1018ed28c4..d678d7fd3c206d 100644 --- a/lib/manager/buildkite/index.ts +++ b/lib/manager/buildkite/index.ts @@ -7,5 +7,4 @@ export const defaultConfig = { commitMessageTopic: 'buildkite plugin {{depName}}', commitMessageExtra: 'to {{#if isMajor}}v{{{newMajor}}}{{else}}{{{newValue}}}{{/if}}', - additionalBranchPrefix: 'buildkite-', }; diff --git a/lib/manager/bundler/extract.spec.ts b/lib/manager/bundler/extract.spec.ts index a70326a8cf8503..baefc8e48a5df9 100644 --- a/lib/manager/bundler/extract.spec.ts +++ b/lib/manager/bundler/extract.spec.ts @@ -1,67 +1,33 @@ -import { readFileSync } from 'fs'; -import { fs, getName } from '../../../test/util'; +import { fs, getName, loadFixture } from '../../../test/util'; import { isValid } from '../../versioning/ruby'; import { extractPackageFile } from './extract'; jest.mock('../../util/fs'); -const railsGemfile = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.rails', - 'utf8' -); -const railsGemfileLock = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.rails.lock', - 'utf8' -); +const railsGemfile = loadFixture(__filename, 'Gemfile.rails'); +const railsGemfileLock = loadFixture(__filename, 'Gemfile.rails.lock'); -const sourceGroupGemfile = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.sourceGroup', - 'utf8' -); -const webPackerGemfile = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.webpacker', - 'utf8' -); -const webPackerGemfileLock = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.webpacker.lock', - 'utf8' -); -const mastodonGemfile = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.mastodon', - 'utf8' -); -const mastodonGemfileLock = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.mastodon.lock', - 'utf8' -); -const rubyCIGemfileLock = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.rubyci.lock', - 'utf8' -); +const sourceGroupGemfile = loadFixture(__filename, 'Gemfile.sourceGroup'); +const webPackerGemfile = loadFixture(__filename, 'Gemfile.webpacker'); +const webPackerGemfileLock = loadFixture(__filename, 'Gemfile.webpacker.lock'); +const mastodonGemfile = loadFixture(__filename, 'Gemfile.mastodon'); +const mastodonGemfileLock = loadFixture(__filename, 'Gemfile.mastodon.lock'); +const rubyCIGemfileLock = loadFixture(__filename, 'Gemfile.rubyci.lock'); -const rubyCIGemfile = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.rubyci', - 'utf8' -); -const gitlabFossGemfileLock = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.gitlab-foss.lock', - 'utf8' -); -const gitlabFossGemfile = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.gitlab-foss', - 'utf8' -); -const sourceBlockGemfile = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.sourceBlock', - 'utf8' +const rubyCIGemfile = loadFixture(__filename, 'Gemfile.rubyci'); +const gitlabFossGemfileLock = loadFixture( + __filename, + 'Gemfile.gitlab-foss.lock' ); -const sourceBlockWithNewLinesGemfileLock = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.sourceBlockWithNewLines.lock', - 'utf8' +const gitlabFossGemfile = loadFixture(__filename, 'Gemfile.gitlab-foss'); +const sourceBlockGemfile = loadFixture(__filename, 'Gemfile.sourceBlock'); +const sourceBlockWithNewLinesGemfileLock = loadFixture( + __filename, + 'Gemfile.sourceBlockWithNewLines.lock' ); -const sourceBlockWithNewLinesGemfile = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.sourceBlockWithNewLines', - 'utf8' +const sourceBlockWithNewLinesGemfile = loadFixture( + __filename, + 'Gemfile.sourceBlockWithNewLines' ); function validateGems(raw, parsed) { diff --git a/lib/manager/bundler/gemfile.spec.ts b/lib/manager/bundler/gemfile.spec.ts index cee947b8a84b7f..a066c10e2f6017 100644 --- a/lib/manager/bundler/gemfile.spec.ts +++ b/lib/manager/bundler/gemfile.spec.ts @@ -1,10 +1,8 @@ -import { readFileSync } from 'fs'; +import { loadFixture } from '../../../test/util'; import { extractLockFileEntries } from './locked-version'; -const gemLockFile = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.rails.lock', - 'utf8' -); +const gemLockFile = loadFixture(__filename, 'Gemfile.rails.lock'); + describe('extract lib/manager/bundler/gemfile.rails.lock', () => { it('matches the expected output', () => { expect(extractLockFileEntries(gemLockFile)).toMatchSnapshot(); diff --git a/lib/manager/bundler/locked-version.spec.ts b/lib/manager/bundler/locked-version.spec.ts index 6670a10aa49115..6401691b7bb25f 100644 --- a/lib/manager/bundler/locked-version.spec.ts +++ b/lib/manager/bundler/locked-version.spec.ts @@ -1,26 +1,15 @@ -import { readFileSync } from 'fs'; +import { loadFixture } from '../../../test/util'; import { extractLockFileEntries } from './locked-version'; -const railsGemfileLock = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.rails.lock', - 'utf8' -); -const webPackerGemfileLock = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.webpacker.lock', - 'utf8' -); -const mastodonGemfileLock = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.mastodon.lock', - 'utf8' -); -const rubyCIGemfileLock = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.rubyci.lock', - 'utf8' -); -const gitlabFossGemfileLock = readFileSync( - 'lib/manager/bundler/__fixtures__/Gemfile.gitlab-foss.lock', - 'utf8' +const railsGemfileLock = loadFixture(__filename, 'Gemfile.rails.lock'); +const webPackerGemfileLock = loadFixture(__filename, 'Gemfile.webpacker.lock'); +const mastodonGemfileLock = loadFixture(__filename, 'Gemfile.mastodon.lock'); +const rubyCIGemfileLock = loadFixture(__filename, 'Gemfile.rubyci.lock'); +const gitlabFossGemfileLock = loadFixture( + __filename, + 'Gemfile.gitlab-foss.lock' ); + describe('/lib/manager/bundler/locked-version', () => { test('Parse Rails Gem Lock File', () => { const parsedLockEntries = extractLockFileEntries(railsGemfileLock); diff --git a/lib/manager/cake/__fixtures__/build.cake b/lib/manager/cake/__fixtures__/build.cake index 4cdbf4d0496313..f3d942b91997e7 100644 --- a/lib/manager/cake/__fixtures__/build.cake +++ b/lib/manager/cake/__fixtures__/build.cake @@ -1,5 +1,6 @@ foo #addin nuget:?package=Foo.Foo&version=1.1.1 +#addin "nuget:?package=Bim.Bim&version=6.6.6" #tool nuget:https://example.com?package=Bar.Bar&version=2.2.2 #module nuget:file:///tmp/?package=Baz.Baz&version=3.3.3 // #module nuget:?package=Qux.Qux&version=4.4.4 diff --git a/lib/manager/cake/__snapshots__/index.spec.ts.snap b/lib/manager/cake/__snapshots__/index.spec.ts.snap index a6e389b1fc832f..8df0548df51e2a 100644 --- a/lib/manager/cake/__snapshots__/index.spec.ts.snap +++ b/lib/manager/cake/__snapshots__/index.spec.ts.snap @@ -8,6 +8,11 @@ Object { "datasource": "nuget", "depName": "Foo.Foo", }, + Object { + "currentValue": "6.6.6", + "datasource": "nuget", + "depName": "Bim.Bim", + }, Object { "currentValue": "2.2.2", "datasource": "nuget", diff --git a/lib/manager/cake/index.spec.ts b/lib/manager/cake/index.spec.ts index c354776c5e0c94..eae570413174cd 100644 --- a/lib/manager/cake/index.spec.ts +++ b/lib/manager/cake/index.spec.ts @@ -1,11 +1,7 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from '.'; -const content = readFileSync( - 'lib/manager/cake/__fixtures__/build.cake', - 'utf8' -); +const content = loadFixture(__filename, 'build.cake'); describe(getName(__filename), () => { it('extracts', () => { diff --git a/lib/manager/cake/index.ts b/lib/manager/cake/index.ts index 60cb08b985172d..50d04007f97a92 100644 --- a/lib/manager/cake/index.ts +++ b/lib/manager/cake/index.ts @@ -10,22 +10,27 @@ export const defaultConfig = { fileMatch: ['\\.cake$'], }; -const lexerStates = { +const lexer = moo.states({ main: { lineComment: { match: /\/\/.*?$/ }, multiLineComment: { match: /\/\*[^]*?\*\//, lineBreaks: true }, dependency: { match: /^#(?:addin|tool|module)\s+(?:nuget|dotnet):.*$/, }, + dependencyQuoted: { + match: /^#(?:addin|tool|module)\s+"(?:nuget|dotnet):[^"]+"\s*$/, + value: (s: string) => s.trim().slice(1, -1), + }, unknown: { match: /[^]/, lineBreaks: true }, }, -}; +}); function parseDependencyLine(line: string): PackageDependency | null { try { let url = line.replace(/^[^:]*:/, ''); const isEmptyHost = url.startsWith('?'); url = isEmptyHost ? `http://localhost/${url}` : url; + const { origin: registryUrl, protocol, searchParams } = new URL(url); const depName = searchParams.get('package'); @@ -49,12 +54,11 @@ function parseDependencyLine(line: string): PackageDependency | null { export function extractPackageFile(content: string): PackageFile { const deps = []; - const lexer = moo.states(lexerStates); lexer.reset(content); let token = lexer.next(); while (token) { const { type, value } = token; - if (type === 'dependency') { + if (type === 'dependency' || type === 'dependencyQuoted') { const dep = parseDependencyLine(value); if (dep) { deps.push(dep); diff --git a/lib/manager/cargo/extract.spec.ts b/lib/manager/cargo/extract.spec.ts index cfaf0d624c9d33..761785d8031a7f 100644 --- a/lib/manager/cargo/extract.spec.ts +++ b/lib/manager/cargo/extract.spec.ts @@ -1,39 +1,16 @@ -import { readFileSync } from 'fs'; import { dir } from 'tmp-promise'; import { join } from 'upath'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { setFsConfig, writeLocalFile } from '../../util/fs'; import { extractPackageFile } from './extract'; -const cargo1toml = readFileSync( - 'lib/manager/cargo/__fixtures__/Cargo.1.toml', - 'utf8' -); -const cargo2toml = readFileSync( - 'lib/manager/cargo/__fixtures__/Cargo.2.toml', - 'utf8' -); -const cargo3toml = readFileSync( - 'lib/manager/cargo/__fixtures__/Cargo.3.toml', - 'utf8' -); -const cargo4toml = readFileSync( - 'lib/manager/cargo/__fixtures__/Cargo.4.toml', - 'utf8' -); -const cargo5toml = readFileSync( - 'lib/manager/cargo/__fixtures__/Cargo.5.toml', - 'utf8' -); - -const cargo6configtoml = readFileSync( - 'lib/manager/cargo/__fixtures__/cargo.6.config.toml', - 'utf8' -); -const cargo6toml = readFileSync( - 'lib/manager/cargo/__fixtures__/Cargo.6.toml', - 'utf8' -); +const cargo1toml = loadFixture(__filename, 'Cargo.1.toml'); +const cargo2toml = loadFixture(__filename, 'Cargo.2.toml'); +const cargo3toml = loadFixture(__filename, 'Cargo.3.toml'); +const cargo4toml = loadFixture(__filename, 'Cargo.4.toml'); +const cargo5toml = loadFixture(__filename, 'Cargo.5.toml'); +const cargo6configtoml = loadFixture(__filename, 'cargo.6.config.toml'); +const cargo6toml = loadFixture(__filename, 'Cargo.6.toml'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/cargo/index.ts b/lib/manager/cargo/index.ts index e18f8527d5244c..e91db57470e3be 100644 --- a/lib/manager/cargo/index.ts +++ b/lib/manager/cargo/index.ts @@ -10,7 +10,6 @@ export { extractPackageFile, updateArtifacts, language }; export const defaultConfig = { commitMessageTopic: 'Rust crate {{depName}}', - additionalBranchPrefix: 'rust-', fileMatch: ['(^|/)Cargo.toml$'], versioning: cargoVersioning.id, rangeStrategy: 'bump', diff --git a/lib/manager/cdnurl/extract.spec.ts b/lib/manager/cdnurl/extract.spec.ts index 0a01f316df7612..7d03a1539fed13 100644 --- a/lib/manager/cdnurl/extract.spec.ts +++ b/lib/manager/cdnurl/extract.spec.ts @@ -1,12 +1,7 @@ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from '.'; -const input = readFileSync( - resolve(__dirname, `./__fixtures__/sample.txt`), - 'utf8' -); +const input = loadFixture(__filename, `sample.txt`); describe(getName(__filename), () => { it('extractPackageFile', () => { diff --git a/lib/manager/circleci/__snapshots__/extract.spec.ts.snap b/lib/manager/circleci/__snapshots__/extract.spec.ts.snap index 099414ce7920f5..e6ff11b229c9b1 100644 --- a/lib/manager/circleci/__snapshots__/extract.spec.ts.snap +++ b/lib/manager/circleci/__snapshots__/extract.spec.ts.snap @@ -4,7 +4,6 @@ exports[`manager/circleci/extract extractPackageFile() extracts image without le Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "14.8.0", "datasource": "docker", @@ -20,7 +19,6 @@ exports[`manager/circleci/extract extractPackageFile() extracts multiple image l Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": undefined, "datasource": "docker", @@ -31,7 +29,6 @@ Array [ }, Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "4", "datasource": "docker", @@ -42,7 +39,6 @@ Array [ }, Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "6", "datasource": "docker", @@ -53,7 +49,6 @@ Array [ }, Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "8.9.0", "datasource": "docker", diff --git a/lib/manager/circleci/extract.spec.ts b/lib/manager/circleci/extract.spec.ts index fc25189c5871b3..dc31c4a5a59b5c 100644 --- a/lib/manager/circleci/extract.spec.ts +++ b/lib/manager/circleci/extract.spec.ts @@ -1,19 +1,9 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const file1 = readFileSync( - 'lib/manager/circleci/__fixtures__/config.yml', - 'utf8' -); -const file2 = readFileSync( - 'lib/manager/circleci/__fixtures__/config2.yml', - 'utf8' -); -const file3 = readFileSync( - 'lib/manager/circleci/__fixtures__/config3.yml', - 'utf8' -); +const file1 = loadFixture(__filename, 'config.yml'); +const file2 = loadFixture(__filename, 'config2.yml'); +const file3 = loadFixture(__filename, 'config3.yml'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/cloudbuild/__snapshots__/extract.spec.ts.snap b/lib/manager/cloudbuild/__snapshots__/extract.spec.ts.snap index ffd3d8a3be8486..6bffda93dcec3e 100644 --- a/lib/manager/cloudbuild/__snapshots__/extract.spec.ts.snap +++ b/lib/manager/cloudbuild/__snapshots__/extract.spec.ts.snap @@ -12,7 +12,6 @@ Array [ }, Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "12", "datasource": "docker", diff --git a/lib/manager/cloudbuild/extract.spec.ts b/lib/manager/cloudbuild/extract.spec.ts index 116a38c644b384..4301cf5ccec8bb 100644 --- a/lib/manager/cloudbuild/extract.spec.ts +++ b/lib/manager/cloudbuild/extract.spec.ts @@ -1,11 +1,7 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const file1 = readFileSync( - 'lib/manager/cloudbuild/__fixtures__/cloudbuild.yml', - 'utf8' -); +const file1 = loadFixture(__filename, 'cloudbuild.yml'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/cocoapods/extract.spec.ts b/lib/manager/cocoapods/extract.spec.ts index 09d456474f43c4..d8e5d18dcb3278 100644 --- a/lib/manager/cocoapods/extract.spec.ts +++ b/lib/manager/cocoapods/extract.spec.ts @@ -1,18 +1,8 @@ -import fs from 'fs-extra'; -import upath from 'upath'; - -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from '.'; -const simplePodfile = fs.readFileSync( - upath.resolve(__dirname, './__fixtures__/Podfile.simple'), - 'utf-8' -); - -const complexPodfile = fs.readFileSync( - upath.resolve(__dirname, './__fixtures__/Podfile.complex'), - 'utf-8' -); +const simplePodfile = loadFixture(__filename, 'Podfile.simple'); +const complexPodfile = loadFixture(__filename, 'Podfile.complex'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/composer/artifacts.spec.ts b/lib/manager/composer/artifacts.spec.ts index d7798754387c6c..fca585b9583432 100644 --- a/lib/manager/composer/artifacts.spec.ts +++ b/lib/manager/composer/artifacts.spec.ts @@ -30,6 +30,7 @@ const config = { localDir: join('/tmp/github/some/repo'), cacheDir: join('/tmp/renovate/cache'), composerIgnorePlatformReqs: true, + ignoreScripts: false, }; const repoStatus = partial({ @@ -46,7 +47,7 @@ describe('.updateArtifacts()', () => { await setUtilConfig(config); docker.resetPrefetchedImages(); hostRules.clear(); - setAdminConfig(); + setAdminConfig({ allowScripts: false }); }); it('returns if no composer.lock found', async () => { expect( @@ -63,7 +64,7 @@ describe('.updateArtifacts()', () => { const execSnapshots = mockExecAll(exec); fs.readLocalFile.mockReturnValueOnce('Current composer.lock' as any); git.getRepoStatus.mockResolvedValue(repoStatus); - setAdminConfig({ trustLevel: 'high' }); + setAdminConfig({ allowScripts: true }); expect( await composer.updateArtifacts({ packageFileName: 'composer.json', diff --git a/lib/manager/composer/artifacts.ts b/lib/manager/composer/artifacts.ts index 9515106780c284..bffbe7510c707e 100644 --- a/lib/manager/composer/artifacts.ts +++ b/lib/manager/composer/artifacts.ts @@ -151,7 +151,7 @@ export async function updateArtifacts({ args += ' --ignore-platform-reqs'; } args += ' --no-ansi --no-interaction'; - if (getAdminConfig().trustLevel !== 'high' || config.ignoreScripts) { + if (!getAdminConfig().allowScripts || config.ignoreScripts) { args += ' --no-scripts --no-autoloader'; } logger.debug({ cmd, args }, 'composer command'); diff --git a/lib/manager/composer/extract.spec.ts b/lib/manager/composer/extract.spec.ts index 04bf9d7121ffdd..f7dc652ef6df87 100644 --- a/lib/manager/composer/extract.spec.ts +++ b/lib/manager/composer/extract.spec.ts @@ -1,33 +1,14 @@ -import { readFileSync } from 'fs'; -import { fs, getName } from '../../../test/util'; +import { fs, getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; jest.mock('../../util/fs'); -const requirements1 = readFileSync( - 'lib/manager/composer/__fixtures__/composer1.json', - 'utf8' -); -const requirements2 = readFileSync( - 'lib/manager/composer/__fixtures__/composer2.json', - 'utf8' -); -const requirements3 = readFileSync( - 'lib/manager/composer/__fixtures__/composer3.json', - 'utf8' -); -const requirements4 = readFileSync( - 'lib/manager/composer/__fixtures__/composer4.json', - 'utf8' -); -const requirements5 = readFileSync( - 'lib/manager/composer/__fixtures__/composer5.json', - 'utf8' -); -const requirements5Lock = readFileSync( - 'lib/manager/composer/__fixtures__/composer5.lock', - 'utf8' -); +const requirements1 = loadFixture(__filename, 'composer1.json'); +const requirements2 = loadFixture(__filename, 'composer2.json'); +const requirements3 = loadFixture(__filename, 'composer3.json'); +const requirements4 = loadFixture(__filename, 'composer4.json'); +const requirements5 = loadFixture(__filename, 'composer5.json'); +const requirements5Lock = loadFixture(__filename, 'composer5.lock'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/deps-edn/extract.spec.ts b/lib/manager/deps-edn/extract.spec.ts index dd550044a7196c..b240919bb75bdd 100644 --- a/lib/manager/deps-edn/extract.spec.ts +++ b/lib/manager/deps-edn/extract.spec.ts @@ -1,13 +1,7 @@ -/* eslint-disable no-template-curly-in-string */ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const depsEdn = readFileSync( - resolve(__dirname, `./__fixtures__/deps.edn`), - 'utf8' -); +const depsEdn = loadFixture(__filename, 'deps.edn'); describe(getName(__filename), () => { it('extractPackageFile', () => { diff --git a/lib/manager/docker-compose/__snapshots__/extract.spec.ts.snap b/lib/manager/docker-compose/__snapshots__/extract.spec.ts.snap index ce8eb2b879c7e3..716a76d5bdd2c3 100644 --- a/lib/manager/docker-compose/__snapshots__/extract.spec.ts.snap +++ b/lib/manager/docker-compose/__snapshots__/extract.spec.ts.snap @@ -12,7 +12,6 @@ Array [ }, Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "10.0.0", "datasource": "docker", @@ -80,7 +79,6 @@ Array [ }, Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "10.0.0", "datasource": "docker", @@ -148,7 +146,6 @@ Array [ }, Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "10.0.0", "datasource": "docker", diff --git a/lib/manager/docker-compose/extract.spec.ts b/lib/manager/docker-compose/extract.spec.ts index 915e00345f0f1c..4cca8cd425415c 100644 --- a/lib/manager/docker-compose/extract.spec.ts +++ b/lib/manager/docker-compose/extract.spec.ts @@ -1,20 +1,11 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const yamlFile1 = readFileSync( - 'lib/manager/docker-compose/__fixtures__/docker-compose.1.yml', - 'utf8' -); - -const yamlFile3 = readFileSync( - 'lib/manager/docker-compose/__fixtures__/docker-compose.3.yml', - 'utf8' -); - -const yamlFile3NoVersion = readFileSync( - 'lib/manager/docker-compose/__fixtures__/docker-compose.3-no-version.yml', - 'utf8' +const yamlFile1 = loadFixture(__filename, 'docker-compose.1.yml'); +const yamlFile3 = loadFixture(__filename, 'docker-compose.3.yml'); +const yamlFile3NoVersion = loadFixture( + __filename, + 'docker-compose.3-no-version.yml' ); describe(getName(__filename), () => { diff --git a/lib/manager/dockerfile/__snapshots__/extract.spec.ts.snap b/lib/manager/dockerfile/__snapshots__/extract.spec.ts.snap index c1ebae9f7b88c3..7b7696e59e5ab1 100644 --- a/lib/manager/dockerfile/__snapshots__/extract.spec.ts.snap +++ b/lib/manager/dockerfile/__snapshots__/extract.spec.ts.snap @@ -4,7 +4,6 @@ exports[`manager/dockerfile/extract extractPackageFile() detects ["stage"] and [ Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "8.15.1-alpine", "datasource": "docker", @@ -123,7 +122,6 @@ exports[`manager/dockerfile/extract extractPackageFile() extracts images on adja Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": "sha256:d743b4141b02fcfb8beb68f92b4cd164f60ee457bf2d053f36785bf86de16b0d", "currentValue": "8.11.3-alpine", "datasource": "docker", @@ -147,7 +145,6 @@ exports[`manager/dockerfile/extract extractPackageFile() extracts multiple FROM Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "6.12.3", "datasource": "docker", @@ -185,7 +182,6 @@ exports[`manager/dockerfile/extract extractPackageFile() handles abnormal spacin Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "8.7.0", "datasource": "docker", @@ -214,7 +210,6 @@ exports[`manager/dockerfile/extract extractPackageFile() handles comments 1`] = Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": undefined, "datasource": "docker", @@ -229,7 +224,6 @@ exports[`manager/dockerfile/extract extractPackageFile() handles custom hosts 1` Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "8", "datasource": "docker", @@ -244,7 +238,6 @@ exports[`manager/dockerfile/extract extractPackageFile() handles custom hosts an Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "8-alpine", "datasource": "docker", @@ -259,7 +252,6 @@ exports[`manager/dockerfile/extract extractPackageFile() handles custom hosts wi Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "8", "datasource": "docker", @@ -274,7 +266,6 @@ exports[`manager/dockerfile/extract extractPackageFile() handles custom hosts wi Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "8", "datasource": "docker", @@ -289,7 +280,6 @@ exports[`manager/dockerfile/extract extractPackageFile() handles custom hosts wi Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": undefined, "datasource": "docker", @@ -304,7 +294,6 @@ exports[`manager/dockerfile/extract extractPackageFile() handles digest 1`] = ` Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": "sha256:eb85fc5b1198f5e1ec025ea07586bdbbf397e7d82df66c90d7511f533517e063", "currentValue": undefined, "datasource": "docker", @@ -319,7 +308,6 @@ exports[`manager/dockerfile/extract extractPackageFile() handles from as 1`] = ` Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "8.9.0-alpine", "datasource": "docker", @@ -334,7 +322,6 @@ exports[`manager/dockerfile/extract extractPackageFile() handles naked dep 1`] = Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": undefined, "datasource": "docker", @@ -349,7 +336,6 @@ exports[`manager/dockerfile/extract extractPackageFile() handles namespaced imag Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "8", "datasource": "docker", @@ -364,7 +350,6 @@ exports[`manager/dockerfile/extract extractPackageFile() handles tag 1`] = ` Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "8.9.0-alpine", "datasource": "docker", @@ -379,7 +364,6 @@ exports[`manager/dockerfile/extract extractPackageFile() handles tag and digest Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": "sha256:eb85fc5b1198f5e1ec025ea07586bdbbf397e7d82df66c90d7511f533517e063", "currentValue": "8.9.0", "datasource": "docker", @@ -409,7 +393,6 @@ exports[`manager/dockerfile/extract extractPackageFile() is case insensitive 1`] Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": undefined, "datasource": "docker", @@ -424,7 +407,6 @@ exports[`manager/dockerfile/extract extractPackageFile() skips index reference C Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "6.12.3", "datasource": "docker", @@ -439,7 +421,6 @@ exports[`manager/dockerfile/extract extractPackageFile() skips named multistage Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "6.12.3", "datasource": "docker", @@ -454,7 +435,6 @@ exports[`manager/dockerfile/extract extractPackageFile() skips named multistage Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "6.12.3", "datasource": "docker", diff --git a/lib/manager/dockerfile/extract.spec.ts b/lib/manager/dockerfile/extract.spec.ts index fcdf3409bcb4d6..6a72adff49ac56 100644 --- a/lib/manager/dockerfile/extract.spec.ts +++ b/lib/manager/dockerfile/extract.spec.ts @@ -1,16 +1,8 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile, getDep } from './extract'; -const d1 = readFileSync( - 'lib/manager/dockerfile/__fixtures__/1.Dockerfile', - 'utf8' -); - -const d2 = readFileSync( - 'lib/manager/dockerfile/__fixtures__/2.Dockerfile', - 'utf8' -); +const d1 = loadFixture(__filename, '1.Dockerfile'); +const d2 = loadFixture(__filename, '2.Dockerfile'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/dockerfile/extract.ts b/lib/manager/dockerfile/extract.ts index fae09b1aff9eab..01d9e58af7be95 100644 --- a/lib/manager/dockerfile/extract.ts +++ b/lib/manager/dockerfile/extract.ts @@ -48,14 +48,6 @@ export function getDep( '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}'; } dep.datasource = datasourceDocker.id; - if ( - dep.depName && - (dep.depName === 'node' || dep.depName.endsWith('/node')) && - dep.depName !== 'calico/node' - ) { - dep.commitMessageTopic = 'Node.js'; - } - if (dep.depName === 'ubuntu') { dep.versioning = ubuntuVersioning.id; } diff --git a/lib/manager/droneci/__snapshots__/extract.spec.ts.snap b/lib/manager/droneci/__snapshots__/extract.spec.ts.snap index 3723edeab59ae7..4d74cfdddd02b0 100644 --- a/lib/manager/droneci/__snapshots__/extract.spec.ts.snap +++ b/lib/manager/droneci/__snapshots__/extract.spec.ts.snap @@ -13,7 +13,6 @@ Array [ }, Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": "sha256:36adc17e9cceab32179d3314da9cb9c737ffb11f0de4e688f407ad6d9ca32201", "currentValue": "10.0.0", "datasource": "docker", diff --git a/lib/manager/droneci/extract.spec.ts b/lib/manager/droneci/extract.spec.ts index 585137d56d0d85..3855871bb729f7 100644 --- a/lib/manager/droneci/extract.spec.ts +++ b/lib/manager/droneci/extract.spec.ts @@ -1,13 +1,8 @@ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const droneYAML = readFileSync( - resolve('lib/manager/droneci/__fixtures__/.drone.yml'), - 'utf8' -); +const droneYAML = loadFixture(__filename, '.drone.yml'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/github-actions/__snapshots__/extract.spec.ts.snap b/lib/manager/github-actions/__snapshots__/extract.spec.ts.snap index 900449a8c59363..d7d3f17dee9b11 100644 --- a/lib/manager/github-actions/__snapshots__/extract.spec.ts.snap +++ b/lib/manager/github-actions/__snapshots__/extract.spec.ts.snap @@ -67,7 +67,6 @@ Array [ }, Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": "sha256:7b65413af120ec5328077775022c78101f103258a1876ec2f83890bce416e896", "currentValue": "6", "datasource": "docker", diff --git a/lib/manager/github-actions/extract.spec.ts b/lib/manager/github-actions/extract.spec.ts index 9e607beda7426c..96b57906990614 100644 --- a/lib/manager/github-actions/extract.spec.ts +++ b/lib/manager/github-actions/extract.spec.ts @@ -1,16 +1,8 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const workflow1 = readFileSync( - 'lib/manager/github-actions/__fixtures__/workflow.yml.1', - 'utf8' -); - -const workflow2 = readFileSync( - 'lib/manager/github-actions/__fixtures__/workflow.yml.2', - 'utf8' -); +const workflow1 = loadFixture(__filename, 'workflow.yml.1'); +const workflow2 = loadFixture(__filename, 'workflow.yml.2'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/gitlabci-include/extract.spec.ts b/lib/manager/gitlabci-include/extract.spec.ts index f7083030c5e110..d0e561f84c941b 100644 --- a/lib/manager/gitlabci-include/extract.spec.ts +++ b/lib/manager/gitlabci-include/extract.spec.ts @@ -1,11 +1,7 @@ -import fs from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const yamlFile = fs.readFileSync( - 'lib/manager/gitlabci-include/__fixtures__/gitlab-ci.1.yaml', - 'utf8' -); +const yamlFile = loadFixture(__filename, 'gitlab-ci.1.yaml'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/gitlabci/__snapshots__/extract.spec.ts.snap b/lib/manager/gitlabci/__snapshots__/extract.spec.ts.snap index 0cb54034e6210a..89a2a0259235a0 100644 --- a/lib/manager/gitlabci/__snapshots__/extract.spec.ts.snap +++ b/lib/manager/gitlabci/__snapshots__/extract.spec.ts.snap @@ -148,7 +148,6 @@ Array [ "deps": Array [ Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "commitMessageTopic": "Node.js", "currentDigest": undefined, "currentValue": "12", "datasource": "docker", diff --git a/lib/manager/gomod/extract.spec.ts b/lib/manager/gomod/extract.spec.ts index d0ae06a506032d..e24ba7a50eee1a 100644 --- a/lib/manager/gomod/extract.spec.ts +++ b/lib/manager/gomod/extract.spec.ts @@ -1,10 +1,9 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const gomod1 = readFileSync('lib/manager/gomod/__fixtures__/1/go.mod', 'utf8'); -const gomod2 = readFileSync('lib/manager/gomod/__fixtures__/2/go.mod', 'utf8'); -const gomod3 = readFileSync('lib/manager/gomod/__fixtures__/3/go.mod', 'utf8'); +const gomod1 = loadFixture(__filename, '1/go.mod'); +const gomod2 = loadFixture(__filename, '2/go.mod'); +const gomod3 = loadFixture(__filename, '3/go.mod'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/gomod/update.spec.ts b/lib/manager/gomod/update.spec.ts index 6dfba946bf02b0..eb03ca3cfc6806 100644 --- a/lib/manager/gomod/update.spec.ts +++ b/lib/manager/gomod/update.spec.ts @@ -1,10 +1,9 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import type { UpdateType } from '../../config/types'; import { updateDependency } from './update'; -const gomod1 = readFileSync('lib/manager/gomod/__fixtures__/1/go.mod', 'utf8'); -const gomod2 = readFileSync('lib/manager/gomod/__fixtures__/2/go.mod', 'utf8'); +const gomod1 = loadFixture(__filename, '1/go.mod'); +const gomod2 = loadFixture(__filename, '2/go.mod'); describe(getName(__filename), () => { describe('updateDependency', () => { diff --git a/lib/manager/gradle-lite/parser.spec.ts b/lib/manager/gradle-lite/parser.spec.ts index 560d365dbdf88a..972653ff4bff10 100644 --- a/lib/manager/gradle-lite/parser.spec.ts +++ b/lib/manager/gradle-lite/parser.spec.ts @@ -1,13 +1,7 @@ -import { readFileSync } from 'fs'; -import path from 'path'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { GOOGLE_REPO, JCENTER_REPO, MAVEN_REPO } from './common'; import { parseGradle, parseProps } from './parser'; -function getGradleFile(fileName: string): string { - return readFileSync(path.resolve(__dirname, fileName), 'utf8'); -} - describe(getName(__filename), () => { it('handles end of input', () => { expect(parseGradle('version = ').deps).toBeEmpty(); @@ -162,8 +156,10 @@ describe(getName(__filename), () => { ]); }); it('parses fixture from "gradle" manager', () => { - const content = getGradleFile( - `../gradle/__fixtures__/build.gradle.example1` + const content = loadFixture( + __filename, + 'build.gradle.example1', + '../gradle' ); const { deps } = parseGradle(content, {}, 'build.gradle'); deps.forEach((dep) => { diff --git a/lib/manager/gradle-lite/tokenizer.ts b/lib/manager/gradle-lite/tokenizer.ts index 904cf29b161111..b37722fae2b873 100644 --- a/lib/manager/gradle-lite/tokenizer.ts +++ b/lib/manager/gradle-lite/tokenizer.ts @@ -19,7 +19,7 @@ const escapedChars = { }, }; -export const rawLexer = { +const lexer = moo.states({ // Top-level Groovy lexemes main: { [TokenType.LineComment]: { match: /\/\/.*?$/ }, @@ -104,7 +104,7 @@ export const rawLexer = { [TokenType.RightBrace]: { match: '}', pop: 1 }, [TokenType.UnknownLexeme]: { match: /[^]/, lineBreaks: true }, }, -}; +}); /* Turn UnknownLexeme chars to UnknownFragment strings @@ -213,7 +213,6 @@ function filterTokens({ type }: Token): boolean { } export function extractRawTokens(input: string): Token[] { - const lexer = moo.states(rawLexer); lexer.reset(input); return Array.from(lexer).map( ({ type, offset, value }) => ({ type, offset, value } as Token) diff --git a/lib/manager/gradle-wrapper/extract.spec.ts b/lib/manager/gradle-wrapper/extract.spec.ts index b3d3a149d131c7..f436ccdafdc953 100644 --- a/lib/manager/gradle-wrapper/extract.spec.ts +++ b/lib/manager/gradle-wrapper/extract.spec.ts @@ -1,27 +1,13 @@ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const propertiesFile1 = readFileSync( - resolve(__dirname, './__fixtures__/gradle-wrapper-1.properties'), - 'utf8' -); -const propertiesFile2 = readFileSync( - resolve(__dirname, './__fixtures__/gradle-wrapper-2.properties'), - 'utf8' -); -const propertiesFile3 = readFileSync( - resolve(__dirname, './__fixtures__/gradle-wrapper-3.properties'), - 'utf8' -); -const propertiesFile4 = readFileSync( - resolve(__dirname, './__fixtures__/gradle-wrapper-4.properties'), - 'utf8' -); -const whitespacePropertiesFile = readFileSync( - resolve(__dirname, './__fixtures__/gradle-wrapper-whitespace.properties'), - 'utf8' +const propertiesFile1 = loadFixture(__filename, 'gradle-wrapper-1.properties'); +const propertiesFile2 = loadFixture(__filename, 'gradle-wrapper-2.properties'); +const propertiesFile3 = loadFixture(__filename, 'gradle-wrapper-3.properties'); +const propertiesFile4 = loadFixture(__filename, 'gradle-wrapper-4.properties'); +const whitespacePropertiesFile = loadFixture( + __filename, + 'gradle-wrapper-whitespace.properties' ); describe(getName(__filename), () => { diff --git a/lib/manager/helm-values/extract.spec.ts b/lib/manager/helm-values/extract.spec.ts index 3db74c265e3d8c..53fbc347837df3 100644 --- a/lib/manager/helm-values/extract.spec.ts +++ b/lib/manager/helm-values/extract.spec.ts @@ -1,15 +1,14 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const helmDefaultChartInitValues = readFileSync( - 'lib/manager/helm-values/__fixtures__/default_chart_init_values.yaml', - 'utf8' +const helmDefaultChartInitValues = loadFixture( + __filename, + 'default_chart_init_values.yaml' ); -const helmMultiAndNestedImageValues = readFileSync( - 'lib/manager/helm-values/__fixtures__/multi_and_nested_image_values.yaml', - 'utf8' +const helmMultiAndNestedImageValues = loadFixture( + __filename, + 'multi_and_nested_image_values.yaml' ); describe(getName(__filename), () => { diff --git a/lib/manager/helmfile/extract.spec.ts b/lib/manager/helmfile/extract.spec.ts index 7c983e6c7a807a..3a3888575aae4c 100644 --- a/lib/manager/helmfile/extract.spec.ts +++ b/lib/manager/helmfile/extract.spec.ts @@ -1,11 +1,8 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const multidocYaml = readFileSync( - 'lib/manager/helmfile/__fixtures__/multidoc.yaml', - 'utf8' -); +const multidocYaml = loadFixture(__filename, 'multidoc.yaml'); + describe(getName(__filename), () => { describe('extractPackageFile()', () => { beforeEach(() => { diff --git a/lib/manager/homebrew/extract.spec.ts b/lib/manager/homebrew/extract.spec.ts index d4c61f7d27f3e4..b4e8f6d8d87662 100644 --- a/lib/manager/homebrew/extract.spec.ts +++ b/lib/manager/homebrew/extract.spec.ts @@ -1,24 +1,11 @@ -import fs from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const aalib = fs.readFileSync( - 'lib/manager/homebrew/__fixtures__/aalib.rb', - 'utf8' -); -const aap = fs.readFileSync('lib/manager/homebrew/__fixtures__/aap.rb', 'utf8'); -const acmetool = fs.readFileSync( - 'lib/manager/homebrew/__fixtures__/acmetool.rb', - 'utf8' -); -const aide = fs.readFileSync( - 'lib/manager/homebrew/__fixtures__/aide.rb', - 'utf8' -); -const ibazel = fs.readFileSync( - 'lib/manager/homebrew/__fixtures__/ibazel.rb', - 'utf8' -); +const aalib = loadFixture(__filename, 'aalib.rb'); +const aap = loadFixture(__filename, 'aap.rb'); +const acmetool = loadFixture(__filename, 'acmetool.rb'); +const aide = loadFixture(__filename, 'aide.rb'); +const ibazel = loadFixture(__filename, 'ibazel.rb'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/homebrew/index.ts b/lib/manager/homebrew/index.ts index 62bb3b08a55d92..b45e932cf7f9a7 100644 --- a/lib/manager/homebrew/index.ts +++ b/lib/manager/homebrew/index.ts @@ -3,6 +3,5 @@ export { updateDependency } from './update'; export const defaultConfig = { commitMessageTopic: 'Homebrew Formula {{depName}}', - additionalBranchPrefix: 'homebrew-', fileMatch: ['^Formula/[^/]+[.]rb$'], }; diff --git a/lib/manager/homebrew/update.spec.ts b/lib/manager/homebrew/update.spec.ts index 84aafa850acaba..ad7f6df4a7ec8d 100644 --- a/lib/manager/homebrew/update.spec.ts +++ b/lib/manager/homebrew/update.spec.ts @@ -1,17 +1,10 @@ -import fs from 'fs'; import { Readable } from 'stream'; import * as httpMock from '../../../test/http-mock'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { updateDependency } from './update'; -const aide = fs.readFileSync( - 'lib/manager/homebrew/__fixtures__/aide.rb', - 'utf8' -); -const ibazel = fs.readFileSync( - 'lib/manager/homebrew/__fixtures__/ibazel.rb', - 'utf8' -); +const aide = loadFixture(__filename, 'aide.rb'); +const ibazel = loadFixture(__filename, 'ibazel.rb'); const baseUrl = 'https://github.com'; diff --git a/lib/manager/html/extract.spec.ts b/lib/manager/html/extract.spec.ts index 7f27a8eb30428c..20bfa9720bd4eb 100644 --- a/lib/manager/html/extract.spec.ts +++ b/lib/manager/html/extract.spec.ts @@ -1,16 +1,8 @@ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from '.'; -const sample = readFileSync( - resolve(__dirname, `./__fixtures__/sample.html`), - 'utf8' -); -const nothing = readFileSync( - resolve(__dirname, `./__fixtures__/nothing.html`), - 'utf8' -); +const sample = loadFixture(__filename, `sample.html`); +const nothing = loadFixture(__filename, `nothing.html`); describe(getName(__filename), () => { it('extractPackageFile', () => { diff --git a/lib/manager/jenkins/extract.spec.ts b/lib/manager/jenkins/extract.spec.ts index 36775a6e261ffa..b9481d1576ec40 100644 --- a/lib/manager/jenkins/extract.spec.ts +++ b/lib/manager/jenkins/extract.spec.ts @@ -1,29 +1,13 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const invalidYamlFile = readFileSync( - 'lib/manager/jenkins/__fixtures__/invalid.yaml', - 'utf8' -); - -const pluginsTextFile = readFileSync( - 'lib/manager/jenkins/__fixtures__/plugins.txt', - 'utf8' -); -const pluginsYamlFile = readFileSync( - 'lib/manager/jenkins/__fixtures__/plugins.yaml', - 'utf8' -); - -const pluginsEmptyTextFile = readFileSync( - 'lib/manager/jenkins/__fixtures__/empty.txt', - 'utf8' -); -const pluginsEmptyYamlFile = readFileSync( - 'lib/manager/jenkins/__fixtures__/empty.yaml', - 'utf8' -); +const invalidYamlFile = loadFixture(__filename, 'invalid.yaml'); + +const pluginsTextFile = loadFixture(__filename, 'plugins.txt'); +const pluginsYamlFile = loadFixture(__filename, 'plugins.yaml'); + +const pluginsEmptyTextFile = loadFixture(__filename, 'empty.txt'); +const pluginsEmptyYamlFile = loadFixture(__filename, 'empty.yaml'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/kubernetes/extract.spec.ts b/lib/manager/kubernetes/extract.spec.ts index 8862eaf8c09383..04fe288e18c451 100644 --- a/lib/manager/kubernetes/extract.spec.ts +++ b/lib/manager/kubernetes/extract.spec.ts @@ -1,26 +1,10 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const kubernetesImagesFile = readFileSync( - 'lib/manager/kubernetes/__fixtures__/kubernetes.yaml', - 'utf8' -); - -const kubernetesConfigMapFile = readFileSync( - 'lib/manager/kubernetes/__fixtures__/configmap.yaml', - 'utf8' -); - -const kubernetesArraySyntaxFile = readFileSync( - 'lib/manager/kubernetes/__fixtures__/array-syntax.yaml', - 'utf8' -); - -const otherYamlFile = readFileSync( - 'lib/manager/kubernetes/__fixtures__/gitlab-ci.yaml', - 'utf8' -); +const kubernetesImagesFile = loadFixture(__filename, 'kubernetes.yaml'); +const kubernetesConfigMapFile = loadFixture(__filename, 'configmap.yaml'); +const kubernetesArraySyntaxFile = loadFixture(__filename, 'array-syntax.yaml'); +const otherYamlFile = loadFixture(__filename, 'gitlab-ci.yaml'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/kustomize/extract.spec.ts b/lib/manager/kustomize/extract.spec.ts index f7330ce303e06b..e4da4782aed016 100644 --- a/lib/manager/kustomize/extract.spec.ts +++ b/lib/manager/kustomize/extract.spec.ts @@ -1,5 +1,4 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import * as datasourceDocker from '../../datasource/docker'; import * as datasourceGitTags from '../../datasource/git-tags'; import * as datasourceGitHubTags from '../../datasource/github-tags'; @@ -11,47 +10,18 @@ import { parseKustomize, } from './extract'; -const kustomizeGitSSHBase = readFileSync( - 'lib/manager/kustomize/__fixtures__/gitSshBase.yaml', - 'utf8' +const kustomizeGitSSHBase = loadFixture(__filename, 'gitSshBase.yaml'); +const kustomizeEmpty = loadFixture(__filename, 'kustomizeEmpty.yaml'); +const kustomizeGitSSHSubdir = loadFixture(__filename, 'gitSubdir.yaml'); +const kustomizeHTTP = loadFixture(__filename, 'kustomizeHttp.yaml'); +const kustomizeWithLocal = loadFixture(__filename, 'kustomizeWithLocal.yaml'); +const nonKustomize = loadFixture(__filename, 'service.yaml'); +const gitImages = loadFixture(__filename, 'gitImages.yaml'); +const kustomizeDepsInResources = loadFixture( + __filename, + 'depsInResources.yaml' ); - -const kustomizeEmpty = readFileSync( - 'lib/manager/kustomize/__fixtures__/kustomizeEmpty.yaml', - 'utf8' -); - -const kustomizeGitSSHSubdir = readFileSync( - 'lib/manager/kustomize/__fixtures__/gitSubdir.yaml', - 'utf8' -); - -const kustomizeHTTP = readFileSync( - 'lib/manager/kustomize/__fixtures__/kustomizeHttp.yaml', - 'utf8' -); - -const kustomizeWithLocal = readFileSync( - 'lib/manager/kustomize/__fixtures__/kustomizeWithLocal.yaml', - 'utf8' -); - -const nonKustomize = readFileSync( - 'lib/manager/kustomize/__fixtures__/service.yaml', - 'utf8' -); - -const gitImages = readFileSync( - 'lib/manager/kustomize/__fixtures__/gitImages.yaml', - 'utf8' -); - -const kustomizeDepsInResources = readFileSync( - 'lib/manager/kustomize/__fixtures__/depsInResources.yaml', - 'utf8' -); - -const sha = readFileSync('lib/manager/kustomize/__fixtures__/sha.yaml', 'utf8'); +const sha = loadFixture(__filename, 'sha.yaml'); describe(getName(__filename), () => { it('should successfully parse a valid kustomize file', () => { diff --git a/lib/manager/leiningen/extract.spec.ts b/lib/manager/leiningen/extract.spec.ts index 22a261641037e1..681db83205e449 100644 --- a/lib/manager/leiningen/extract.spec.ts +++ b/lib/manager/leiningen/extract.spec.ts @@ -1,14 +1,8 @@ -/* eslint-disable no-template-curly-in-string */ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import * as datasourceClojure from '../../datasource/clojure'; import { extractFromVectors, extractPackageFile, trimAtKey } from './extract'; -const leinProjectClj = readFileSync( - resolve(__dirname, `./__fixtures__/project.clj`), - 'utf8' -); +const leinProjectClj = loadFixture(__filename, `project.clj`); describe(getName(__filename), () => { it('trimAtKey', () => { diff --git a/lib/manager/maven/extract.spec.ts b/lib/manager/maven/extract.spec.ts index 8ba6f952187249..36c443fe3faafd 100644 --- a/lib/manager/maven/extract.spec.ts +++ b/lib/manager/maven/extract.spec.ts @@ -1,18 +1,9 @@ /* eslint-disable no-template-curly-in-string */ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackage } from './extract'; -const minimumContent = readFileSync( - resolve(__dirname, `./__fixtures__/minimum.pom.xml`), - 'utf8' -); - -const simpleContent = readFileSync( - resolve(__dirname, `./__fixtures__/simple.pom.xml`), - 'utf8' -); +const minimumContent = loadFixture(__filename, `minimum.pom.xml`); +const simpleContent = loadFixture(__filename, `simple.pom.xml`); describe(getName(__filename), () => { describe('extractDependencies', () => { diff --git a/lib/manager/maven/index.spec.ts b/lib/manager/maven/index.spec.ts index 548b71f42629f9..4be69a337c6dbc 100644 --- a/lib/manager/maven/index.spec.ts +++ b/lib/manager/maven/index.spec.ts @@ -1,27 +1,14 @@ -import { readFileSync } from 'fs'; -import { fs, getName } from '../../../test/util'; +import { fs, getName, loadFixture } from '../../../test/util'; import type { PackageDependency, PackageFile } from '../types'; import { extractPackage, resolveParents } from './extract'; import { extractAllPackageFiles, updateDependency } from '.'; jest.mock('../../util/fs'); -const pomContent = readFileSync( - 'lib/manager/maven/__fixtures__/simple.pom.xml', - 'utf8' -); -const pomParent = readFileSync( - 'lib/manager/maven/__fixtures__/parent.pom.xml', - 'utf8' -); -const pomChild = readFileSync( - 'lib/manager/maven/__fixtures__/child.pom.xml', - 'utf8' -); -const origContent = readFileSync( - 'lib/manager/maven/__fixtures__/grouping.pom.xml', - 'utf8' -); +const pomContent = loadFixture(__filename, 'simple.pom.xml'); +const pomParent = loadFixture(__filename, 'parent.pom.xml'); +const pomChild = loadFixture(__filename, 'child.pom.xml'); +const origContent = loadFixture(__filename, 'grouping.pom.xml'); function selectDep(deps: PackageDependency[], name = 'org.example:quuz') { return deps.find((dep) => dep.depName === name); diff --git a/lib/manager/meteor/extract.spec.ts b/lib/manager/meteor/extract.spec.ts index 6bfb2f18671161..7171f035823bc0 100644 --- a/lib/manager/meteor/extract.spec.ts +++ b/lib/manager/meteor/extract.spec.ts @@ -1,13 +1,7 @@ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -function readFixture(fixture: string) { - return readFileSync(resolve(__dirname, `./__fixtures__/${fixture}`), 'utf8'); -} - -const input01Content = readFixture('package-1.js'); +const input01Content = loadFixture(__filename, 'package-1.js'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/mix/extract.spec.ts b/lib/manager/mix/extract.spec.ts index b350d5750f66f1..834c210a500389 100644 --- a/lib/manager/mix/extract.spec.ts +++ b/lib/manager/mix/extract.spec.ts @@ -1,12 +1,7 @@ -import fs from 'fs-extra'; -import upath from 'upath'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from '.'; -const sample = fs.readFileSync( - upath.resolve(__dirname, './__fixtures__/mix.exs'), - 'utf-8' -); +const sample = loadFixture(__filename, 'mix.exs'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap b/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap index e0b886ce2fb95c..4d7be39d441995 100644 --- a/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap +++ b/lib/manager/npm/extract/__snapshots__/index.spec.ts.snap @@ -11,7 +11,6 @@ Object { "skipReason": "invalid-name", }, ], - "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -135,7 +134,6 @@ Object { "prettyDepType": "engine", }, ], - "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -299,7 +297,6 @@ Object { "sourceUrl": "https://github.com/owner/n", }, ], - "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -349,7 +346,6 @@ Object { "skipReason": "unknown-version", }, ], - "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -410,7 +406,6 @@ Object { "skipReason": "unknown-volta", }, ], - "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -465,7 +460,6 @@ Object { "skipReason": "unknown-version", }, ], - "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -602,7 +596,6 @@ Object { "prettyDepType": "resolutions", }, ], - "ignoreNpmrcFile": undefined, "lernaClient": "npm", "lernaPackages": undefined, "managerData": Object { @@ -739,7 +732,6 @@ Object { "prettyDepType": "resolutions", }, ], - "ignoreNpmrcFile": undefined, "lernaClient": "yarn", "lernaPackages": undefined, "managerData": Object { @@ -876,7 +868,6 @@ Object { "prettyDepType": "resolutions", }, ], - "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -899,7 +890,6 @@ exports[`manager/npm/extract/index .extractPackageFile() finds complex yarn work Object { "constraints": Object {}, "deps": Array [], - "ignoreNpmrcFile": undefined, "lernaClient": "npm", "lernaPackages": undefined, "managerData": Object { @@ -1038,7 +1028,6 @@ Object { "prettyDepType": "resolutions", }, ], - "ignoreNpmrcFile": undefined, "lernaClient": "npm", "lernaPackages": undefined, "managerData": Object { @@ -1061,7 +1050,6 @@ exports[`manager/npm/extract/index .extractPackageFile() finds simple yarn works Object { "constraints": Object {}, "deps": Array [], - "ignoreNpmrcFile": undefined, "lernaClient": "npm", "lernaPackages": undefined, "managerData": Object { @@ -1086,7 +1074,6 @@ exports[`manager/npm/extract/index .extractPackageFile() finds simple yarn works Object { "constraints": Object {}, "deps": Array [], - "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { @@ -1225,7 +1212,6 @@ Object { "prettyDepType": "resolutions", }, ], - "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { diff --git a/lib/manager/npm/extract/index.spec.ts b/lib/manager/npm/extract/index.spec.ts index fa78521e8218ba..b4ea83e1ef2eda 100644 --- a/lib/manager/npm/extract/index.spec.ts +++ b/lib/manager/npm/extract/index.spec.ts @@ -1,6 +1,4 @@ -import { readFileSync } from 'fs'; -import upath from 'upath'; -import { getName } from '../../../../test/util'; +import { getName, loadFixture } from '../../../../test/util'; import { getConfig } from '../../../config/defaults'; import * as _fs from '../../../util/fs'; import * as npmExtract from '.'; @@ -10,18 +8,19 @@ const fs: any = _fs; // TODO: fix types const defaultConfig = getConfig(); -function readFixture(fixture: string) { - return readFileSync( - upath.resolve(__dirname, `../__fixtures__/${fixture}`), - 'utf8' - ); -} - -const input01Content = readFixture('inputs/01.json'); -const workspacesContent = readFixture('inputs/workspaces.json'); -const workspacesSimpleContent = readFixture('inputs/workspaces-simple.json'); -const vendorisedContent = readFixture('is-object.json'); -const invalidNameContent = readFixture('invalid-name.json'); +const input01Content = loadFixture(__filename, 'inputs/01.json', '..'); +const workspacesContent = loadFixture( + __filename, + 'inputs/workspaces.json', + '..' +); +const workspacesSimpleContent = loadFixture( + __filename, + 'inputs/workspaces-simple.json', + '..' +); +const vendorisedContent = loadFixture(__filename, 'is-object.json', '..'); +const invalidNameContent = loadFixture(__filename, 'invalid-name.json', '..'); describe(getName(__filename), () => { describe('.extractPackageFile()', () => { @@ -113,11 +112,25 @@ describe(getName(__filename), () => { ); expect(res.npmrc).toBeDefined(); }); - it('finds and discards .npmrc', async () => { + it('ignores .npmrc when config.npmrc is defined', async () => { + fs.readLocalFile = jest.fn((fileName) => { + if (fileName === '.npmrc') { + return 'some-npmrc\n'; + } + return null; + }); + const res = await npmExtract.extractPackageFile( + input01Content, + 'package.json', + { npmrc: 'some-configured-npmrc' } + ); + expect(res.npmrc).toBeUndefined(); + }); + it('finds and filters .npmrc with variables', async () => { fs.readLocalFile = jest.fn((fileName) => { if (fileName === '.npmrc') { // eslint-disable-next-line - return '//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}\n'; + return 'registry=https://registry.npmjs.org\n//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}\n'; } return null; }); @@ -126,7 +139,7 @@ describe(getName(__filename), () => { 'package.json', {} ); - expect(res.npmrc).toBeUndefined(); + expect(res.npmrc).toEqual('registry=https://registry.npmjs.org\n'); }); it('finds lerna', async () => { fs.readLocalFile = jest.fn((fileName) => { diff --git a/lib/manager/npm/extract/index.ts b/lib/manager/npm/extract/index.ts index 7bccc130f11d2a..b6192925fe83f7 100644 --- a/lib/manager/npm/extract/index.ts +++ b/lib/manager/npm/extract/index.ts @@ -6,11 +6,7 @@ import * as datasourceGithubTags from '../../../datasource/github-tags'; import { id as npmId } from '../../../datasource/npm'; import { logger } from '../../../logger'; import { SkipReason } from '../../../types'; -import { - deleteLocalFile, - getSiblingFileName, - readLocalFile, -} from '../../../util/fs'; +import { getSiblingFileName, readLocalFile } from '../../../util/fs'; import * as nodeVersioning from '../../../versioning/node'; import { isValid, isVersion } from '../../../versioning/npm'; import type { @@ -95,26 +91,30 @@ export async function extractPackageFile( delete lockFiles.shrinkwrapJson; let npmrc: string; - let ignoreNpmrcFile: boolean; const npmrcFileName = getSiblingFileName(fileName, '.npmrc'); - // istanbul ignore if - if (config.ignoreNpmrcFile) { - await deleteLocalFile(npmrcFileName); - } else { - npmrc = await readLocalFile(npmrcFileName, 'utf8'); - if (npmrc?.includes('package-lock')) { - logger.debug('Stripping package-lock setting from npmrc'); - npmrc = npmrc.replace(/(^|\n)package-lock.*?(\n|$)/g, '\n'); - } - if (is.string(npmrc)) { - if (npmrc.includes('=${') && getAdminConfig().trustLevel !== 'high') { - logger.debug('Discarding .npmrc file with variables'); - ignoreNpmrcFile = true; - npmrc = undefined; - await deleteLocalFile(npmrcFileName); - } + const npmrcContent = await readLocalFile(npmrcFileName, 'utf8'); + if (is.string(npmrcContent)) { + if (is.string(config.npmrc)) { + logger.debug( + { npmrcFileName }, + 'Repo .npmrc file is ignored due to presence of config.npmrc' + ); } else { - npmrc = undefined; + npmrc = npmrcContent; + if (npmrc?.includes('package-lock')) { + logger.debug('Stripping package-lock setting from .npmrc'); + npmrc = npmrc.replace(/(^|\n)package-lock.*?(\n|$)/g, '\n'); + } + if (npmrc.includes('=${') && !getAdminConfig().exposeAllEnv) { + logger.debug( + { npmrcFileName }, + 'Stripping .npmrc file of lines with variables' + ); + npmrc = npmrc + .split('\n') + .filter((line) => !line.includes('=${')) + .join('\n'); + } } } const yarnrcFileName = getSiblingFileName(fileName, '.yarnrc'); @@ -364,7 +364,6 @@ export async function extractPackageFile( packageFileVersion, packageJsonType, npmrc, - ignoreNpmrcFile, yarnrc, ...lockFiles, managerData: { diff --git a/lib/manager/npm/extract/npm.spec.ts b/lib/manager/npm/extract/npm.spec.ts index 4a9962c4027198..1946d3e61eb9b8 100644 --- a/lib/manager/npm/extract/npm.spec.ts +++ b/lib/manager/npm/extract/npm.spec.ts @@ -1,5 +1,4 @@ -import { readFileSync } from 'fs'; -import { fs, getName } from '../../../../test/util'; +import { fs, getName, loadFixture } from '../../../../test/util'; import { getNpmLock } from './npm'; jest.mock('../../../util/fs'); @@ -12,8 +11,10 @@ describe(getName(__filename), () => { expect(Object.keys(res.lockedVersions)).toHaveLength(0); }); it('extracts', async () => { - const plocktest1Lock = readFileSync( - 'lib/manager/npm/__fixtures__/plocktest1/package-lock.json' + const plocktest1Lock = loadFixture( + __filename, + 'plocktest1/package-lock.json', + '..' ); fs.readLocalFile.mockResolvedValueOnce(plocktest1Lock as never); const res = await getNpmLock('package.json'); @@ -21,9 +22,7 @@ describe(getName(__filename), () => { expect(Object.keys(res.lockedVersions)).toHaveLength(7); }); it('extracts npm 7 lockfile', async () => { - const npm7Lock = readFileSync( - 'lib/manager/npm/__fixtures__/npm7/package-lock.json' - ); + const npm7Lock = loadFixture(__filename, 'npm7/package-lock.json', '..'); fs.readLocalFile.mockResolvedValueOnce(npm7Lock as never); const res = await getNpmLock('package.json'); expect(res).toMatchSnapshot(); diff --git a/lib/manager/npm/extract/yarn.spec.ts b/lib/manager/npm/extract/yarn.spec.ts index 9b91d267724422..9882b371471882 100644 --- a/lib/manager/npm/extract/yarn.spec.ts +++ b/lib/manager/npm/extract/yarn.spec.ts @@ -1,5 +1,4 @@ -import { readFileSync } from 'fs'; -import { fs, getName } from '../../../../test/util'; +import { fs, getName, loadFixture } from '../../../../test/util'; import { getYarnLock } from './yarn'; jest.mock('../../../util/fs'); @@ -14,9 +13,10 @@ describe(getName(__filename), () => { }); it('extracts yarn 1', async () => { - const plocktest1Lock = readFileSync( - 'lib/manager/npm/__fixtures__/plocktest1/yarn.lock', - 'utf8' + const plocktest1Lock = loadFixture( + __filename, + 'plocktest1/yarn.lock', + '..' ); fs.readLocalFile.mockResolvedValueOnce(plocktest1Lock); const res = await getYarnLock('package.json'); @@ -27,10 +27,7 @@ describe(getName(__filename), () => { }); it('extracts yarn 2', async () => { - const plocktest1Lock = readFileSync( - 'lib/manager/npm/__fixtures__/yarn2/yarn.lock', - 'utf8' - ); + const plocktest1Lock = loadFixture(__filename, 'yarn2/yarn.lock', '..'); fs.readLocalFile.mockResolvedValueOnce(plocktest1Lock); const res = await getYarnLock('package.json'); expect(res.isYarn1).toBe(false); @@ -40,10 +37,7 @@ describe(getName(__filename), () => { }); it('extracts yarn 2 cache version', async () => { - const plocktest1Lock = readFileSync( - 'lib/manager/npm/__fixtures__/yarn2.2/yarn.lock', - 'utf8' - ); + const plocktest1Lock = loadFixture(__filename, 'yarn2.2/yarn.lock', '..'); fs.readLocalFile.mockResolvedValueOnce(plocktest1Lock); const res = await getYarnLock('package.json'); expect(res.isYarn1).toBe(false); diff --git a/lib/manager/npm/post-update/__snapshots__/lerna.spec.ts.snap b/lib/manager/npm/post-update/__snapshots__/lerna.spec.ts.snap index e8f5d06c35c0a7..4dc615e84774c2 100644 --- a/lib/manager/npm/post-update/__snapshots__/lerna.spec.ts.snap +++ b/lib/manager/npm/post-update/__snapshots__/lerna.spec.ts.snap @@ -236,65 +236,6 @@ Array [ ] `; -exports[`manager/npm/post-update/lerna generateLockFiles() maps dot files 1`] = ` -Array [ - Object { - "cmd": "lerna info || echo \\"Ignoring lerna info failure\\"", - "options": Object { - "cwd": "some-dir", - "encoding": "utf-8", - "env": Object { - "HOME": "/home/user", - "HTTPS_PROXY": "https://example.com", - "HTTP_PROXY": "http://example.com", - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US", - "NO_PROXY": "localhost", - "PATH": "/tmp/path", - }, - "maxBuffer": 10485760, - "timeout": 900000, - }, - }, - Object { - "cmd": "npm install --ignore-scripts --no-audit --package-lock-only", - "options": Object { - "cwd": "some-dir", - "encoding": "utf-8", - "env": Object { - "HOME": "/home/user", - "HTTPS_PROXY": "https://example.com", - "HTTP_PROXY": "http://example.com", - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US", - "NO_PROXY": "localhost", - "PATH": "/tmp/path", - }, - "maxBuffer": 10485760, - "timeout": 900000, - }, - }, - Object { - "cmd": "lerna bootstrap --no-ci --ignore-scripts -- --ignore-scripts --no-audit --package-lock-only", - "options": Object { - "cwd": "some-dir", - "encoding": "utf-8", - "env": Object { - "HOME": "/home/user", - "HTTPS_PROXY": "https://example.com", - "HTTP_PROXY": "http://example.com", - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US", - "NO_PROXY": "localhost", - "PATH": "/tmp/path", - }, - "maxBuffer": 10485760, - "timeout": 900000, - }, - }, -] -`; - exports[`manager/npm/post-update/lerna generateLockFiles() performs full npm install 1`] = ` Array [ Object { diff --git a/lib/manager/npm/post-update/__snapshots__/npm.spec.ts.snap b/lib/manager/npm/post-update/__snapshots__/npm.spec.ts.snap index ca01a58982538b..bba9f265872a67 100644 --- a/lib/manager/npm/post-update/__snapshots__/npm.spec.ts.snap +++ b/lib/manager/npm/post-update/__snapshots__/npm.spec.ts.snap @@ -7,7 +7,7 @@ exports[`generateLockFile finds npm globally 1`] = `Array []`; exports[`generateLockFile generates lock files 1`] = ` Array [ Object { - "cmd": "npm install --ignore-scripts --no-audit", + "cmd": "npm install --no-audit --ignore-scripts", "options": Object { "cwd": "some-dir", "encoding": "utf-8", @@ -50,7 +50,7 @@ exports[`generateLockFile performs full install 1`] = `Array []`; exports[`generateLockFile performs lock file maintenance 1`] = ` Array [ Object { - "cmd": "npm install --package-lock-only --ignore-scripts --no-audit", + "cmd": "npm install --package-lock-only --no-audit --ignore-scripts", "options": Object { "cwd": "some-dir", "encoding": "utf-8", @@ -73,7 +73,7 @@ Array [ exports[`generateLockFile performs lock file updates 1`] = ` Array [ Object { - "cmd": "npm install --package-lock-only --ignore-scripts --no-audit some-dep@1.0.1", + "cmd": "npm install --package-lock-only --no-audit --ignore-scripts some-dep@1.0.1", "options": Object { "cwd": "some-dir", "encoding": "utf-8", diff --git a/lib/manager/npm/post-update/index.ts b/lib/manager/npm/post-update/index.ts index 083272c1612b0f..aa992b653e70e8 100644 --- a/lib/manager/npm/post-update/index.ts +++ b/lib/manager/npm/post-update/index.ts @@ -144,9 +144,6 @@ export async function writeExistingFiles( } catch (err) /* istanbul ignore next */ { logger.warn({ npmrcFilename, err }, 'Error writing .npmrc'); } - } else if (config.ignoreNpmrcFile) { - logger.debug('Removing ignored .npmrc file before artifact generation'); - await remove(npmrcFilename); } if (packageFile.yarnrc) { logger.debug(`Writing .yarnrc to ${basedir}`); diff --git a/lib/manager/npm/post-update/lerna.spec.ts b/lib/manager/npm/post-update/lerna.spec.ts index 0dddb7c585fe5d..267bef2c31d306 100644 --- a/lib/manager/npm/post-update/lerna.spec.ts +++ b/lib/manager/npm/post-update/lerna.spec.ts @@ -93,27 +93,13 @@ describe(getName(__filename), () => { expect(res.error).toBe(false); expect(execSnapshots).toMatchSnapshot(); }); - it('maps dot files', async () => { - const execSnapshots = mockExecAll(exec); - const res = await lernaHelper.generateLockFiles( - lernaPkgFile('npm'), - 'some-dir', - { - dockerMapDotfiles: true, - constraints: { npm: '^6.0.0' }, - }, - {} - ); - expect(res.error).toBe(false); - expect(execSnapshots).toMatchSnapshot(); - }); it('allows scripts for trust level high', async () => { const execSnapshots = mockExecAll(exec); - setAdminConfig({ trustLevel: 'high' }); + setAdminConfig({ allowScripts: true }); const res = await lernaHelper.generateLockFiles( lernaPkgFile('npm'), 'some-dir', - {}, + { constraints: { npm: '^6.0.0' } }, {} ); expect(res.error).toBe(false); diff --git a/lib/manager/npm/post-update/lerna.ts b/lib/manager/npm/post-update/lerna.ts index 08cfc8be3d4c6c..4cf0bc54750c0c 100644 --- a/lib/manager/npm/post-update/lerna.ts +++ b/lib/manager/npm/post-update/lerna.ts @@ -1,6 +1,5 @@ import semver, { validRange } from 'semver'; import { quote } from 'shlex'; -import { join } from 'upath'; import { getAdminConfig } from '../../../config/admin'; import { TEMPORARY_ERROR } from '../../../constants/error-messages'; import { logger } from '../../../logger'; @@ -72,10 +71,7 @@ export async function generateLockFiles( return { error: false }; } let lernaCommand = `lerna bootstrap --no-ci --ignore-scripts -- `; - if ( - getAdminConfig().trustLevel === 'high' && - config.ignoreScripts !== false - ) { + if (getAdminConfig().allowScripts && config.ignoreScripts !== false) { cmdOptions = cmdOptions.replace('--ignore-scripts ', ''); lernaCommand = lernaCommand.replace('--ignore-scripts ', ''); } @@ -96,16 +92,9 @@ export async function generateLockFiles( }, }; // istanbul ignore if - if (getAdminConfig().trustLevel === 'high') { + if (getAdminConfig().exposeAllEnv) { execOptions.extraEnv.NPM_AUTH = env.NPM_AUTH; execOptions.extraEnv.NPM_EMAIL = env.NPM_EMAIL; - execOptions.extraEnv.NPM_TOKEN = env.NPM_TOKEN; - } - if (config.dockerMapDotfiles) { - const homeDir = - process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; - const homeNpmrc = join(homeDir, '.npmrc'); - execOptions.docker.volumes = [[homeNpmrc, '/home/ubuntu/.npmrc']]; } const lernaVersion = getLernaVersion(lernaPackageFile); logger.debug('Using lerna version ' + lernaVersion); diff --git a/lib/manager/npm/post-update/npm.spec.ts b/lib/manager/npm/post-update/npm.spec.ts index f235cb63cc2af1..b896545b9bde2e 100644 --- a/lib/manager/npm/post-update/npm.spec.ts +++ b/lib/manager/npm/post-update/npm.spec.ts @@ -27,7 +27,6 @@ describe('generateLockFile', () => { const execSnapshots = mockExecAll(exec); fs.readFile = jest.fn(() => 'package-lock-contents') as never; const skipInstalls = true; - const dockerMapDotfiles = true; const postUpdateOptions = ['npmDedupe']; const updates = [ { depName: 'some-dep', newVersion: '1.0.1', isLockfileUpdate: false }, @@ -36,7 +35,7 @@ describe('generateLockFile', () => { 'some-dir', {}, 'package-lock.json', - { dockerMapDotfiles, skipInstalls, postUpdateOptions }, + { skipInstalls, postUpdateOptions }, updates ); expect(fs.readFile).toHaveBeenCalledTimes(1); diff --git a/lib/manager/npm/post-update/npm.ts b/lib/manager/npm/post-update/npm.ts index d3e43876605615..9405b604056a2b 100644 --- a/lib/manager/npm/post-update/npm.ts +++ b/lib/manager/npm/post-update/npm.ts @@ -51,11 +51,16 @@ export async function generateLockFile( let cmdOptions = ''; if (postUpdateOptions?.includes('npmDedupe') || skipInstalls === false) { logger.debug('Performing node_modules install'); - cmdOptions += '--ignore-scripts --no-audit'; + cmdOptions += '--no-audit'; } else { logger.debug('Updating lock file only'); - cmdOptions += '--package-lock-only --ignore-scripts --no-audit'; + cmdOptions += '--package-lock-only --no-audit'; } + + if (!getAdminConfig().allowScripts || config.ignoreScripts) { + cmdOptions += ' --ignore-scripts'; + } + const tagConstraint = await getNodeConstraint(config); const execOptions: ExecOptions = { cwd, @@ -71,16 +76,9 @@ export async function generateLockFile( }, }; // istanbul ignore if - if (getAdminConfig().trustLevel === 'high') { + if (getAdminConfig().exposeAllEnv) { execOptions.extraEnv.NPM_AUTH = env.NPM_AUTH; execOptions.extraEnv.NPM_EMAIL = env.NPM_EMAIL; - execOptions.extraEnv.NPM_TOKEN = env.NPM_TOKEN; - } - if (config.dockerMapDotfiles) { - const homeDir = - process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; - const homeNpmrc = join(homeDir, '.npmrc'); - execOptions.docker.volumes = [[homeNpmrc, '/home/ubuntu/.npmrc']]; } if (!upgrades.every((upgrade) => upgrade.isLockfileUpdate)) { diff --git a/lib/manager/npm/post-update/pnpm.spec.ts b/lib/manager/npm/post-update/pnpm.spec.ts index f1146a0d018a09..195690f3d41cf7 100644 --- a/lib/manager/npm/post-update/pnpm.spec.ts +++ b/lib/manager/npm/post-update/pnpm.spec.ts @@ -24,7 +24,6 @@ describe('generateLockFile', () => { env.getChildProcessEnv.mockReturnValue(envMock.basic); }); it('generates lock files', async () => { - config.dockerMapDotfiles = true; const execSnapshots = mockExecAll(exec); fs.readFile = jest.fn(() => 'package-lock-contents') as never; const res = await pnpmHelper.generateLockFile('some-dir', {}, config); diff --git a/lib/manager/npm/post-update/pnpm.ts b/lib/manager/npm/post-update/pnpm.ts index 7816267e786744..f6a802fc609a01 100644 --- a/lib/manager/npm/post-update/pnpm.ts +++ b/lib/manager/npm/post-update/pnpm.ts @@ -50,20 +50,13 @@ export async function generateLockFile( }, }; // istanbul ignore if - if (getAdminConfig().trustLevel === 'high') { + if (getAdminConfig().exposeAllEnv) { execOptions.extraEnv.NPM_AUTH = env.NPM_AUTH; execOptions.extraEnv.NPM_EMAIL = env.NPM_EMAIL; - execOptions.extraEnv.NPM_TOKEN = env.NPM_TOKEN; - } - if (config.dockerMapDotfiles) { - const homeDir = - process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; - const homeNpmrc = join(homeDir, '.npmrc'); - execOptions.docker.volumes = [[homeNpmrc, '/home/ubuntu/.npmrc']]; } cmd = 'pnpm'; let args = 'install --recursive --lockfile-only'; - if (getAdminConfig().trustLevel !== 'high' || config.ignoreScripts) { + if (!getAdminConfig().allowScripts || config.ignoreScripts) { args += ' --ignore-scripts'; args += ' --ignore-pnpmfile'; } diff --git a/lib/manager/npm/post-update/yarn.spec.ts b/lib/manager/npm/post-update/yarn.spec.ts index 1439b5971cba5f..060417910eb830 100644 --- a/lib/manager/npm/post-update/yarn.spec.ts +++ b/lib/manager/npm/post-update/yarn.spec.ts @@ -54,7 +54,6 @@ describe(getName(__filename), () => { ); }); const config = { - dockerMapDotfiles: true, constraints: { yarn: yarnCompatibility, }, @@ -140,7 +139,6 @@ describe(getName(__filename), () => { ); }); const config = { - dockerMapDotfiles: true, constraints: { yarn: yarnCompatibility, }, diff --git a/lib/manager/npm/post-update/yarn.ts b/lib/manager/npm/post-update/yarn.ts index e179f717703ead..f555bcbce78f02 100644 --- a/lib/manager/npm/post-update/yarn.ts +++ b/lib/manager/npm/post-update/yarn.ts @@ -102,7 +102,7 @@ export async function generateLockFile( extraEnv.YARN_ENABLE_IMMUTABLE_INSTALLS = 'false'; extraEnv.YARN_HTTP_TIMEOUT = '100000'; } - if (getAdminConfig().trustLevel !== 'high' || config.ignoreScripts) { + if (!getAdminConfig().allowScripts || config.ignoreScripts) { if (isYarn1) { cmdOptions += ' --ignore-scripts'; } else { @@ -121,16 +121,9 @@ export async function generateLockFile( }, }; // istanbul ignore if - if (getAdminConfig().trustLevel === 'high') { + if (getAdminConfig().exposeAllEnv) { execOptions.extraEnv.NPM_AUTH = env.NPM_AUTH; execOptions.extraEnv.NPM_EMAIL = env.NPM_EMAIL; - execOptions.extraEnv.NPM_TOKEN = env.NPM_TOKEN; - } - if (config.dockerMapDotfiles) { - const homeDir = - process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; - const homeNpmrc = join(homeDir, '.npmrc'); - execOptions.docker.volumes = [[homeNpmrc, '/home/ubuntu/.npmrc']]; } // This command updates the lock file based on package.json diff --git a/lib/manager/npm/update/dependency/index.spec.ts b/lib/manager/npm/update/dependency/index.spec.ts index a663e644d3a2f4..b2a2c177b3a483 100644 --- a/lib/manager/npm/update/dependency/index.spec.ts +++ b/lib/manager/npm/update/dependency/index.spec.ts @@ -1,15 +1,7 @@ -import fs from 'fs'; -import upath from 'upath'; - -import { getName } from '../../../../../test/util'; +import { getName, loadFixture } from '../../../../../test/util'; import * as npmUpdater from '.'; -function readFixture(fixture: string) { - return fs.readFileSync( - upath.resolve(__dirname, `../../__fixtures__/${fixture}`), - 'utf8' - ); -} +const readFixture = (x: string): string => loadFixture(__filename, x, '../..'); const input01Content = readFixture('inputs/01.json'); const input01GlobContent = readFixture('inputs/01-glob.json'); diff --git a/lib/manager/npm/update/locked-dependency/dep-constraints.spec.ts b/lib/manager/npm/update/locked-dependency/dep-constraints.spec.ts index 47e0122b741f8c..577b9317221bf9 100644 --- a/lib/manager/npm/update/locked-dependency/dep-constraints.spec.ts +++ b/lib/manager/npm/update/locked-dependency/dep-constraints.spec.ts @@ -1,16 +1,10 @@ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { getName } from '../../../../../test/util'; +import { getName, loadJsonFixture } from '../../../../../test/util'; import { findDepConstraints } from './dep-constraints'; jest.mock('../../../../util/fs'); -const packageJson = JSON.parse( - readFileSync(resolve(__dirname, './__fixtures__/package.json'), 'utf8') -); -const packageLockJson = JSON.parse( - readFileSync(resolve(__dirname, './__fixtures__/package-lock.json'), 'utf8') -); +const packageJson = loadJsonFixture(__filename, 'package.json'); +const packageLockJson = loadJsonFixture(__filename, 'package-lock.json'); describe(getName(__filename), () => { describe('findDepConstraints()', () => { diff --git a/lib/manager/npm/update/locked-dependency/get-locked.spec.ts b/lib/manager/npm/update/locked-dependency/get-locked.spec.ts index f6ee9de18acee9..80370af9e543ac 100644 --- a/lib/manager/npm/update/locked-dependency/get-locked.spec.ts +++ b/lib/manager/npm/update/locked-dependency/get-locked.spec.ts @@ -1,13 +1,9 @@ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { getName } from '../../../../../test/util'; +import { getName, loadJsonFixture } from '../../../../../test/util'; import { getLockedDependencies } from './get-locked'; jest.mock('../../../../util/fs'); -const packageLockJson = JSON.parse( - readFileSync(resolve(__dirname, './__fixtures__/package-lock.json'), 'utf8') -); +const packageLockJson = loadJsonFixture(__filename, 'package-lock.json'); describe(getName(__filename), () => { describe('getLockedDependencies()', () => { diff --git a/lib/manager/npm/update/locked-dependency/index.spec.ts b/lib/manager/npm/update/locked-dependency/index.spec.ts index b5cff2f0e15a15..ebcda222783838 100644 --- a/lib/manager/npm/update/locked-dependency/index.spec.ts +++ b/lib/manager/npm/update/locked-dependency/index.spec.ts @@ -1,43 +1,19 @@ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; import * as httpMock from '../../../../../test/http-mock'; -import { getName } from '../../../../../test/util'; +import { getName, loadFixture } from '../../../../../test/util'; import { clone } from '../../../../util/clone'; import type { UpdateLockedConfig } from '../../../types'; import { updateLockedDependency } from '.'; -const packageFileContent = readFileSync( - resolve(__dirname, './__fixtures__/package.json'), - 'utf8' -); -const lockFileContent = readFileSync( - resolve(__dirname, './__fixtures__/package-lock.json'), - 'utf8' -); - -const acceptsJson = JSON.parse( - readFileSync(resolve(__dirname, './__fixtures__/accepts.json'), 'utf8') -); - -const expressJson = JSON.parse( - readFileSync(resolve(__dirname, './__fixtures__/express.json'), 'utf8') -); - -const mimeJson = JSON.parse( - readFileSync(resolve(__dirname, './__fixtures__/mime.json'), 'utf8') -); - +const packageFileContent = loadFixture(__filename, 'package.json'); +const lockFileContent = loadFixture(__filename, 'package-lock.json'); +const acceptsJson = JSON.parse(loadFixture(__filename, 'accepts.json')); +const expressJson = JSON.parse(loadFixture(__filename, 'express.json')); +const mimeJson = JSON.parse(loadFixture(__filename, 'mime.json')); const serveStaticJson = JSON.parse( - readFileSync(resolve(__dirname, './__fixtures__/serve-static.json'), 'utf8') -); - -const sendJson = JSON.parse( - readFileSync(resolve(__dirname, './__fixtures__/send.json'), 'utf8') -); - -const typeIsJson = JSON.parse( - readFileSync(resolve(__dirname, './__fixtures__/type-is.json'), 'utf8') + loadFixture(__filename, 'serve-static.json') ); +const sendJson = JSON.parse(loadFixture(__filename, 'send.json')); +const typeIsJson = JSON.parse(loadFixture(__filename, 'type-is.json')); describe(getName(__filename), () => { describe('updateLockedDependency()', () => { diff --git a/lib/manager/npm/update/locked-dependency/parent-version.spec.ts b/lib/manager/npm/update/locked-dependency/parent-version.spec.ts index ee2e5a7c3d5370..0e5717c181a216 100644 --- a/lib/manager/npm/update/locked-dependency/parent-version.spec.ts +++ b/lib/manager/npm/update/locked-dependency/parent-version.spec.ts @@ -1,12 +1,8 @@ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; import * as httpMock from '../../../../../test/http-mock'; -import { getName } from '../../../../../test/util'; +import { getName, loadJsonFixture } from '../../../../../test/util'; import { findFirstParentVersion } from './parent-version'; -const expressJson = JSON.parse( - readFileSync(resolve(__dirname, './__fixtures__/express.json'), 'utf8') -); +const expressJson = loadJsonFixture(__filename, 'express.json'); describe(getName(__filename), () => { describe('getLockedDependencies()', () => { diff --git a/lib/manager/pip_requirements/extract.spec.ts b/lib/manager/pip_requirements/extract.spec.ts index 6226ab5fc424da..886f6059fe10c0 100644 --- a/lib/manager/pip_requirements/extract.spec.ts +++ b/lib/manager/pip_requirements/extract.spec.ts @@ -1,40 +1,14 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { setAdminConfig } from '../../config/admin'; import { extractPackageFile } from './extract'; -const requirements1 = readFileSync( - 'lib/manager/pip_requirements/__fixtures__/requirements1.txt', - 'utf8' -); -const requirements2 = readFileSync( - 'lib/manager/pip_requirements/__fixtures__/requirements2.txt', - 'utf8' -); -const requirements3 = readFileSync( - 'lib/manager/pip_requirements/__fixtures__/requirements3.txt', - 'utf8' -); - -const requirements4 = readFileSync( - 'lib/manager/pip_requirements/__fixtures__/requirements4.txt', - 'utf8' -); - -const requirements5 = readFileSync( - 'lib/manager/pip_requirements/__fixtures__/requirements5.txt', - 'utf8' -); - -const requirements6 = readFileSync( - 'lib/manager/pip_requirements/__fixtures__/requirements6.txt', - 'utf8' -); - -const requirements7 = readFileSync( - 'lib/manager/pip_requirements/__fixtures__/requirements7.txt', - 'utf8' -); +const requirements1 = loadFixture(__filename, 'requirements1.txt'); +const requirements2 = loadFixture(__filename, 'requirements2.txt'); +const requirements3 = loadFixture(__filename, 'requirements3.txt'); +const requirements4 = loadFixture(__filename, 'requirements4.txt'); +const requirements5 = loadFixture(__filename, 'requirements5.txt'); +const requirements6 = loadFixture(__filename, 'requirements6.txt'); +const requirements7 = loadFixture(__filename, 'requirements7.txt'); describe(getName(__filename), () => { beforeEach(() => { @@ -129,7 +103,7 @@ describe(getName(__filename), () => { }); it('should replace env vars in high trust mode', () => { process.env.PIP_TEST_TOKEN = 'its-a-secret'; - setAdminConfig({ trustLevel: 'high' }); + setAdminConfig({ exposeAllEnv: true }); const res = extractPackageFile(requirements7, 'unused_file_name', {}); expect(res.registryUrls).toEqual([ 'https://pypi.org/pypi/', diff --git a/lib/manager/pip_requirements/extract.ts b/lib/manager/pip_requirements/extract.ts index 87e2ffaec01963..87fc491b410ce2 100644 --- a/lib/manager/pip_requirements/extract.ts +++ b/lib/manager/pip_requirements/extract.ts @@ -84,7 +84,7 @@ export function extractPackageFile( res.registryUrls = registryUrls.map((url) => { // handle the optional quotes in eg. `--extra-index-url "https://foo.bar"` const cleaned = url.replace(/^"/, '').replace(/"$/, ''); - if (getAdminConfig().trustLevel !== 'high') { + if (!getAdminConfig().exposeAllEnv) { return cleaned; } // interpolate any environment variables diff --git a/lib/manager/pip_setup/__snapshots__/index.spec.ts.snap b/lib/manager/pip_setup/__snapshots__/index.spec.ts.snap index 69fad81daa3714..540026674ee265 100644 --- a/lib/manager/pip_setup/__snapshots__/index.spec.ts.snap +++ b/lib/manager/pip_setup/__snapshots__/index.spec.ts.snap @@ -390,9 +390,9 @@ Array [ }, }, Object { - "cmd": " \\"lib/manager/pip_setup/__fixtures__/setup.py\\"", + "cmd": " \\"setup.py\\"", "options": Object { - "cwd": "/tmp/github/some/repo/lib/manager/pip_setup/__fixtures__", + "cwd": "/tmp/github/some/repo", "encoding": "utf-8", "env": Object { "HOME": "/home/user", @@ -449,9 +449,9 @@ Array [ }, }, Object { - "cmd": " \\"lib/manager/pip_setup/__fixtures__/setup.py\\"", + "cmd": " \\"setup.py\\"", "options": Object { - "cwd": "/tmp/github/some/repo/lib/manager/pip_setup/__fixtures__", + "cwd": "/tmp/github/some/repo", "encoding": "utf-8", "env": Object { "HOME": "/home/user", diff --git a/lib/manager/pip_setup/index.spec.ts b/lib/manager/pip_setup/index.spec.ts index 68b51bdef7c8a3..d5f6bad3c68e5d 100644 --- a/lib/manager/pip_setup/index.spec.ts +++ b/lib/manager/pip_setup/index.spec.ts @@ -1,4 +1,3 @@ -import { readFileSync } from 'fs'; import { ExecSnapshots, envMock, @@ -6,18 +5,16 @@ import { mockExecAll, mockExecSequence, } from '../../../test/exec-util'; -import { env, getName } from '../../../test/util'; +import { env, getName, loadFixture } from '../../../test/util'; import { setUtilConfig } from '../../util'; import { BinarySource } from '../../util/exec/common'; import * as fs from '../../util/fs'; import * as extract from './extract'; import { extractPackageFile } from '.'; -const packageFile = 'lib/manager/pip_setup/__fixtures__/setup.py'; -const content = readFileSync(packageFile, 'utf8'); - -const packageFileJson = 'lib/manager/pip_setup/__fixtures__/setup.py.json'; -const jsonContent = readFileSync(packageFileJson, 'utf8'); +const packageFile = 'setup.py'; +const content = loadFixture(__filename, packageFile); +const jsonContent = loadFixture(__filename, 'setup.py.json'); const config = { localDir: '/tmp/github/some/repo', diff --git a/lib/manager/pipenv/extract.spec.ts b/lib/manager/pipenv/extract.spec.ts index 5e491d6bd3eba5..d302208b924b43 100644 --- a/lib/manager/pipenv/extract.spec.ts +++ b/lib/manager/pipenv/extract.spec.ts @@ -1,29 +1,13 @@ -import fs from 'fs'; -import { fs as fsutil, getName } from '../../../test/util'; +import { fs as fsutil, getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; jest.mock('../../util/fs'); -const pipfile1 = fs.readFileSync( - 'lib/manager/pipenv/__fixtures__/Pipfile1', - 'utf8' -); -const pipfile2 = fs.readFileSync( - 'lib/manager/pipenv/__fixtures__/Pipfile2', - 'utf8' -); -const pipfile3 = fs.readFileSync( - 'lib/manager/pipenv/__fixtures__/Pipfile3', - 'utf8' -); -const pipfile4 = fs.readFileSync( - 'lib/manager/pipenv/__fixtures__/Pipfile4', - 'utf8' -); -const pipfile5 = fs.readFileSync( - 'lib/manager/pipenv/__fixtures__/Pipfile5', - 'utf8' -); +const pipfile1 = loadFixture(__filename, 'Pipfile1'); +const pipfile2 = loadFixture(__filename, 'Pipfile2'); +const pipfile3 = loadFixture(__filename, 'Pipfile3'); +const pipfile4 = loadFixture(__filename, 'Pipfile4'); +const pipfile5 = loadFixture(__filename, 'Pipfile5'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/poetry/artifacts.spec.ts b/lib/manager/poetry/artifacts.spec.ts index c8a8aa9cb8f354..92466cf6aae69b 100644 --- a/lib/manager/poetry/artifacts.spec.ts +++ b/lib/manager/poetry/artifacts.spec.ts @@ -1,9 +1,8 @@ import { exec as _exec } from 'child_process'; -import { readFileSync } from 'fs'; import _fs from 'fs-extra'; import { join } from 'upath'; import { envMock, mockExecAll } from '../../../test/exec-util'; -import { mocked } from '../../../test/util'; +import { loadFixture, mocked } from '../../../test/util'; import * as _datasource from '../../datasource'; import { setExecConfig } from '../../util/exec'; import { BinarySource } from '../../util/exec/common'; @@ -12,10 +11,7 @@ import * as _env from '../../util/exec/env'; import * as _hostRules from '../../util/host-rules'; import { updateArtifacts } from './artifacts'; -const pyproject10toml = readFileSync( - 'lib/manager/poetry/__fixtures__/pyproject.10.toml', - 'utf8' -); +const pyproject10toml = loadFixture(__filename, 'pyproject.10.toml'); jest.mock('fs-extra'); jest.mock('child_process'); diff --git a/lib/manager/poetry/extract.spec.ts b/lib/manager/poetry/extract.spec.ts index 8e69b748625532..5991b47a68fd3d 100644 --- a/lib/manager/poetry/extract.spec.ts +++ b/lib/manager/poetry/extract.spec.ts @@ -1,65 +1,21 @@ -import { readFileSync } from 'fs'; -import { fs, getName } from '../../../test/util'; +import { fs, getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; jest.mock('../../util/fs'); -const pyproject1toml = readFileSync( - 'lib/manager/poetry/__fixtures__/pyproject.1.toml', - 'utf8' -); - -const pyproject2toml = readFileSync( - 'lib/manager/poetry/__fixtures__/pyproject.2.toml', - 'utf8' -); - -const pyproject3toml = readFileSync( - 'lib/manager/poetry/__fixtures__/pyproject.3.toml', - 'utf8' -); - -const pyproject4toml = readFileSync( - 'lib/manager/poetry/__fixtures__/pyproject.4.toml', - 'utf8' -); - -const pyproject5toml = readFileSync( - 'lib/manager/poetry/__fixtures__/pyproject.5.toml', - 'utf8' -); - -const pyproject6toml = readFileSync( - 'lib/manager/poetry/__fixtures__/pyproject.6.toml', - 'utf8' -); - -const pyproject7toml = readFileSync( - 'lib/manager/poetry/__fixtures__/pyproject.7.toml', - 'utf8' -); - -const pyproject8toml = readFileSync( - 'lib/manager/poetry/__fixtures__/pyproject.8.toml', - 'utf8' -); - -const pyproject9toml = readFileSync( - 'lib/manager/poetry/__fixtures__/pyproject.9.toml', - 'utf8' -); +const pyproject1toml = loadFixture(__filename, 'pyproject.1.toml'); +const pyproject2toml = loadFixture(__filename, 'pyproject.2.toml'); +const pyproject3toml = loadFixture(__filename, 'pyproject.3.toml'); +const pyproject4toml = loadFixture(__filename, 'pyproject.4.toml'); +const pyproject5toml = loadFixture(__filename, 'pyproject.5.toml'); +const pyproject6toml = loadFixture(__filename, 'pyproject.6.toml'); +const pyproject7toml = loadFixture(__filename, 'pyproject.7.toml'); +const pyproject8toml = loadFixture(__filename, 'pyproject.8.toml'); +const pyproject9toml = loadFixture(__filename, 'pyproject.9.toml'); // pyproject.10.toml use by artifacts - -const pyproject11toml = readFileSync( - 'lib/manager/poetry/__fixtures__/pyproject.11.toml', - 'utf8' -); - -const pyproject11tomlLock = readFileSync( - 'lib/manager/poetry/__fixtures__/pyproject.11.toml.lock', - 'utf8' -); +const pyproject11toml = loadFixture(__filename, 'pyproject.11.toml'); +const pyproject11tomlLock = loadFixture(__filename, 'pyproject.11.toml.lock'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/pre-commit/extract.spec.ts b/lib/manager/pre-commit/extract.spec.ts index 18f4df48b1cff4..fd9ae0b6c53e40 100644 --- a/lib/manager/pre-commit/extract.spec.ts +++ b/lib/manager/pre-commit/extract.spec.ts @@ -1,41 +1,34 @@ -import { readFileSync } from 'fs'; -import { getName, mocked } from '../../../test/util'; +import { getName, loadFixture, mocked } from '../../../test/util'; import * as _hostRules from '../../util/host-rules'; import { extractPackageFile } from './extract'; jest.mock('../../util/host-rules'); const hostRules = mocked(_hostRules); - const filename = '.pre-commit.yaml'; -const complexPrecommitConfig = readFileSync( - 'lib/manager/pre-commit/__fixtures__/complex.pre-commit-config.yaml', - 'utf8' +const complexPrecommitConfig = loadFixture( + __filename, + 'complex.pre-commit-config.yaml' ); - -const examplePrecommitConfig = readFileSync( - 'lib/manager/pre-commit/__fixtures__/.pre-commit-config.yaml', - 'utf8' +const examplePrecommitConfig = loadFixture( + __filename, + '.pre-commit-config.yaml' ); - -const emptyReposPrecommitConfig = readFileSync( - 'lib/manager/pre-commit/__fixtures__/empty_repos.pre-commit-config.yaml', - 'utf8' +const emptyReposPrecommitConfig = loadFixture( + __filename, + 'empty_repos.pre-commit-config.yaml' ); - -const noReposPrecommitConfig = readFileSync( - 'lib/manager/pre-commit/__fixtures__/no_repos.pre-commit-config.yaml', - 'utf8' +const noReposPrecommitConfig = loadFixture( + __filename, + 'no_repos.pre-commit-config.yaml' ); - -const invalidRepoPrecommitConfig = readFileSync( - 'lib/manager/pre-commit/__fixtures__/invalid_repo.pre-commit-config.yaml', - 'utf8' +const invalidRepoPrecommitConfig = loadFixture( + __filename, + 'invalid_repo.pre-commit-config.yaml' ); - -const enterpriseGitPrecommitConfig = readFileSync( - 'lib/manager/pre-commit/__fixtures__/enterprise.pre-commit-config.yaml', - 'utf8' +const enterpriseGitPrecommitConfig = loadFixture( + __filename, + 'enterprise.pre-commit-config.yaml' ); describe(getName(__filename), () => { diff --git a/lib/manager/pub/extract.spec.ts b/lib/manager/pub/extract.spec.ts index 6130772162eded..1b5c74a5d6c203 100644 --- a/lib/manager/pub/extract.spec.ts +++ b/lib/manager/pub/extract.spec.ts @@ -1,16 +1,8 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from '.'; -const brokenYaml = readFileSync( - 'lib/manager/pub/__fixtures__/update.yaml', - 'utf8' -); - -const packageFile = readFileSync( - 'lib/manager/pub/__fixtures__/extract.yaml', - 'utf8' -); +const brokenYaml = loadFixture(__filename, 'update.yaml'); +const packageFile = loadFixture(__filename, 'extract.yaml'); describe(getName(__filename), () => { describe('extractPackageFile', () => { diff --git a/lib/manager/regex/index.spec.ts b/lib/manager/regex/index.spec.ts index 7d69417eeb6d54..0f944b63a9f877 100644 --- a/lib/manager/regex/index.spec.ts +++ b/lib/manager/regex/index.spec.ts @@ -1,22 +1,11 @@ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { logger } from '../../logger'; import type { CustomExtractConfig } from '../types'; import { defaultConfig, extractPackageFile } from '.'; -const dockerfileContent = readFileSync( - resolve(__dirname, `./__fixtures__/Dockerfile`), - 'utf8' -); -const ansibleYamlContent = readFileSync( - resolve(__dirname, `./__fixtures__/ansible.yml`), - 'utf8' -); -const exampleJsonContent = readFileSync( - resolve(__dirname, `./__fixtures__/example.json`), - 'utf8' -); +const dockerfileContent = loadFixture(__filename, `Dockerfile`); +const ansibleYamlContent = loadFixture(__filename, `ansible.yml`); +const exampleJsonContent = loadFixture(__filename, `example.json`); describe(getName(__filename), () => { it('has default config', () => { diff --git a/lib/manager/sbt/extract.spec.ts b/lib/manager/sbt/extract.spec.ts index f4f0453ed4cc41..9ddb9831332636 100644 --- a/lib/manager/sbt/extract.spec.ts +++ b/lib/manager/sbt/extract.spec.ts @@ -1,29 +1,19 @@ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const sbt = readFileSync( - resolve(__dirname, `./__fixtures__/sample.sbt`), - 'utf8' +const sbt = loadFixture(__filename, `sample.sbt`); +const sbtScalaVersionVariable = loadFixture( + __filename, + `scala-version-variable.sbt` ); -const sbtScalaVersionVariable = readFileSync( - resolve(__dirname, `./__fixtures__/scala-version-variable.sbt`), - 'utf8' +const sbtMissingScalaVersion = loadFixture( + __filename, + `missing-scala-version.sbt` ); -const sbtMissingScalaVersion = readFileSync( - resolve(__dirname, `./__fixtures__/missing-scala-version.sbt`), - 'utf8' -); - -const sbtDependencyFile = readFileSync( - resolve(__dirname, `./__fixtures__/dependency-file.scala`), - 'utf8' -); - -const sbtPrivateVariableDependencyFile = readFileSync( - resolve(__dirname, `./__fixtures__/private-variable-dependency-file.scala`), - 'utf8' +const sbtDependencyFile = loadFixture(__filename, `dependency-file.scala`); +const sbtPrivateVariableDependencyFile = loadFixture( + __filename, + `private-variable-dependency-file.scala` ); describe(getName(__filename), () => { diff --git a/lib/manager/setup-cfg/extract.spec.ts b/lib/manager/setup-cfg/extract.spec.ts index 97d564c32e4209..693c3d6d0be9dc 100644 --- a/lib/manager/setup-cfg/extract.spec.ts +++ b/lib/manager/setup-cfg/extract.spec.ts @@ -1,11 +1,7 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const content = readFileSync( - 'lib/manager/setup-cfg/__fixtures__/setup-cfg-1.txt', - 'utf8' -); +const content = loadFixture(__filename, 'setup-cfg-1.txt'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/swift/index.spec.ts b/lib/manager/swift/index.spec.ts index fcc6362a2c3ac1..3c0e90918502ad 100644 --- a/lib/manager/swift/index.spec.ts +++ b/lib/manager/swift/index.spec.ts @@ -1,12 +1,7 @@ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const pkgContent = readFileSync( - resolve(__dirname, `./__fixtures__/SamplePackage.swift`), - 'utf8' -); +const pkgContent = loadFixture(__filename, `SamplePackage.swift`); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/terraform/__snapshots__/extract.spec.ts.snap b/lib/manager/terraform/__snapshots__/extract.spec.ts.snap index a7c0567b1cf466..1fba3faa42c84d 100644 --- a/lib/manager/terraform/__snapshots__/extract.spec.ts.snap +++ b/lib/manager/terraform/__snapshots__/extract.spec.ts.snap @@ -7,7 +7,7 @@ Object { "currentValue": "1.0.1", "datasource": "helm", "depName": "redis", - "depType": "helm", + "depType": "helm_release", "registryUrls": Array [ "https://charts.helm.sh/stable", ], @@ -15,7 +15,7 @@ Object { Object { "datasource": "helm", "depName": "redis", - "depType": "helm", + "depType": "helm_release", "registryUrls": Array [ "https://charts.helm.sh/stable", ], @@ -23,7 +23,7 @@ Object { Object { "datasource": "helm", "depName": "./charts/example", - "depType": "helm", + "depType": "helm_release", "registryUrls": Array [ undefined, ], @@ -33,7 +33,7 @@ Object { "currentValue": "4.0.1", "datasource": "helm", "depName": undefined, - "depType": "helm", + "depType": "helm_release", "registryUrls": Array [ "https://charts.helm.sh/stable", ], @@ -43,7 +43,7 @@ Object { "currentValue": "5.0.1", "datasource": "helm", "depName": "redis", - "depType": "helm", + "depType": "helm_release", "registryUrls": Array [ "https://charts.helm.sh/stable", ], @@ -52,7 +52,7 @@ Object { "currentValue": "6.0.1", "datasource": "helm", "depName": "redis", - "depType": "helm", + "depType": "helm_release", "registryUrls": Array [ undefined, ], @@ -68,86 +68,86 @@ Object { "currentValue": "v1.0.0", "datasource": "github-tags", "depName": "github.com/hashicorp/example", - "depType": "github", + "depType": "module", "lookupName": "hashicorp/example", }, Object { "currentValue": "next", "datasource": "github-tags", "depName": "github.com/hashicorp/example", - "depType": "github", + "depType": "module", "lookupName": "hashicorp/example", }, Object { "currentValue": "tfmodule_one-v0.0.9", "datasource": "github-tags", "depName": "github.com/githubuser/myrepo", - "depType": "github", + "depType": "module", "lookupName": "githubuser/myrepo", }, Object { "currentValue": "v1.0.0", "datasource": "github-tags", "depName": "github.com/hashicorp/example.2.3", - "depType": "github", + "depType": "module", "lookupName": "hashicorp/example.2.3", }, Object { "currentValue": "v1.0.0", "datasource": "github-tags", "depName": "github.com/hashicorp/example.2.3", - "depType": "github", + "depType": "module", "lookupName": "hashicorp/example.2.3", }, Object { "currentValue": "0.1.0", "datasource": "terraform-module", "depName": "hashicorp/consul/aws", - "depType": "terraform", + "depType": "module", }, Object { "currentValue": "v0.1.0", "datasource": "github-tags", "depName": "github.com/tieto-cem/terraform-aws-ecs-task-definition", - "depType": "github", + "depType": "module", "lookupName": "tieto-cem/terraform-aws-ecs-task-definition", }, Object { "currentValue": "v0.1.0", "datasource": "github-tags", "depName": "github.com/tieto-cem/terraform-aws-ecs-task-definition", - "depType": "github", + "depType": "module", "lookupName": "tieto-cem/terraform-aws-ecs-task-definition", }, Object { "currentValue": "v2.0.0", "datasource": "github-tags", "depName": "github.com/hashicorp/example", - "depType": "github", + "depType": "module", "lookupName": "hashicorp/example", }, Object { "datasource": "terraform-module", "depName": "terraform-aws-modules/security-group/aws", - "depType": "terraform", + "depType": "module", }, Object { "currentValue": "<= 2.4.0", "datasource": "terraform-module", "depName": "terraform-aws-modules/security-group/aws", - "depType": "terraform", + "depType": "module", }, Object { "currentValue": "1.28.3", "datasource": "terraform-module", "depName": "particuleio/addons/kubernetes", - "depType": "terraform", + "depType": "module", }, Object { "currentValue": "~> 1.1.0", "datasource": "terraform-module", "depName": "app.terraform.io/example-corp/k8s-cluster/azurerm", - "depType": "terraform", + "depType": "module", "registryUrls": Array [ "https://app.terraform.io", ], @@ -156,7 +156,7 @@ Object { "currentValue": "~> 1.1", "datasource": "terraform-module", "depName": "app.terraform.io/example-corp/k8s-cluster/azurerm", - "depType": "terraform", + "depType": "module", "registryUrls": Array [ "https://app.terraform.io", ], @@ -165,7 +165,7 @@ Object { "currentValue": "~~ 1.1", "datasource": "terraform-module", "depName": "app.terraform.io/example-corp/k8s-cluster/azurerm", - "depType": "terraform", + "depType": "module", "registryUrls": Array [ "https://app.terraform.io", ], @@ -174,7 +174,7 @@ Object { "currentValue": ">= 1.0.0, <= 2.0.0", "datasource": "terraform-module", "depName": "hashicorp/consul/aws", - "depType": "terraform", + "depType": "module", }, Object { "skipReason": "local", @@ -186,89 +186,90 @@ Object { "currentValue": "1.36.1", "datasource": "terraform-provider", "depName": "azurerm", - "depType": "terraform", + "depType": "provider", }, Object { "currentValue": "=2.4", "datasource": "terraform-provider", "depName": "gitlab", - "depType": "terraform", + "depType": "provider", }, Object { "currentValue": "=1.3", "datasource": "terraform-provider", "depName": "gitlab", - "depType": "terraform", + "depType": "provider", }, Object { "datasource": "terraform-provider", "depName": "helm", - "depType": "terraform", + "depType": "provider", }, Object { "currentValue": "V1.9", "datasource": "terraform-provider", "depName": "newrelic", - "depType": "terraform", + "depType": "provider", }, Object { "currentValue": "v1.0.0", "datasource": "git-tags", "depName": "bitbucket.com/hashicorp/example", - "depType": "gitTags", + "depType": "module", "lookupName": "https://bitbucket.com/hashicorp/example", }, Object { "currentValue": "v1.0.0", "datasource": "git-tags", "depName": "bitbucket.com/hashicorp/example", - "depType": "gitTags", + "depType": "module", "lookupName": "https://bitbucket.com/hashicorp/example", }, Object { "currentValue": "next", "datasource": "git-tags", "depName": "bitbucket.com/hashicorp/example", - "depType": "gitTags", + "depType": "module", "lookupName": "https://bitbucket.com/hashicorp/example", }, Object { "currentValue": "v1.0.1", "datasource": "git-tags", "depName": "bitbucket.com/hashicorp/example", - "depType": "gitTags", + "depType": "module", "lookupName": "https://bitbucket.com/hashicorp/example", }, Object { "currentValue": "v1.0.2", "datasource": "git-tags", "depName": "bitbucket.com/hashicorp/example", - "depType": "gitTags", + "depType": "module", "lookupName": "http://bitbucket.com/hashicorp/example", }, Object { "currentValue": "v1.0.3", "datasource": "git-tags", "depName": "bitbucket.com/hashicorp/example", - "depType": "gitTags", + "depType": "module", "lookupName": "ssh://git@bitbucket.com/hashicorp/example", }, Object { "currentValue": ">= 2.7.0", "datasource": "terraform-provider", "depName": "aws", - "depType": "terraform", + "depType": "required_provider", }, Object { "currentValue": ">= 2.0.0", "datasource": "terraform-provider", "depName": "azurerm", - "depType": "terraform", + "depType": "required_provider", }, Object { "currentValue": ">= 0.13", "datasource": "github-tags", "depName": "hashicorp/terraform", + "depType": "required_version", "extractVersion": "v(?.*)$", "lineNumber": 230, }, @@ -276,7 +277,7 @@ Object { "currentValue": "2.7.2", "datasource": "terraform-provider", "depName": "docker", - "depType": "terraform", + "depType": "required_provider", "registryUrls": Array [ "https://releases.hashicorp.com", ], @@ -285,34 +286,34 @@ Object { "currentValue": "2.7.0", "datasource": "terraform-provider", "depName": "aws", - "depType": "terraform", + "depType": "required_provider", "lookupName": "aws", }, Object { "currentValue": "=2.27.0", "datasource": "terraform-provider", "depName": "azurerm", - "depType": "terraform", + "depType": "required_provider", }, Object { "currentValue": "1.2.4", "datasource": "terraform-provider", "depName": "invalid", - "depType": "terraform", + "depType": "required_provider", "skipReason": "unsupported-url", }, Object { "currentValue": "1.2.4", "datasource": "terraform-provider", "depName": "helm", - "depType": "terraform", + "depType": "required_provider", "lookupName": "hashicorp/helm", }, Object { "currentValue": ">= 1.0", "datasource": "terraform-provider", "depName": "kubernetes", - "depType": "terraform", + "depType": "required_provider", "lookupName": "hashicorp/kubernetes", "registryUrls": Array [ "https://terraform.example.com", @@ -324,6 +325,7 @@ Object { "currentValue": "1.7.8", "datasource": "docker", "depName": "nginx", + "depType": "docker_image", "replaceString": "nginx:1.7.8", }, Object { @@ -332,6 +334,7 @@ Object { Object { "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", "datasource": "docker", + "depType": "docker_image", "replaceString": "\${data.docker_registry_image.ubuntu.name}", "skipReason": "contains-variable", }, @@ -341,6 +344,7 @@ Object { "currentValue": "1.7.8", "datasource": "docker", "depName": "nginx", + "depType": "docker_container", "replaceString": "nginx:1.7.8", }, Object { @@ -352,6 +356,7 @@ Object { "currentValue": "v1", "datasource": "docker", "depName": "repo.mycompany.com:8080/foo-service", + "depType": "docker_service", "replaceString": "repo.mycompany.com:8080/foo-service:v1", }, Object { diff --git a/lib/manager/terraform/extract.spec.ts b/lib/manager/terraform/extract.spec.ts index 11f80a1817c796..b617c39b856374 100644 --- a/lib/manager/terraform/extract.spec.ts +++ b/lib/manager/terraform/extract.spec.ts @@ -1,13 +1,12 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const tf1 = readFileSync('lib/manager/terraform/__fixtures__/1.tf', 'utf8'); +const tf1 = loadFixture(__filename, '1.tf'); const tf2 = `module "relative" { source = "../../modules/fe" } `; -const helm = readFileSync('lib/manager/terraform/__fixtures__/helm.tf', 'utf8'); +const helm = loadFixture(__filename, 'helm.tf'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/terraform/extract.ts b/lib/manager/terraform/extract.ts index 4658a80336cbe7..0048bde408dc4a 100644 --- a/lib/manager/terraform/extract.ts +++ b/lib/manager/terraform/extract.ts @@ -5,7 +5,10 @@ import { analyzeTerraformProvider, extractTerraformProvider, } from './providers'; -import { extractTerraformRequiredProviders } from './required-providers'; +import { + analyzeTerraformRequiredProvider, + extractTerraformRequiredProviders, +} from './required-providers'; import { analyseTerraformVersion, extractTerraformRequiredVersion, @@ -98,6 +101,8 @@ export function extractPackageFile(content: string): PackageFile | null { deps.forEach((dep) => { switch (dep.managerData.terraformDependencyType) { case TerraformDependencyTypes.required_providers: + analyzeTerraformRequiredProvider(dep); + break; case TerraformDependencyTypes.provider: analyzeTerraformProvider(dep); break; diff --git a/lib/manager/terraform/modules.spec.ts b/lib/manager/terraform/modules.spec.ts new file mode 100644 index 00000000000000..2dcf3a594f8c3c --- /dev/null +++ b/lib/manager/terraform/modules.spec.ts @@ -0,0 +1,64 @@ +import { getName } from '../../../test/util'; +import { gitTagsRefMatchRegex, githubRefMatchRegex } from './modules'; + +describe(getName(__filename), () => { + describe('githubRefMatchRegex', () => { + it('should split project and tag from source', () => { + const { project, tag } = githubRefMatchRegex.exec( + 'github.com/hashicorp/example?ref=v1.0.0' + ).groups; + expect(project).toBe('hashicorp/example'); + expect(tag).toBe('v1.0.0'); + }); + + it('should parse alpha-numeric characters as well as dots, underscores, and dashes in repo names', () => { + const { project } = githubRefMatchRegex.exec( + 'github.com/hashicorp/example.repo-123?ref=v1.0.0' + ).groups; + expect(project).toBe('hashicorp/example.repo-123'); + }); + }); + describe('gitTagsRefMatchRegex', () => { + it('should split project and tag from source', () => { + const http = gitTagsRefMatchRegex.exec( + 'http://github.com/hashicorp/example?ref=v1.0.0' + ).groups; + const https = gitTagsRefMatchRegex.exec( + 'https://github.com/hashicorp/example?ref=v1.0.0' + ).groups; + const ssh = gitTagsRefMatchRegex.exec( + 'ssh://github.com/hashicorp/example?ref=v1.0.0' + ).groups; + + expect(http.project).toBe('hashicorp/example'); + expect(http.tag).toBe('v1.0.0'); + + expect(https.project).toBe('hashicorp/example'); + expect(https.tag).toBe('v1.0.0'); + + expect(ssh.project).toBe('hashicorp/example'); + expect(ssh.tag).toBe('v1.0.0'); + }); + + it('should parse alpha-numeric characters as well as dots, underscores, and dashes in repo names', () => { + const http = gitTagsRefMatchRegex.exec( + 'http://github.com/hashicorp/example.repo-123?ref=v1.0.0' + ).groups; + const https = gitTagsRefMatchRegex.exec( + 'https://github.com/hashicorp/example.repo-123?ref=v1.0.0' + ).groups; + const ssh = gitTagsRefMatchRegex.exec( + 'ssh://github.com/hashicorp/example.repo-123?ref=v1.0.0' + ).groups; + + expect(http.project).toBe('hashicorp/example.repo-123'); + expect(http.tag).toBe('v1.0.0'); + + expect(https.project).toBe('hashicorp/example.repo-123'); + expect(https.tag).toBe('v1.0.0'); + + expect(ssh.project).toBe('hashicorp/example.repo-123'); + expect(ssh.tag).toBe('v1.0.0'); + }); + }); +}); diff --git a/lib/manager/terraform/modules.ts b/lib/manager/terraform/modules.ts index f3336a1ab7ff09..d4d645565fc0e3 100644 --- a/lib/manager/terraform/modules.ts +++ b/lib/manager/terraform/modules.ts @@ -7,8 +7,8 @@ import type { PackageDependency } from '../types'; import { extractTerraformProvider } from './providers'; import { ExtractionResult, TerraformDependencyTypes } from './util'; -const githubRefMatchRegex = /github.com([/:])(?[^/]+\/[a-z0-9-.]+).*\?ref=(?.*)$/; -const gitTagsRefMatchRegex = /(?:git::)?(?(?:http|https|ssh):\/\/(?:.*@)?(?.*.*\/(?.*\/.*)))\?ref=(?.*)$/; +export const githubRefMatchRegex = /github\.com([/:])(?[^/]+\/[a-z0-9-_.]+).*\?ref=(?.*)$/i; +export const gitTagsRefMatchRegex = /(?:git::)?(?(?:http|https|ssh):\/\/(?:.*@)?(?.*.*\/(?.*\/.*)))\?ref=(?.*)$/; const hostnameMatchRegex = /^(?([\w|\d]+\.)+[\w|\d]+)/; export function extractTerraformModule( @@ -30,12 +30,12 @@ export function analyseTerraformModule(dep: PackageDependency): void { /* eslint-disable no-param-reassign */ if (githubRefMatch) { dep.lookupName = githubRefMatch.groups.project.replace(/\.git$/, ''); - dep.depType = 'github'; + dep.depType = 'module'; dep.depName = 'github.com/' + dep.lookupName; dep.currentValue = githubRefMatch.groups.tag; dep.datasource = datasourceGithubTags.id; } else if (gitTagsRefMatch) { - dep.depType = 'gitTags'; + dep.depType = 'module'; if (gitTagsRefMatch.groups.path.includes('//')) { logger.debug('Terraform module contains subdirectory'); dep.depName = gitTagsRefMatch.groups.path.split('//')[0]; @@ -56,7 +56,7 @@ export function analyseTerraformModule(dep: PackageDependency): void { if (hostnameMatch) { dep.registryUrls = [`https://${hostnameMatch.groups.hostname}`]; } - dep.depType = 'terraform'; + dep.depType = 'module'; dep.depName = moduleParts.join('/'); dep.datasource = datasourceTerraformModule.id; } diff --git a/lib/manager/terraform/providers.ts b/lib/manager/terraform/providers.ts index 7be0e7653a3889..aa06ad0d73609c 100644 --- a/lib/manager/terraform/providers.ts +++ b/lib/manager/terraform/providers.ts @@ -61,7 +61,7 @@ export function extractTerraformProvider( export function analyzeTerraformProvider(dep: PackageDependency): void { /* eslint-disable no-param-reassign */ - dep.depType = 'terraform'; + dep.depType = 'provider'; dep.depName = dep.managerData.moduleName; dep.datasource = datasourceTerraformProvider.id; diff --git a/lib/manager/terraform/readme.md b/lib/manager/terraform/readme.md index 4dd83219332888..9d3138c89cb327 100644 --- a/lib/manager/terraform/readme.md +++ b/lib/manager/terraform/readme.md @@ -1,21 +1,38 @@ -Currently Terraform support is limited to Terraform registry sources and GitHub sources that include SemVer refs, e.g. like `github.com/hashicorp/example?ref=v1.0.0`. +Currently, Terraform supports renovating the following dependencies, where sub points represent hosting options of the dependencies: -Fixed versions like the following will receive a PR whenever there is a newer version available: +- modules + - GitTags + - GithubTags + - TerraformRegistry ( Public and Private ) +- providers ( deprecated in Terraform 0.13.0 ) + - TerraformRegistry ( Public and Private ) +- required_providers block ( Terraform >= 0.13.0) + - TerraformRegistry ( Public and Private ) +- required_version +- helm_release + - chart repository ( Public and Private ) +- docker\_\* + - Docker registry ( Public and Private ) -``` -module "consul" { - source = "hashicorp/consul/aws" - version = "0.0.5" - servers = 3 -} -``` - -The following _range_ constraints are also supported: +Terraform range constraints are supported: - `>= 1.2.0`: version 1.2.0 or newer - `<= 1.2.0`: version 1.2.0 or older - `~> 1.2.0`: any non-beta version >= 1.2.0 and < 1.3.0, e.g. 1.2.X - `~> 1.2`: any non-beta version >= 1.2.0 and < 2.0.0, e.g. 1.X.Y -- `>= 1.0.0`, <= 2.0.0`: any version between 1.0.0 and 2.0.0 inclusive +- `>= 1.0.0, <= 2.0.0`: any version between 1.0.0 and 2.0.0 inclusive + +For fine-grained control, e.g. to turn off only parts of this manager, there are following `depTypes` provided: + +| resource | depType | +| --------------------------- | :---------------: | +| terraform provider | provider | +| required terraform provider | required_provider | +| required terraform version | required_version | +| terraform module | module | +| helm release | helm_release | +| docker container | docker_container | +| docker image | docker_image | +| docker service | docker_service | If you need to change the versioning format, read the [versioning](https://docs.renovatebot.com/modules/versioning/) documentation to learn more. diff --git a/lib/manager/terraform/required-providers.ts b/lib/manager/terraform/required-providers.ts index 9319737a69c94f..44b1186210c23e 100644 --- a/lib/manager/terraform/required-providers.ts +++ b/lib/manager/terraform/required-providers.ts @@ -1,4 +1,5 @@ import type { PackageDependency } from '../types'; +import { analyzeTerraformProvider } from './providers'; import { ExtractionResult, TerraformDependencyTypes, @@ -72,3 +73,10 @@ export function extractTerraformRequiredProviders( } while (line.trim() !== '}'); return { lineNumber, dependencies: deps }; } + +export function analyzeTerraformRequiredProvider(dep: PackageDependency): void { + /* eslint-disable no-param-reassign */ + analyzeTerraformProvider(dep); + dep.depType = `required_provider`; + /* eslint-enable no-param-reassign */ +} diff --git a/lib/manager/terraform/required-version.ts b/lib/manager/terraform/required-version.ts index f5deb89a8b87fd..c8bb1e4dad6f32 100644 --- a/lib/manager/terraform/required-version.ts +++ b/lib/manager/terraform/required-version.ts @@ -48,6 +48,7 @@ export function extractTerraformRequiredVersion( export function analyseTerraformVersion(dep: PackageDependency): void { /* eslint-disable no-param-reassign */ + dep.depType = 'required_version'; dep.datasource = datasourceGithubTags.id; dep.depName = 'hashicorp/terraform'; dep.extractVersion = 'v(?.*)$'; diff --git a/lib/manager/terraform/resources.ts b/lib/manager/terraform/resources.ts index 62c986261c8806..4937a8e98ef4d6 100644 --- a/lib/manager/terraform/resources.ts +++ b/lib/manager/terraform/resources.ts @@ -73,6 +73,7 @@ export function analyseTerraformResource( case TerraformResourceTypes.docker_container: if (dep.managerData.image) { applyDockerDependency(dep, dep.managerData.image); + dep.depType = 'docker_container'; } else { dep.skipReason = SkipReason.InvalidDependencySpecification; } @@ -81,6 +82,7 @@ export function analyseTerraformResource( case TerraformResourceTypes.docker_image: if (dep.managerData.name) { applyDockerDependency(dep, dep.managerData.name); + dep.depType = 'docker_image'; } else { dep.skipReason = SkipReason.InvalidDependencySpecification; } @@ -89,6 +91,7 @@ export function analyseTerraformResource( case TerraformResourceTypes.docker_service: if (dep.managerData.image) { applyDockerDependency(dep, dep.managerData.image); + dep.depType = 'docker_service'; } else { dep.skipReason = SkipReason.InvalidDependencySpecification; } @@ -100,7 +103,7 @@ export function analyseTerraformResource( } else if (checkIfStringIsPath(dep.managerData.chart)) { dep.skipReason = SkipReason.LocalChart; } - dep.depType = 'helm'; + dep.depType = 'helm_release'; dep.registryUrls = [dep.managerData.repository]; dep.depName = dep.managerData.chart; dep.datasource = datasourceHelm.id; diff --git a/lib/manager/terragrunt/extract.spec.ts b/lib/manager/terragrunt/extract.spec.ts index 23e68f7d4e0e80..90626f785bbede 100644 --- a/lib/manager/terragrunt/extract.spec.ts +++ b/lib/manager/terragrunt/extract.spec.ts @@ -1,8 +1,7 @@ -import { readFileSync } from 'fs'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const tg1 = readFileSync('lib/manager/terragrunt/__fixtures__/2.hcl', 'utf8'); +const tg1 = loadFixture(__filename, '2.hcl'); const tg2 = `terragrunt { source = "../../modules/fe" } diff --git a/lib/manager/terragrunt/modules.spec.ts b/lib/manager/terragrunt/modules.spec.ts new file mode 100644 index 00000000000000..2dcf3a594f8c3c --- /dev/null +++ b/lib/manager/terragrunt/modules.spec.ts @@ -0,0 +1,64 @@ +import { getName } from '../../../test/util'; +import { gitTagsRefMatchRegex, githubRefMatchRegex } from './modules'; + +describe(getName(__filename), () => { + describe('githubRefMatchRegex', () => { + it('should split project and tag from source', () => { + const { project, tag } = githubRefMatchRegex.exec( + 'github.com/hashicorp/example?ref=v1.0.0' + ).groups; + expect(project).toBe('hashicorp/example'); + expect(tag).toBe('v1.0.0'); + }); + + it('should parse alpha-numeric characters as well as dots, underscores, and dashes in repo names', () => { + const { project } = githubRefMatchRegex.exec( + 'github.com/hashicorp/example.repo-123?ref=v1.0.0' + ).groups; + expect(project).toBe('hashicorp/example.repo-123'); + }); + }); + describe('gitTagsRefMatchRegex', () => { + it('should split project and tag from source', () => { + const http = gitTagsRefMatchRegex.exec( + 'http://github.com/hashicorp/example?ref=v1.0.0' + ).groups; + const https = gitTagsRefMatchRegex.exec( + 'https://github.com/hashicorp/example?ref=v1.0.0' + ).groups; + const ssh = gitTagsRefMatchRegex.exec( + 'ssh://github.com/hashicorp/example?ref=v1.0.0' + ).groups; + + expect(http.project).toBe('hashicorp/example'); + expect(http.tag).toBe('v1.0.0'); + + expect(https.project).toBe('hashicorp/example'); + expect(https.tag).toBe('v1.0.0'); + + expect(ssh.project).toBe('hashicorp/example'); + expect(ssh.tag).toBe('v1.0.0'); + }); + + it('should parse alpha-numeric characters as well as dots, underscores, and dashes in repo names', () => { + const http = gitTagsRefMatchRegex.exec( + 'http://github.com/hashicorp/example.repo-123?ref=v1.0.0' + ).groups; + const https = gitTagsRefMatchRegex.exec( + 'https://github.com/hashicorp/example.repo-123?ref=v1.0.0' + ).groups; + const ssh = gitTagsRefMatchRegex.exec( + 'ssh://github.com/hashicorp/example.repo-123?ref=v1.0.0' + ).groups; + + expect(http.project).toBe('hashicorp/example.repo-123'); + expect(http.tag).toBe('v1.0.0'); + + expect(https.project).toBe('hashicorp/example.repo-123'); + expect(https.tag).toBe('v1.0.0'); + + expect(ssh.project).toBe('hashicorp/example.repo-123'); + expect(ssh.tag).toBe('v1.0.0'); + }); + }); +}); diff --git a/lib/manager/terragrunt/modules.ts b/lib/manager/terragrunt/modules.ts index 77ae489ab3e92b..e11e12e20bf95f 100644 --- a/lib/manager/terragrunt/modules.ts +++ b/lib/manager/terragrunt/modules.ts @@ -7,8 +7,8 @@ import type { PackageDependency } from '../types'; import { extractTerragruntProvider } from './providers'; import { ExtractionResult, TerragruntDependencyTypes } from './util'; -const githubRefMatchRegex = /github.com([/:])(?[^/]+\/[a-z0-9-.]+).*\?ref=(?.*)$/; -const gitTagsRefMatchRegex = /(?:git::)?(?(?:http|https|ssh):\/\/(?:.*@)?(?.*.*\/(?.*\/.*)))\?ref=(?.*)$/; +export const githubRefMatchRegex = /github\.com([/:])(?[^/]+\/[a-z0-9-_.]+).*\?ref=(?.*)$/i; +export const gitTagsRefMatchRegex = /(?:git::)?(?(?:http|https|ssh):\/\/(?:.*@)?(?.*.*\/(?.*\/.*)))\?ref=(?.*)$/; const hostnameMatchRegex = /^(?([\w|\d]+\.)+[\w|\d]+)/; export function extractTerragruntModule( diff --git a/lib/manager/travis/extract.spec.ts b/lib/manager/travis/extract.spec.ts index 08ade541405730..8335256c0c672d 100644 --- a/lib/manager/travis/extract.spec.ts +++ b/lib/manager/travis/extract.spec.ts @@ -1,12 +1,7 @@ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { extractPackageFile } from './extract'; -const invalidYAML = readFileSync( - resolve('lib/manager/travis/__fixtures__/invalid.yml'), - 'utf8' -); +const invalidYAML = loadFixture(__filename, 'invalid.yml'); describe(getName(__filename), () => { describe('extractPackageFile()', () => { diff --git a/lib/manager/travis/update.spec.ts b/lib/manager/travis/update.spec.ts index eee1acf5a09ba4..50518739cda118 100644 --- a/lib/manager/travis/update.spec.ts +++ b/lib/manager/travis/update.spec.ts @@ -1,12 +1,7 @@ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { updateDependency } from './update'; -const content = readFileSync( - resolve('lib/manager/travis/__fixtures__/travis.yml'), - 'utf8' -); +const content = loadFixture(__filename, 'travis.yml'); describe(getName(__filename), () => { describe('updateDependency', () => { diff --git a/lib/manager/types.ts b/lib/manager/types.ts index 2c167ecc539103..5cccc8a481b3ab 100644 --- a/lib/manager/types.ts +++ b/lib/manager/types.ts @@ -23,7 +23,7 @@ export interface ExtractConfig extends ManagerConfig { endpoint?: string; gradle?: { timeout?: number }; aliases?: Record; - ignoreNpmrcFile?: boolean; + npmrc?: string; yarnrc?: string; skipInstalls?: boolean; versioning?: string; @@ -90,7 +90,6 @@ export interface PackageFile> datasource?: string; registryUrls?: string[]; deps: PackageDependency[]; - ignoreNpmrcFile?: boolean; lernaClient?: string; lernaPackages?: string[]; mavenProps?: Record; @@ -278,6 +277,7 @@ export interface PostUpdateConfig extends ManagerConfig, Record { updatedPackageFiles?: File[]; postUpdateOptions?: string[]; skipInstalls?: boolean; + ignoreScripts?: boolean; platform?: string; upgrades?: Upgrade[]; diff --git a/lib/platform/github/index.spec.ts b/lib/platform/github/index.spec.ts index ebcd4a20d0d65d..f6002def84c42c 100644 --- a/lib/platform/github/index.spec.ts +++ b/lib/platform/github/index.spec.ts @@ -1,7 +1,6 @@ -import fs from 'fs-extra'; import { DateTime } from 'luxon'; import * as httpMock from '../../../test/http-mock'; -import { getName, mocked } from '../../../test/util'; +import { getName, loadFixture, mocked } from '../../../test/util'; import { REPOSITORY_NOT_FOUND, REPOSITORY_RENAMED, @@ -42,13 +41,13 @@ describe(getName(__filename), () => { httpMock.reset(); }); - const graphqlOpenPullRequests = fs.readFileSync( - 'lib/platform/github/__fixtures__/graphql/pullrequest-1.json', - 'utf8' + const graphqlOpenPullRequests = loadFixture( + __filename, + 'graphql/pullrequest-1.json' ); - const graphqlClosedPullRequests = fs.readFileSync( - 'lib/platform/github/__fixtures__/graphql/pullrequests-closed.json', - 'utf8' + const graphqlClosedPullRequests = loadFixture( + __filename, + 'graphql/pullrequests-closed.json' ); describe('initPlatform()', () => { diff --git a/lib/platform/gitlab/__snapshots__/index.spec.ts.snap b/lib/platform/gitlab/__snapshots__/index.spec.ts.snap index e5778843549a5f..f63b6d3f9fa792 100644 --- a/lib/platform/gitlab/__snapshots__/index.spec.ts.snap +++ b/lib/platform/gitlab/__snapshots__/index.spec.ts.snap @@ -798,6 +798,83 @@ Array [ ] `; +exports[`platform/gitlab/index filterUnavailableUsers(users) filters users that are busy 1`] = ` +Array [ + "john", +] +`; + +exports[`platform/gitlab/index filterUnavailableUsers(users) filters users that are busy 2`] = ` +Array [ + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer abc123", + "host": "gitlab.com", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://gitlab.com/api/v4/users/maria/status", + }, + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer abc123", + "host": "gitlab.com", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://gitlab.com/api/v4/users/john/status", + }, +] +`; + +exports[`platform/gitlab/index filterUnavailableUsers(users) keeps users with failing requests 1`] = ` +Array [ + "maria", +] +`; + +exports[`platform/gitlab/index filterUnavailableUsers(users) keeps users with failing requests 2`] = ` +Array [ + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer abc123", + "host": "gitlab.com", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://gitlab.com/api/v4/users/maria/status", + }, +] +`; + +exports[`platform/gitlab/index filterUnavailableUsers(users) keeps users with missing availability 1`] = ` +Array [ + "maria", +] +`; + +exports[`platform/gitlab/index filterUnavailableUsers(users) keeps users with missing availability 2`] = ` +Array [ + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "authorization": "Bearer abc123", + "host": "gitlab.com", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://gitlab.com/api/v4/users/maria/status", + }, +] +`; + exports[`platform/gitlab/index findIssue() finds issue 1`] = ` Array [ Object { diff --git a/lib/platform/gitlab/http.ts b/lib/platform/gitlab/http.ts index 51a836de629ab2..bab2b0f80378cd 100644 --- a/lib/platform/gitlab/http.ts +++ b/lib/platform/gitlab/http.ts @@ -1,4 +1,6 @@ +import { logger } from '../../logger'; import { GitlabHttp } from '../../util/http/gitlab'; +import type { GitlabUserStatus } from './types'; export const gitlabApi = new GitlabHttp(); @@ -7,3 +9,14 @@ export async function getUserID(username: string): Promise { await gitlabApi.getJson<{ id: number }[]>(`users?username=${username}`) ).body[0].id; } + +export async function isUserBusy(user: string): Promise { + try { + const url = `/users/${user}/status`; + const userStatus = (await gitlabApi.getJson(url)).body; + return userStatus.availability === 'busy'; + } catch (err) { + logger.warn({ err }, 'Failed to get user status'); + return false; + } +} diff --git a/lib/platform/gitlab/index.spec.ts b/lib/platform/gitlab/index.spec.ts index b60e0ac2eed26b..9f31a17ae240cb 100644 --- a/lib/platform/gitlab/index.spec.ts +++ b/lib/platform/gitlab/index.spec.ts @@ -1614,4 +1614,44 @@ These updates have all been created already. Click a checkbox below to force a r expect(httpMock.getTrace()).toMatchSnapshot(); }); }); + describe('filterUnavailableUsers(users)', () => { + it('filters users that are busy', async () => { + httpMock + .scope(gitlabApiHost) + .get('/api/v4/users/maria/status') + .reply(200, { + availability: 'busy', + }) + .get('/api/v4/users/john/status') + .reply(200, { + availability: 'not_set', + }); + const filteredUsers = await gitlab.filterUnavailableUsers([ + 'maria', + 'john', + ]); + expect(filteredUsers).toMatchSnapshot(); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('keeps users with missing availability', async () => { + httpMock + .scope(gitlabApiHost) + .get('/api/v4/users/maria/status') + .reply(200, {}); + const filteredUsers = await gitlab.filterUnavailableUsers(['maria']); + expect(filteredUsers).toMatchSnapshot(); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + + it('keeps users with failing requests', async () => { + httpMock + .scope(gitlabApiHost) + .get('/api/v4/users/maria/status') + .reply(404); + const filteredUsers = await gitlab.filterUnavailableUsers(['maria']); + expect(filteredUsers).toMatchSnapshot(); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + }); }); diff --git a/lib/platform/gitlab/index.ts b/lib/platform/gitlab/index.ts index 8ea18a0cd42b3b..6faaf766cc14ce 100755 --- a/lib/platform/gitlab/index.ts +++ b/lib/platform/gitlab/index.ts @@ -40,7 +40,7 @@ import type { UpdatePrConfig, } from '../types'; import { smartTruncate } from '../utils/pr-body'; -import { getUserID, gitlabApi } from './http'; +import { getUserID, gitlabApi, isUserBusy } from './http'; import { getMR, updateMR } from './merge-request'; import type { GitLabMergeRequest, @@ -1067,3 +1067,15 @@ export async function ensureCommentRemoval({ export function getVulnerabilityAlerts(): Promise { return Promise.resolve([]); } + +export async function filterUnavailableUsers( + users: string[] +): Promise { + const filteredUsers = []; + for (const user of users) { + if (!(await isUserBusy(user))) { + filteredUsers.push(user); + } + } + return filteredUsers; +} diff --git a/lib/platform/gitlab/types.ts b/lib/platform/gitlab/types.ts index 607b3e973ea0c1..f35eba0b51b4c5 100644 --- a/lib/platform/gitlab/types.ts +++ b/lib/platform/gitlab/types.ts @@ -51,3 +51,11 @@ export interface RepoResponse { merge_method: MergeMethod; path_with_namespace: string; } + +// See https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/types/user_status_type.rb +export interface GitlabUserStatus { + message?: string; + message_html?: string; + emoji?: string; + availability: 'not_set' | 'busy'; +} diff --git a/lib/platform/types.ts b/lib/platform/types.ts index 89345dc4518d35..467dafdd67cf1a 100644 --- a/lib/platform/types.ts +++ b/lib/platform/types.ts @@ -177,4 +177,5 @@ export interface Platform { ): Promise; getBranchPr(branchName: string): Promise; initPlatform(config: PlatformParams): Promise; + filterUnavailableUsers?(users: string[]): Promise; } diff --git a/lib/platform/utils/pr-body.spec.ts b/lib/platform/utils/pr-body.spec.ts index ab0b3a7cfece7d..873b12529919c6 100644 --- a/lib/platform/utils/pr-body.spec.ts +++ b/lib/platform/utils/pr-body.spec.ts @@ -1,15 +1,9 @@ -import fs from 'fs-extra'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { smartTruncate } from './pr-body'; +const prBody = loadFixture(__filename, 'pr-body.txt'); + describe(getName(__filename), () => { - let prBody: string; - beforeAll(async () => { - prBody = await fs.readFile( - 'lib/platform/utils/__fixtures__/pr-body.txt', - 'utf8' - ); - }); describe('.smartTruncate', () => { it('truncates to 1000', () => { const body = smartTruncate(prBody, 1000); diff --git a/lib/platform/utils/read-only-issue-body.spec.ts b/lib/platform/utils/read-only-issue-body.spec.ts index 440d4b82acaa56..ef98dedc3d7ef9 100644 --- a/lib/platform/utils/read-only-issue-body.spec.ts +++ b/lib/platform/utils/read-only-issue-body.spec.ts @@ -1,15 +1,9 @@ -import fs from 'fs-extra'; -import { getName } from '../../../test/util'; +import { getName, loadFixture } from '../../../test/util'; import { readOnlyIssueBody } from './read-only-issue-body'; +const issueBody = loadFixture(__filename, 'issue-body.txt'); + describe(getName(__filename), () => { - let issueBody: string; - beforeAll(async () => { - issueBody = await fs.readFile( - 'lib/platform/utils/__fixtures__/issue-body.txt', - 'utf8' - ); - }); describe('.readOnlyIssueBody', () => { it('removes all checkbox formatting', () => { expect(readOnlyIssueBody(issueBody)).toEqual( diff --git a/lib/util/exec/env.spec.ts b/lib/util/exec/env.spec.ts index e3a0eabc258ad3..ebc1c16900a513 100644 --- a/lib/util/exec/env.spec.ts +++ b/lib/util/exec/env.spec.ts @@ -58,7 +58,7 @@ describe('getChildProcess environment when trustlevel set to low', () => { describe('getChildProcessEnv when trustlevel set to high', () => { it('returns process.env if trustlevel set to high', () => { - setAdminConfig({ trustLevel: 'high' }); + setAdminConfig({ exposeAllEnv: true }); expect(getChildProcessEnv()).toMatchObject(process.env); }); }); diff --git a/lib/util/exec/env.ts b/lib/util/exec/env.ts index 38950e4e867a95..faffd61bf81526 100644 --- a/lib/util/exec/env.ts +++ b/lib/util/exec/env.ts @@ -17,7 +17,7 @@ export function getChildProcessEnv( customEnvVars: string[] = [] ): NodeJS.ProcessEnv { const env: NodeJS.ProcessEnv = {}; - if (getAdminConfig().trustLevel === 'high') { + if (getAdminConfig().exposeAllEnv) { return { ...env, ...process.env }; } const envVars = [...basicEnvVars, ...customEnvVars]; diff --git a/lib/util/exec/exec.spec.ts b/lib/util/exec/exec.spec.ts index f5a67fbda53284..e5db81a628a4e8 100644 --- a/lib/util/exec/exec.spec.ts +++ b/lib/util/exec/exec.spec.ts @@ -194,7 +194,7 @@ describe(getName(__filename), () => { maxBuffer: 10485760, }, ], - adminConfig: { trustLevel: 'high' }, + adminConfig: { exposeAllEnv: true }, }, ], diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts index 3ced1d68ead6f5..829f18abe8cdcd 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -488,7 +488,6 @@ export async function isBranchModified(branchName: string): Promise { ).trim(); const { gitAuthorEmail } = config; if ( - lastAuthor === process.env.RENOVATE_LEGACY_GIT_AUTHOR_EMAIL || // remove in next major release lastAuthor === gitAuthorEmail || config.ignoredAuthors.some((ignoredAuthor) => lastAuthor === ignoredAuthor) ) { diff --git a/lib/workers/branch/auto-replace.spec.ts b/lib/workers/branch/auto-replace.spec.ts index 0bf06f454badb6..125d9237d34620 100644 --- a/lib/workers/branch/auto-replace.spec.ts +++ b/lib/workers/branch/auto-replace.spec.ts @@ -1,15 +1,10 @@ -import { readFileSync } from 'fs'; -import { resolve } from 'upath'; -import { defaultConfig, getName } from '../../../test/util'; +import { defaultConfig, getName, loadFixture } from '../../../test/util'; import { WORKER_FILE_UPDATE_FAILED } from '../../constants/error-messages'; import { extractPackageFile } from '../../manager/html'; import type { BranchUpgradeConfig } from '../types'; import { doAutoReplace } from './auto-replace'; -const sampleHtml = readFileSync( - resolve(__dirname, `../../manager/html/__fixtures__/sample.html`), - 'utf8' -); +const sampleHtml = loadFixture(__filename, 'sample.html', `../../manager/html`); jest.mock('../../util/fs'); diff --git a/lib/workers/branch/index.spec.ts b/lib/workers/branch/index.spec.ts index a38f6cce331b99..097e78b5490a7e 100644 --- a/lib/workers/branch/index.spec.ts +++ b/lib/workers/branch/index.spec.ts @@ -372,6 +372,7 @@ describe(getName(__filename), () => { await branchWorker.processBranch(config); expect(automerge.tryBranchAutomerge).toHaveBeenCalledTimes(1); expect(prWorker.ensurePr).toHaveBeenCalledTimes(0); + expect(git.deleteBranch).toHaveBeenCalledTimes(0); }); it('returns if branch exists and prCreation set to approval', async () => { getUpdated.getUpdatedPackageFiles.mockResolvedValueOnce({ @@ -736,7 +737,7 @@ describe(getName(__filename), () => { const adminConfig = { allowedPostUpgradeCommands: ['^echo {{{versioning}}}$'], allowPostUpgradeCommandTemplating: true, - trustLevel: 'high', + exposeAllEnv: true, }; setAdminConfig(adminConfig); @@ -816,7 +817,7 @@ describe(getName(__filename), () => { const adminConfig = { allowedPostUpgradeCommands: ['^exit 1$'], allowPostUpgradeCommandTemplating: true, - trustLevel: 'high', + exposeAllEnv: true, }; setAdminConfig(adminConfig); @@ -885,7 +886,7 @@ describe(getName(__filename), () => { const adminConfig = { allowedPostUpgradeCommands: ['^echo {{{versioning}}}$'], allowPostUpgradeCommandTemplating: false, - trustLevel: 'high', + exposeAllEnv: true, }; setAdminConfig(adminConfig); const result = await branchWorker.processBranch({ @@ -965,7 +966,7 @@ describe(getName(__filename), () => { const adminConfig = { allowedPostUpgradeCommands: ['^echo {{{depName}}}$'], allowPostUpgradeCommandTemplating: true, - trustLevel: 'high', + exposeAllEnv: true, }; setAdminConfig(adminConfig); diff --git a/lib/workers/branch/index.ts b/lib/workers/branch/index.ts index ae25f57494cff1..d5359e2028110a 100644 --- a/lib/workers/branch/index.ts +++ b/lib/workers/branch/index.ts @@ -372,7 +372,11 @@ export async function processBranch( const mergeStatus = await tryBranchAutomerge(config); logger.debug(`mergeStatus=${mergeStatus}`); if (mergeStatus === 'automerged') { - await deleteBranchSilently(config.branchName); + if (getAdminConfig().dryRun) { + logger.info('DRY-RUN: Would delete branch' + config.branchName); + } else { + await deleteBranchSilently(config.branchName); + } logger.debug('Branch is automerged - returning'); return { branchExists: false, result: BranchResult.Automerged }; } diff --git a/lib/workers/global/index.ts b/lib/workers/global/index.ts index 0d7978fb735f75..d7715983fe8c8c 100644 --- a/lib/workers/global/index.ts +++ b/lib/workers/global/index.ts @@ -5,12 +5,14 @@ import { satisfies } from 'semver'; import upath from 'upath'; import * as pkg from '../../../package.json'; import * as configParser from '../../config'; +import { resolveConfigPresets } from '../../config/presets'; import { validateConfigSecrets } from '../../config/secrets'; import type { GlobalConfig, RenovateConfig, RenovateRepository, } from '../../config/types'; +import { CONFIG_PRESETS_INVALID } from '../../constants/error-messages'; import { getProblems, logger, setMeta } from '../../logger'; import { setUtilConfig } from '../../util'; import * as hostRules from '../../util/host-rules'; @@ -70,6 +72,14 @@ function checkEnv(): void { } } +export async function validatePresets(config: GlobalConfig): Promise { + try { + await resolveConfigPresets(config); + } catch (err) /* istanbul ignore next */ { + throw new Error(CONFIG_PRESETS_INVALID); + } +} + export async function start(): Promise { let config: GlobalConfig; try { @@ -78,6 +88,8 @@ export async function start(): Promise { // initialize all submodules config = await globalInitialize(config); + await validatePresets(config); + checkEnv(); // validate secrets. Will throw and abort if invalid diff --git a/lib/workers/pr/__snapshots__/index.spec.ts.snap b/lib/workers/pr/__snapshots__/index.spec.ts.snap index 13361625d53546..a3941ef731a1e4 100644 --- a/lib/workers/pr/__snapshots__/index.spec.ts.snap +++ b/lib/workers/pr/__snapshots__/index.spec.ts.snap @@ -184,6 +184,28 @@ Array [ ] `; +exports[`workers/pr/index ensurePr should filter assignees and reviewers based on their availability 1`] = ` +Array [ + Array [ + undefined, + Array [ + "foo", + ], + ], +] +`; + +exports[`workers/pr/index ensurePr should filter assignees and reviewers based on their availability 2`] = ` +Array [ + Array [ + undefined, + Array [ + "foo", + ], + ], +] +`; + exports[`workers/pr/index ensurePr should return modified existing PR 1`] = ` Object { "body": "This PR contains the following updates:\\n\\n| Package | Type | Update | Change |\\n|---|---|---|---|\\n| [dummy](https://dummy.com) ([source](https://github.com/renovateapp/dummy), [changelog](https://github.com/renovateapp/dummy/changelog.md)) | devDependencies | minor | \`1.0.0\` -> \`1.1.0\` |\\n\\n---\\n\\n### Release Notes\\n\\n
\\nrenovateapp/dummy\\n\\n### [\`v1.1.0\`](https://github.com/renovateapp/dummy/compare/v1.0.0...v1.1.0)\\n\\n[Compare Source](https://github.com/renovateapp/dummy/compare/v1.0.0...v1.1.0)\\n\\n
\\n\\n---\\n\\n### Configuration\\n\\n:date: **Schedule**: \\"before 5am\\" (UTC).\\n\\n:vertical_traffic_light: **Automerge**: Enabled.\\n\\n:recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.\\n\\n:no_bell: **Ignore**: Close this PR and you won't be reminded about this update again.\\n\\n---\\n\\n - [ ] If you want to rebase/retry this PR, check this box.\\n\\n---\\n\\nThis PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).", diff --git a/lib/workers/pr/changelog/release-notes.spec.ts b/lib/workers/pr/changelog/release-notes.spec.ts index aca57ac8c44f2b..f28f25f667f182 100644 --- a/lib/workers/pr/changelog/release-notes.spec.ts +++ b/lib/workers/pr/changelog/release-notes.spec.ts @@ -1,7 +1,6 @@ -import fs from 'fs-extra'; import { DateTime } from 'luxon'; import * as httpMock from '../../../../test/http-mock'; -import { getName, mocked } from '../../../../test/util'; +import { getName, loadFixture, mocked } from '../../../../test/util'; import * as _hostRules from '../../../util/host-rules'; import { addReleaseNotes, @@ -16,33 +15,19 @@ jest.mock('../../../util/host-rules'); const hostRules = mocked(_hostRules); -const angularJsChangelogMd = fs.readFileSync( - 'lib/workers/pr/__fixtures__/angular-js.md', - 'utf8' +const angularJsChangelogMd = loadFixture(__filename, 'angular-js.md', '..'); +const jestChangelogMd = loadFixture(__filename, 'jest.md', '..'); +const jsYamlChangelogMd = loadFixture(__filename, 'js-yaml.md', '..'); +const yargsChangelogMd = loadFixture(__filename, 'yargs.md', '..'); +const adapterutilsChangelogMd = loadFixture( + __filename, + 'adapter-utils.md', + '..' ); -const jestChangelogMd = fs.readFileSync( - 'lib/workers/pr/__fixtures__/jest.md', - 'utf8' -); - -const jsYamlChangelogMd = fs.readFileSync( - 'lib/workers/pr/__fixtures__/js-yaml.md', - 'utf8' -); - -const yargsChangelogMd = fs.readFileSync( - 'lib/workers/pr/__fixtures__/yargs.md', - 'utf8' -); - -const adapterutilsChangelogMd = fs.readFileSync( - 'lib/workers/pr/__fixtures__/adapter-utils.md', - 'utf8' -); - -const gitterWebappChangelogMd = fs.readFileSync( - 'lib/workers/pr/__fixtures__/gitter-webapp.md', - 'utf8' +const gitterWebappChangelogMd = loadFixture( + __filename, + 'gitter-webapp.md', + '..' ); const githubTreeResponse = { diff --git a/lib/workers/pr/index.spec.ts b/lib/workers/pr/index.spec.ts index 47d8de271219cd..507d51cda845c7 100644 --- a/lib/workers/pr/index.spec.ts +++ b/lib/workers/pr/index.spec.ts @@ -410,6 +410,16 @@ describe(getName(__filename), () => { expect(platform.addReviewers).toHaveBeenCalledTimes(1); expect(platform.addReviewers.mock.calls).toMatchSnapshot(); }); + it('should filter assignees and reviewers based on their availability', async () => { + config.assignees = ['foo', 'bar']; + config.reviewers = ['foo', 'bar']; + config.filterUnavailableUsers = true; + platform.filterUnavailableUsers = jest.fn(); + platform.filterUnavailableUsers.mockResolvedValue(['foo']); + await prWorker.ensurePr(config); + expect(platform.addAssignees.mock.calls).toMatchSnapshot(); + expect(platform.addReviewers.mock.calls).toMatchSnapshot(); + }); it('should determine assignees from code owners', async () => { config.assigneesFromCodeOwners = true; codeOwnersMock.codeOwnersForPr.mockResolvedValueOnce(['@john', '@maria']); diff --git a/lib/workers/pr/index.ts b/lib/workers/pr/index.ts index 0ddb2aab61b461..92efafb868ae10 100644 --- a/lib/workers/pr/index.ts +++ b/lib/workers/pr/index.ts @@ -33,6 +33,15 @@ async function addCodeOwners( return [...new Set(assigneesOrReviewers.concat(await codeOwnersForPr(pr)))]; } +function filterUnavailableUsers( + config: RenovateConfig, + users: string[] +): Promise { + return config.filterUnavailableUsers && platform.filterUnavailableUsers + ? platform.filterUnavailableUsers(users) + : Promise.resolve(users); +} + export async function addAssigneesReviewers( config: RenovateConfig, pr: Pr @@ -41,6 +50,7 @@ export async function addAssigneesReviewers( if (config.assigneesFromCodeOwners) { assignees = await addCodeOwners(assignees, pr); } + assignees = await filterUnavailableUsers(config, assignees); if (assignees.length > 0) { try { assignees = assignees.map(noLeadingAtSymbol); @@ -70,6 +80,7 @@ export async function addAssigneesReviewers( if (config.additionalReviewers.length > 0) { reviewers = reviewers.concat(config.additionalReviewers); } + reviewers = await filterUnavailableUsers(config, reviewers); if (reviewers.length > 0) { try { reviewers = [...new Set(reviewers.map(noLeadingAtSymbol))]; diff --git a/lib/workers/repository/dependency-dashboard.spec.ts b/lib/workers/repository/dependency-dashboard.spec.ts index 67bf63f17c86fb..35f20a00daf67e 100644 --- a/lib/workers/repository/dependency-dashboard.spec.ts +++ b/lib/workers/repository/dependency-dashboard.spec.ts @@ -1,10 +1,10 @@ -import fs from 'fs'; import { ERROR, WARN } from 'bunyan'; import { mock } from 'jest-mock-extended'; import { RenovateConfig, getConfig, getName, + loadFixture, logger, platform, } from '../../../test/util'; @@ -239,10 +239,7 @@ describe(getName(__filename), () => { config.dependencyDashboardTitle ); expect(platform.ensureIssue.mock.calls[0][0].body).toBe( - fs.readFileSync( - 'lib/workers/repository/__fixtures__/master-issue_with_8_PR.txt', - 'utf8' - ) + loadFixture(__filename, 'master-issue_with_8_PR.txt') ); expect(platform.getBranchPr).toHaveBeenCalledTimes(0); expect(platform.findPr).toHaveBeenCalledTimes(0); @@ -282,10 +279,7 @@ describe(getName(__filename), () => { config.dependencyDashboardTitle ); expect(platform.ensureIssue.mock.calls[0][0].body).toBe( - fs.readFileSync( - 'lib/workers/repository/__fixtures__/master-issue_with_2_PR_edited.txt', - 'utf8' - ) + loadFixture(__filename, 'master-issue_with_2_PR_edited.txt') ); expect(platform.getBranchPr).toHaveBeenCalledTimes(2); expect(platform.getBranchPr.mock.calls[0][0]).toBe('branchName1'); @@ -335,10 +329,7 @@ describe(getName(__filename), () => { config.dependencyDashboardTitle ); expect(platform.ensureIssue.mock.calls[0][0].body).toBe( - fs.readFileSync( - 'lib/workers/repository/__fixtures__/master-issue_with_3_PR_in_progress.txt', - 'utf8' - ) + loadFixture(__filename, 'master-issue_with_3_PR_in_progress.txt') ); expect(platform.getBranchPr).toHaveBeenCalledTimes(3); expect(platform.getBranchPr.mock.calls[0][0]).toBe('branchName1'); @@ -382,10 +373,7 @@ describe(getName(__filename), () => { config.dependencyDashboardTitle ); expect(platform.ensureIssue.mock.calls[0][0].body).toBe( - fs.readFileSync( - 'lib/workers/repository/__fixtures__/master-issue_with_2_PR_closed_ignored.txt', - 'utf8' - ) + loadFixture(__filename, 'master-issue_with_2_PR_closed_ignored.txt') ); expect(platform.getBranchPr).toHaveBeenCalledTimes(0); expect(platform.findPr).toHaveBeenCalledTimes(2); @@ -443,10 +431,7 @@ describe(getName(__filename), () => { config.dependencyDashboardTitle ); expect(platform.ensureIssue.mock.calls[0][0].body).toBe( - fs.readFileSync( - 'lib/workers/repository/__fixtures__/master-issue_with_3_PR_in_approval.txt', - 'utf8' - ) + loadFixture(__filename, 'master-issue_with_3_PR_in_approval.txt') ); expect(platform.findPr).toHaveBeenCalledTimes(0); diff --git a/lib/workers/repository/extract/__snapshots__/manager-files.spec.ts.snap b/lib/workers/repository/extract/__snapshots__/manager-files.spec.ts.snap index 7b05cb15e52b9f..52bad56bc98bae 100644 --- a/lib/workers/repository/extract/__snapshots__/manager-files.spec.ts.snap +++ b/lib/workers/repository/extract/__snapshots__/manager-files.spec.ts.snap @@ -14,7 +14,6 @@ Array [ "prettyDepType": "dependency", }, ], - "ignoreNpmrcFile": undefined, "lernaClient": undefined, "lernaPackages": undefined, "managerData": Object { diff --git a/lib/workers/repository/init/config.ts b/lib/workers/repository/init/config.ts index fb802acef351f8..15a92b1e2f9b1a 100644 --- a/lib/workers/repository/init/config.ts +++ b/lib/workers/repository/init/config.ts @@ -203,7 +203,6 @@ export async function mergeRenovateConfig( 'Ignoring any .npmrc files in repository due to configured npmrc' ); npmApi.setNpmrc(resolvedConfig.npmrc); - resolvedConfig.ignoreNpmrcFile = true; } // istanbul ignore if if (resolvedConfig.hostRules) { diff --git a/lib/workers/repository/init/index.spec.ts b/lib/workers/repository/init/index.spec.ts index 63a04cbcce1624..71fcba1b876f99 100644 --- a/lib/workers/repository/init/index.spec.ts +++ b/lib/workers/repository/init/index.spec.ts @@ -1,4 +1,4 @@ -import { getName, mocked } from '../../../../test/util'; +import { getName, logger, mocked } from '../../../../test/util'; import * as _secrets from '../../../config/secrets'; import * as _onboarding from '../onboarding/branch'; import * as _apis from './apis'; @@ -29,5 +29,18 @@ describe(getName(__filename), () => { const renovateConfig = await initRepo({}); expect(renovateConfig).toMatchSnapshot(); }); + it('warns on unsupported options', async () => { + apis.initApis.mockResolvedValue({} as never); + onboarding.checkOnboardingBranch.mockResolvedValueOnce({}); + config.getRepoConfig.mockResolvedValueOnce({ + filterUnavailableUsers: true, + }); + config.mergeRenovateConfig.mockResolvedValueOnce({}); + secrets.applySecretsToConfig.mockReturnValueOnce({} as never); + await initRepo({}); + expect(logger.logger.warn).toHaveBeenCalledWith( + "Configuration option 'filterUnavailableUsers' is not supported on the current platform 'undefined'." + ); + }); }); }); diff --git a/lib/workers/repository/init/index.ts b/lib/workers/repository/init/index.ts index 07a47f1f4cf828..735e1fd44b739f 100644 --- a/lib/workers/repository/init/index.ts +++ b/lib/workers/repository/init/index.ts @@ -1,6 +1,7 @@ import { applySecretsToConfig } from '../../../config/secrets'; import type { RenovateConfig } from '../../../config/types'; import { logger } from '../../../logger'; +import { platform } from '../../../platform'; import { clone } from '../../../util/clone'; import { setUserRepoConfig } from '../../../util/git'; import { checkIfConfigured } from '../configured'; @@ -13,6 +14,14 @@ function initializeConfig(config: RenovateConfig): RenovateConfig { return { ...clone(config), errors: [], warnings: [], branchList: [] }; } +function warnOnUnsupportedOptions(config: RenovateConfig): void { + if (config.filterUnavailableUsers && !platform.filterUnavailableUsers) { + logger.warn( + `Configuration option 'filterUnavailableUsers' is not supported on the current platform '${config.platform}'.` + ); + } +} + export async function initRepo( config_: RenovateConfig ): Promise { @@ -21,6 +30,7 @@ export async function initRepo( config = await initApis(config); config = await getRepoConfig(config); checkIfConfigured(config); + warnOnUnsupportedOptions(config); config = applySecretsToConfig(config); await setUserRepoConfig(config); config = await detectVulnerabilityAlerts(config); diff --git a/lib/workers/repository/process/lookup/__snapshots__/index.spec.ts.snap b/lib/workers/repository/process/lookup/__snapshots__/index.spec.ts.snap index 35d60b78c71ea5..871c729a8f4b3a 100644 --- a/lib/workers/repository/process/lookup/__snapshots__/index.spec.ts.snap +++ b/lib/workers/repository/process/lookup/__snapshots__/index.spec.ts.snap @@ -50,7 +50,7 @@ Array [ "newValue": "==0.9.7", "newVersion": "0.9.7", "releaseTimestamp": "2013-09-04T17:07:22.948Z", - "updateType": "minor", + "updateType": "patch", }, Object { "bucket": "major", @@ -446,30 +446,7 @@ Array [ "newValue": "0.9.7", "newVersion": "0.9.7", "releaseTimestamp": "2013-09-04T17:07:22.948Z", - "updateType": "minor", - }, - Object { - "bucket": "major", - "newMajor": 1, - "newMinor": 4, - "newValue": "1.4.1", - "newVersion": "1.4.1", - "releaseTimestamp": "2015-05-17T04:25:07.299Z", - "updateType": "major", - }, -] -`; - -exports[`workers/repository/process/lookup/index .lookupUpdates() returns minor update if separate patches not configured 1`] = ` -Array [ - Object { - "bucket": "non-major", - "newMajor": 0, - "newMinor": 9, - "newValue": "0.9.7", - "newVersion": "0.9.7", - "releaseTimestamp": "2013-09-04T17:07:22.948Z", - "updateType": "minor", + "updateType": "patch", }, Object { "bucket": "major", @@ -552,6 +529,29 @@ Array [ ] `; +exports[`workers/repository/process/lookup/index .lookupUpdates() returns patch update even if separate patches not configured 1`] = ` +Array [ + Object { + "bucket": "non-major", + "newMajor": 0, + "newMinor": 9, + "newValue": "0.9.7", + "newVersion": "0.9.7", + "releaseTimestamp": "2013-09-04T17:07:22.948Z", + "updateType": "patch", + }, + Object { + "bucket": "major", + "newMajor": 1, + "newMinor": 4, + "newValue": "1.4.1", + "newVersion": "1.4.1", + "releaseTimestamp": "2015-05-17T04:25:07.299Z", + "updateType": "major", + }, +] +`; + exports[`workers/repository/process/lookup/index .lookupUpdates() returns patch update if separateMinorPatch 1`] = ` Array [ Object { @@ -617,7 +617,7 @@ Array [ "newValue": "3.1.0-dev.20180813", "newVersion": "3.1.0-dev.20180813", "releaseTimestamp": "2018-08-13T19:05:14.347Z", - "updateType": "minor", + "updateType": "patch", }, ] `; @@ -631,7 +631,7 @@ Array [ "newValue": "2.5.17-beta.0", "newVersion": "2.5.17-beta.0", "releaseTimestamp": "2018-03-23T23:29:13.819Z", - "updateType": "minor", + "updateType": "patch", }, ] `; @@ -655,7 +655,7 @@ Array [ "newValue": "3.0.1-insiders.20180726", "newVersion": "3.0.1-insiders.20180726", "releaseTimestamp": "2018-07-26T18:20:51.679Z", - "updateType": "minor", + "updateType": "patch", }, ] `; @@ -682,7 +682,7 @@ Array [ "newValue": "3.0.1-insiders.20180726", "newVersion": "3.0.1-insiders.20180726", "releaseTimestamp": "2018-07-26T18:20:51.679Z", - "updateType": "minor", + "updateType": "patch", }, ] `; @@ -696,7 +696,7 @@ Array [ "newValue": "3.0.1", "newVersion": "3.0.1", "releaseTimestamp": "2018-07-30T16:21:13.150Z", - "updateType": "minor", + "updateType": "patch", }, ] `; @@ -723,7 +723,7 @@ Array [ "newValue": "^0.0.35", "newVersion": "0.0.35", "releaseTimestamp": "2017-04-27T16:59:06.479Z", - "updateType": "minor", + "updateType": "patch", }, ] `; @@ -1503,7 +1503,7 @@ Array [ "newValue": "1.0.1", "newVersion": "1.0.1", "releaseTimestamp": "2014-03-11T18:47:17.560Z", - "updateType": "minor", + "updateType": "patch", }, ] `; diff --git a/lib/workers/repository/process/lookup/index.spec.ts b/lib/workers/repository/process/lookup/index.spec.ts index 93413f8a63acdb..d457c3a565ee53 100644 --- a/lib/workers/repository/process/lookup/index.spec.ts +++ b/lib/workers/repository/process/lookup/index.spec.ts @@ -1,12 +1,11 @@ import nock from 'nock'; -import { getConfig, getName, mocked, partial } from '../../../../../test/util'; -import qJson from '../../../../config/npm/__fixtures__/01.json'; -import helmetJson from '../../../../config/npm/__fixtures__/02.json'; -import coffeelintJson from '../../../../config/npm/__fixtures__/coffeelint.json'; -import nextJson from '../../../../config/npm/__fixtures__/next.json'; -import typescriptJson from '../../../../config/npm/__fixtures__/typescript.json'; -import vueJson from '../../../../config/npm/__fixtures__/vue.json'; -import webpackJson from '../../../../config/npm/__fixtures__/webpack.json'; +import { + getConfig, + getName, + loadJsonFixture, + mocked, + partial, +} from '../../../../../test/util'; import { CONFIG_VALIDATION } from '../../../../constants/error-messages'; import * as datasourceDocker from '../../../../datasource/docker'; import { id as datasourceDockerId } from '../../../../datasource/docker'; @@ -29,7 +28,25 @@ jest.mock('../../../../datasource/docker'); jest.mock('../../../../datasource/git-refs'); jest.mock('../../../../datasource/github-releases'); -qJson.latestVersion = '1.4.1'; +const fixtureRoot = '../../../../config/npm'; +const qJson = { + ...loadJsonFixture(__filename, '01.json', fixtureRoot), + latestVersion: '1.4.1', +}; +const helmetJson = loadJsonFixture(__filename, '02.json', fixtureRoot); +const coffeelintJson = loadJsonFixture( + __filename, + 'coffeelint.json', + fixtureRoot +); +const nextJson = loadJsonFixture(__filename, 'next.json', fixtureRoot); +const typescriptJson = loadJsonFixture( + __filename, + 'typescript.json', + fixtureRoot +); +const vueJson = loadJsonFixture(__filename, 'vue.json', fixtureRoot); +const webpackJson = loadJsonFixture(__filename, 'webpack.json', fixtureRoot); const docker = mocked(datasourceDocker) as any; docker.defaultRegistryUrls = ['https://index.docker.io']; @@ -186,7 +203,7 @@ describe(getName(__filename), () => { Error(CONFIG_VALIDATION) ); }); - it('returns minor update if separate patches not configured', async () => { + it('returns patch update even if separate patches not configured', async () => { config.currentValue = '0.9.0'; config.rangeStrategy = 'pin'; config.depName = 'q'; @@ -195,8 +212,8 @@ describe(getName(__filename), () => { const res = await lookup.lookupUpdates(config); expect(res.updates).toMatchSnapshot(); expect(res.updates).toHaveLength(2); - expect(res.updates[0].updateType).not.toEqual('patch'); - expect(res.updates[1].updateType).not.toEqual('patch'); + expect(res.updates[0].updateType).toEqual('patch'); + expect(res.updates[1].updateType).toEqual('major'); }); it('returns minor update if automerging both patch and minor', async () => { config.patch = { @@ -212,7 +229,7 @@ describe(getName(__filename), () => { nock('https://registry.npmjs.org').get('/q').reply(200, qJson); const res = await lookup.lookupUpdates(config); expect(res.updates).toMatchSnapshot(); - expect(res.updates[0].updateType).toEqual('minor'); + expect(res.updates[0].updateType).toEqual('patch'); }); it('returns patch update if separateMinorPatch', async () => { config.separateMinorPatch = true; diff --git a/lib/workers/repository/process/lookup/update-type.ts b/lib/workers/repository/process/lookup/update-type.ts index 956d7b310a88ed..90768a16d11d3f 100644 --- a/lib/workers/repository/process/lookup/update-type.ts +++ b/lib/workers/repository/process/lookup/update-type.ts @@ -19,8 +19,5 @@ export function getUpdateType( if (versioning.getMinor(newVersion) > versioning.getMinor(currentVersion)) { return 'minor'; } - if (config.separateMinorPatch) { - return 'patch'; - } - return 'minor'; + return 'patch'; } diff --git a/lib/workers/repository/updates/flatten.ts b/lib/workers/repository/updates/flatten.ts index 6261b851c88ca9..7c7ef3008846ab 100644 --- a/lib/workers/repository/updates/flatten.ts +++ b/lib/workers/repository/updates/flatten.ts @@ -4,7 +4,6 @@ import { mergeChildConfig, } from '../../../config'; import type { RenovateConfig } from '../../../config/types'; -import { LANGUAGE_DOCKER } from '../../../constants/languages'; import { getDefaultConfig } from '../../../datasource'; import { get } from '../../../manager'; import { applyPackageRules } from '../../../util/package-rules'; @@ -27,14 +26,6 @@ export function applyUpdateConfig(input: BranchUpgradeConfig): any { .replace(/-+/, '-') .toLowerCase() : undefined; - if ( - updateConfig.language === LANGUAGE_DOCKER && - /(^|\/)node$/.exec(updateConfig.depName) && - updateConfig.depName !== 'calico/node' - ) { - updateConfig.additionalBranchPrefix = ''; - updateConfig.depNameSanitized = 'node'; - } generateBranchName(updateConfig); return updateConfig; } diff --git a/package.json b/package.json index f4cd1ea6b76f26..c81c12efa0d946 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "@sindresorhus/is": "4.0.0", "@yarnpkg/core": "2.4.0", "@yarnpkg/parsers": "2.3.0", - "azure-devops-node-api": "10.2.1", + "azure-devops-node-api": "10.2.2", "bunyan": "1.8.15", "cacache": "15.0.6", "chalk": "4.1.0", @@ -160,7 +160,7 @@ "json5": "2.2.0", "linkify-markdown": "1.0.0", "luxon": "1.26.0", - "markdown-it": "12.0.4", + "markdown-it": "12.0.6", "markdown-table": "2.0.0", "minimatch": "3.0.4", "moo": "0.5.1", @@ -178,7 +178,7 @@ "semver-utils": "1.1.4", "shlex": "2.0.2", "shortid": "2.2.16", - "simple-git": "2.37.0", + "simple-git": "2.38.0", "slugify": "1.5.0", "traverse": "0.6.6", "upath": "2.0.1", @@ -202,7 +202,7 @@ "@types/changelog-filename-regex": "2.0.0", "@types/clean-git-ref": "2.0.0", "@types/conventional-commits-detector": "1.0.0", - "@types/eslint": "7.2.8", + "@types/eslint": "7.2.10", "@types/fs-extra": "9.0.11", "@types/git-url-parse": "9.0.0", "@types/github-url-from-git": "1.5.0", @@ -212,12 +212,12 @@ "@types/js-yaml": "3.12.6", "@types/json-dup-key-validator": "1.0.0", "@types/linkify-markdown": "1.0.0", - "@types/luxon": "1.26.3", + "@types/luxon": "1.26.4", "@types/markdown-it": "12.0.1", "@types/markdown-table": "2.0.0", "@types/moo": "0.5.4", "@types/nock": "10.0.3", - "@types/node": "14.14.37", + "@types/node": "14.14.41", "@types/node-emoji": "1.8.1", "@types/parse-link-header": "1.0.0", "@types/registry-auth-token": "4.2.0", @@ -247,7 +247,7 @@ "jest-junit": "12.0.0", "jest-mock-extended": "1.0.13", "jest-silent-reporter": "0.5.0", - "markdownlint-cli2": "0.0.15", + "markdownlint-cli2": "0.1.3", "mockdate": "3.0.5", "nock": "13.0.11", "npm-run-all": "4.1.5", @@ -258,7 +258,7 @@ "shelljs": "0.8.4", "strip-ansi": "6.0.0", "tmp-promise": "3.0.2", - "ts-jest": "26.5.4", + "ts-jest": "26.5.5", "ts-node": "9.1.1", "type-fest": "0.21.3", "typescript": "4.2.4" diff --git a/readme.md b/readme.md index df5f704c90fedd..dd2f2ecf68b505 100644 --- a/readme.md +++ b/readme.md @@ -5,8 +5,8 @@ Automated dependency updates. Multi-platform and multi-language. -[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://raw.githubusercontent.com/renovatebot/renovate/master/license) -[![codecov](https://codecov.io/gh/renovatebot/renovate/branch/master/graph/badge.svg)](https://codecov.io/gh/renovatebot/renovate) +[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://raw.githubusercontent.com/renovatebot/renovate/main/license) +[![codecov](https://codecov.io/gh/renovatebot/renovate/branch/main/graph/badge.svg)](https://codecov.io/gh/renovatebot/renovate) [![Renovate enabled](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://renovatebot.com/) [![Build status](https://github.com/renovatebot/renovate/workflows/build/badge.svg)](https://github.com/renovatebot/renovate/actions) @@ -65,7 +65,7 @@ If you are not on github.com or gitlab.com, or you prefer to run your own instan - Run the `renovate/renovate` Docker Hub image (same content/versions as the CLI tool), run it on a schedule - Run the `renovate/renovate:slim` Docker Hub image if you only use package managers that don't need third party binaries (e.g. JS, Docker, Nuget, pip) -[More details on the self-hosting development](https://github.com/renovatebot/renovate/blob/master/docs/usage/self-hosting.md). +[More details on the self-hosting development](https://github.com/renovatebot/renovate/blob/main/docs/usage/self-hosting.md). ## Contributing diff --git a/test/util.ts b/test/util.ts index 06f596fb1e85e6..e45057b9d29099 100644 --- a/test/util.ts +++ b/test/util.ts @@ -1,5 +1,7 @@ import crypto from 'crypto'; +import { readFileSync } from 'fs'; import { expect } from '@jest/globals'; +import upath from 'upath'; import { getConfig } from '../lib/config/defaults'; import type { RenovateConfig as _RenovateConfig } from '../lib/config/types'; import * as _logger from '../lib/logger'; @@ -44,6 +46,30 @@ export function getName(file: string): string { return name; } +export function loadFixture( + currentFile: string, + fixtureFile: string, + fixtureRoot = '.' +): string { + const callerDir = upath.dirname(currentFile); + const fixtureAbsFile = upath.join( + callerDir, + fixtureRoot, + '__fixtures__', + fixtureFile + ); + return readFileSync(fixtureAbsFile, { encoding: 'utf8' }); +} + +export function loadJsonFixture( + currentFile: string, + fixtureFile: string, + fixtureRoot = '.' +): T { + const rawFixture = loadFixture(currentFile, fixtureFile, fixtureRoot); + return JSON.parse(rawFixture) as T; +} + /** * Can be used to search and replace strings in jest snapshots. * @example diff --git a/tools/dispatch-release.mjs b/tools/dispatch-release.mjs index b1beb8a53648cc..3bdc53a23f53b7 100644 --- a/tools/dispatch-release.mjs +++ b/tools/dispatch-release.mjs @@ -1,9 +1,10 @@ import got from 'got'; import shell from 'shelljs'; -import { program } from './utils.mjs'; +import { options } from './utils.mjs'; -const version = program.release; -const dry = program.dryRun; +const version = options.release; +const tag = options.tag || 'latest'; +const dry = options.dryRun; shell.echo(`Dispatching version: ${version}`); @@ -27,6 +28,7 @@ shell.echo(`Dispatching version: ${version}`); sha: process.env.GITHUB_SHA, ref: process.env.GITHUB_REF, version, + tag, }, }, } diff --git a/tools/release.mjs b/tools/release.mjs index a475489216cc4c..eb1d20f3ea4294 100644 --- a/tools/release.mjs +++ b/tools/release.mjs @@ -1,7 +1,7 @@ import shell from 'shelljs'; -import { program } from './utils.mjs'; +import { options } from './utils.mjs'; -const version = program.release; +const version = options.release; // const sha = program.sha; // let err = false; diff --git a/tools/utils.mjs b/tools/utils.mjs index 49f1e215ffe156..34e0d88af752c2 100644 --- a/tools/utils.mjs +++ b/tools/utils.mjs @@ -5,11 +5,14 @@ const program = new commander.Command(); program .version('0.0.1') .requiredOption('-r, --release ', 'Version to use') - .option('-s, --sha ', 'Sha to use') + .option('-s, --sha ', 'Git sha to use') + .option('-t, --tag ', 'Npm dist-tag to publish to') .option('-d, --dry-run'); program.parse(process.argv); +export const options = program.opts(); + export { program }; /** diff --git a/yarn.lock b/yarn.lock index 9e9558987729df..48b066ac185d27 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1388,10 +1388,10 @@ resolved "https://registry.yarnpkg.com/@types/emscripten/-/emscripten-1.39.4.tgz#d61990c0cee72c4e475de737a140b51fe925a2c8" integrity sha512-k3LLVMFrdNA9UCvMDPWMbFrGPNb+GcPyw29ktJTo1RCN7RmxFG5XzPZcPKRlnLuLT/FRm8wp4ohvDwNY7GlROQ== -"@types/eslint@7.2.8": - version "7.2.8" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.8.tgz#45cd802380fcc352e5680e1781d43c50916f12ee" - integrity sha512-RTKvBsfz0T8CKOGZMfuluDNyMFHnu5lvNr4hWEsQeHXH6FcmIDIozOyWMh36nLGMwVd5UFNXC2xztA8lln22MQ== +"@types/eslint@7.2.10": + version "7.2.10" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.10.tgz#4b7a9368d46c0f8cd5408c23288a59aa2394d917" + integrity sha512-kUEPnMKrqbtpCq/KTaGFFKAcz6Ethm2EjCoKIDaCmfRBWLbFuTcOJfTlorwbnboXBzahqWLgUp1BQeKHiJzPUQ== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -1525,10 +1525,10 @@ resolved "https://registry.yarnpkg.com/@types/linkify-markdown/-/linkify-markdown-1.0.0.tgz#50c357a0a60bb220209f19310a79b939e1b8e2a3" integrity sha512-p3rl2HtugwjkH8qjEjUi5JByoZkVc2lz6E7D96X5/FqNyj2/jlgIrMlyrbck0U+HyjhOIy0XyTwES3RRz+1koQ== -"@types/luxon@1.26.3": - version "1.26.3" - resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-1.26.3.tgz#3d548f5f6f59723c292a8545da97631a85738b95" - integrity sha512-2TELN+Pd3Ocde87sKJMSQ9Wdj0zc/okHK3/+fOQHr3CaWv4jtVtcMzmt1Foww1+5YvPd9B5vL3XR6u5KF0daEA== +"@types/luxon@1.26.4": + version "1.26.4" + resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-1.26.4.tgz#77bbd5a1aa74ca31edff2aee4f8313ea0d93ca5c" + integrity sha512-OIvbVLZQUjyZofqSFpre2VsgvKy0V0JQdRgN0k3H1DTGRdxHiaQjT16+H2gyuhAS9r8B2PQEwrSiqP6/Zka3pQ== "@types/markdown-it@12.0.1": version "12.0.1" @@ -1581,10 +1581,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.25.tgz#15967a7b577ff81383f9b888aa6705d43fbbae93" integrity sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ== -"@types/node@14.14.37": - version "14.14.37" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.37.tgz#a3dd8da4eb84a996c36e331df98d82abd76b516e" - integrity sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw== +"@types/node@14.14.41": + version "14.14.41" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.41.tgz#d0b939d94c1d7bd53d04824af45f1139b8c45615" + integrity sha512-dueRKfaJL4RTtSa7bWeTK1M+VH+Gns73oCgzvYfHZywRCoPSd8EkXBL0mZ9unPTveBn+D9phZBaxuzpwjWkW0g== "@types/node@^13.7.0": version "13.13.41" @@ -2308,14 +2308,13 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -azure-devops-node-api@10.2.1: - version "10.2.1" - resolved "https://registry.yarnpkg.com/azure-devops-node-api/-/azure-devops-node-api-10.2.1.tgz#835080164f8c30cec6506c47198b044c053f1f36" - integrity sha512-XuSiUaYpk0tQpd9fD8qfRa5y1IdavupKNVmwxy0w/RhmxG2Wl8uAYnNJchUoWd3Rn9On0mYTCCZSn+UlYdYFSg== +azure-devops-node-api@10.2.2: + version "10.2.2" + resolved "https://registry.yarnpkg.com/azure-devops-node-api/-/azure-devops-node-api-10.2.2.tgz#9f557e622dd07bbaa9bd5e7e84e17c761e2151b2" + integrity sha512-4TVv2X7oNStT0vLaEfExmy3J4/CzfuXolEcQl/BRUmvGySqKStTG2O55/hUQ0kM7UJlZBLgniM0SBq4d/WkKow== dependencies: tunnel "0.0.6" - typed-rest-client "^1.8.0" - underscore "1.8.3" + typed-rest-client "^1.8.4" babel-jest@^26.6.3: version "26.6.3" @@ -3325,7 +3324,7 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: +debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== @@ -3346,13 +3345,6 @@ debug@^3.1.0: dependencies: ms "^2.1.1" -debug@^4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== - dependencies: - ms "2.1.2" - debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -6736,6 +6728,17 @@ markdown-it@12.0.4: mdurl "^1.0.1" uc.micro "^1.0.5" +markdown-it@12.0.6: + version "12.0.6" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.0.6.tgz#adcc8e5fe020af292ccbdf161fe84f1961516138" + integrity sha512-qv3sVLl4lMT96LLtR7xeRJX11OUFjsaD5oVat2/SNBIb21bJXwal2+SklcRbTwGwqWpWH/HRtYavOoJE+seL8w== + dependencies: + argparse "^2.0.1" + entities "~2.1.0" + linkify-it "^3.0.1" + mdurl "^1.0.1" + uc.micro "^1.0.5" + markdown-table@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-2.0.0.tgz#194a90ced26d31fe753d8b9434430214c011865b" @@ -6753,10 +6756,10 @@ markdownlint-cli2-formatter-default@^0.0.2: resolved "https://registry.yarnpkg.com/markdownlint-cli2-formatter-default/-/markdownlint-cli2-formatter-default-0.0.2.tgz#76f1a064d70966178dfe3bb489af9423d830ca79" integrity sha512-jIz1X3SIC8sX4NDFqQFUXL+JEtfnDoN4i+xocEu+etcxGX455pHb6sx86f/yVk4mKJ2o7aNe2ydSx9an22BfBg== -markdownlint-cli2@0.0.15: - version "0.0.15" - resolved "https://registry.yarnpkg.com/markdownlint-cli2/-/markdownlint-cli2-0.0.15.tgz#c35407d0dc0e7ba5ed02e8693305dfdf4b6a9beb" - integrity sha512-XXJ0qd8mhsSUPdIAi4jUK7PFpc0hG/jCXNj7589cX9Ywg9umynOMaUrbcLpSiRTzzVFrKIN5VLxunA6oG+I7YQ== +markdownlint-cli2@0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/markdownlint-cli2/-/markdownlint-cli2-0.1.3.tgz#15ac14edea7816c96978f5f1de9256e637b691c5" + integrity sha512-4pbrSEDe/G9PjJnrxKXKTQXyXERHvFH+RjvZrCRiNrVPB0p1/wmQXCkdsKNWlaf+gc4gz4k9u1fj2x28GvFenw== dependencies: globby "~11.0.3" markdownlint "~0.23.1" @@ -9235,14 +9238,14 @@ signale@^1.2.1: figures "^2.0.0" pkg-conf "^2.1.0" -simple-git@2.37.0: - version "2.37.0" - resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-2.37.0.tgz#9cf30a1fe6f58453a2ca3e65562428b38ff76f84" - integrity sha512-ZK6qRnP+Xa2v23UEZDNHUfzswsuNCDHOQpWZRkpqNaXn7V5wVBBx3zRJLji3pROJGzrzA7mXwY7preL5EKuAaQ== +simple-git@2.38.0: + version "2.38.0" + resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-2.38.0.tgz#5bc66bec40bce4f8ef950f4966f427799b4dd758" + integrity sha512-CORjrfirWMEGbJAxaXDH/PjZVOeATeG2bkafM9DsLVcFkbF9sXQGIIpEI6FeyXpvUsFK69T/pa4+4FKY9TUJMQ== dependencies: "@kwsites/file-exists" "^1.1.1" "@kwsites/promise-deferred" "^1.1.1" - debug "^4.3.2" + debug "^4.3.1" sisteransi@^1.0.5: version "1.0.5" @@ -10049,10 +10052,10 @@ ts-essentials@^4.0.0: resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-4.0.0.tgz#506c42b270bbd0465574b90416533175b09205ab" integrity sha512-uQJX+SRY9mtbKU+g9kl5Fi7AEMofPCvHfJkQlaygpPmHPZrtgaBqbWFOYyiA47RhnSwwnXdepUJrgqUYxoUyhQ== -ts-jest@26.5.4: - version "26.5.4" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.5.4.tgz#207f4c114812a9c6d5746dd4d1cdf899eafc9686" - integrity sha512-I5Qsddo+VTm94SukBJ4cPimOoFZsYTeElR2xy6H2TOVs+NsvgYglW8KuQgKoApOKuaU/Ix/vrF9ebFZlb5D2Pg== +ts-jest@26.5.5: + version "26.5.5" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.5.5.tgz#e40481b6ee4dd162626ba481a2be05fa57160ea5" + integrity sha512-7tP4m+silwt1NHqzNRAPjW1BswnAhopTdc2K3HEkRZjF0ZG2F/e/ypVH0xiZIMfItFtD3CX0XFbwPzp9fIEUVg== dependencies: bs-logger "0.x" buffer-from "1.x" @@ -10180,14 +10183,14 @@ type-fest@^0.8.0, type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -typed-rest-client@^1.8.0: - version "1.8.1" - resolved "https://registry.yarnpkg.com/typed-rest-client/-/typed-rest-client-1.8.1.tgz#2ecb18dd360ce2a722ad30d0e076712f1fc3d191" - integrity sha512-7JbJFBZZuu3G64u6ksklN1xtVGfqBKiR5MQoTe5oLTi68OyB6pRuuIQCllfK/BdGjQtZYp62rgUOnEYDz4e9Xg== +typed-rest-client@^1.8.4: + version "1.8.4" + resolved "https://registry.yarnpkg.com/typed-rest-client/-/typed-rest-client-1.8.4.tgz#ba3fb788e5b9322547406392533f12d660a5ced6" + integrity sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg== dependencies: qs "^6.9.1" tunnel "0.0.6" - underscore "1.8.3" + underscore "^1.12.1" typedarray-to-buffer@^3.1.5: version "3.1.5" @@ -10226,7 +10229,7 @@ umask@^1.1.0, umask@~1.1.0: resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" integrity sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0= -underscore@1.8.3, underscore@^1.12.1: +underscore@^1.12.1: version "1.12.1" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==