diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index 2b8837858285ab08acfce02e61069df2fa5fbe20..b46babd3aa3cab2d22d88f68fb3601c645471b2c 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -8,6 +8,6 @@ RUN install-apt make g++
 RUN install-tool python 3.11.4
 
 # renovate: datasource=npm
-RUN install-tool yarn 1.22.19
+RUN install-tool corepack 0.19.0
 
 USER ubuntu
diff --git a/.github/actions/setup-node/action.yml b/.github/actions/setup-node/action.yml
index a691a42f3075c2b91e62e864046af1671d6e33e9..82862bc5dece40fdb2483e14fc126718767fd25f 100644
--- a/.github/actions/setup-node/action.yml
+++ b/.github/actions/setup-node/action.yml
@@ -17,7 +17,7 @@ inputs:
   save-cache:
     description: 'Save cache when needed'
     required: false
-    default: false
+    default: 'false'
 runs:
   using: 'composite'
   steps:
@@ -47,6 +47,10 @@ runs:
           (steps.node-modules-restore.outputs.cache-hit == 'true') && 'true' || ''
         }}' >> "$GITHUB_ENV"
 
+    - name: Enable corepack
+      shell: bash
+      run: corepack enable
+
     - name: Setup Node
       uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
       with:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 46c6a3bd1e0ac61936a44bb3fea1ff0d51f7835d..3e93ba7b3c10866bfad26419b960c0d7143807a0 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -506,6 +506,10 @@ jobs:
         with:
           node-version: ${{ env.NODE_VERSION }}
 
+      - name: Enable corepack
+        shell: bash
+        run: corepack enable
+
       - name: Download package
         uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
         with:
diff --git a/.github/workflows/release-npm.yml b/.github/workflows/release-npm.yml
index f94805044522aa436381e18ce92e883a6b8b173a..81282486c3947d5ca39415bacf36acfaee07d02d 100644
--- a/.github/workflows/release-npm.yml
+++ b/.github/workflows/release-npm.yml
@@ -43,6 +43,10 @@ jobs:
         with:
           ref: ${{ env.GIT_SHA }}
 
+      - name: Enable corepack
+        shell: bash
+        run: corepack enable
+
       - name: Set up Node.js ${{ env.NODE_VERSION }}
         uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
         with:
diff --git a/.github/workflows/update-data.yml b/.github/workflows/update-data.yml
index 7b519ca5492c81125a5e4ed1aa850ef1855df624..763dfad77f48801e23c85f3432e5d8777bc97146 100644
--- a/.github/workflows/update-data.yml
+++ b/.github/workflows/update-data.yml
@@ -17,6 +17,10 @@ jobs:
     steps:
       - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
 
+      - name: Enable corepack
+        shell: bash
+        run: corepack enable
+
       - name: Set up Node.js ${{ env.NODE_VERSION }}
         uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
         with:
diff --git a/docs/development/local-development.md b/docs/development/local-development.md
index 9857221030a5cc90c408bc4679595fa116e0e354..38e89e602dfd3d0f8b88eb7b3a64031a7e63d7fd 100644
--- a/docs/development/local-development.md
+++ b/docs/development/local-development.md
@@ -12,7 +12,7 @@ You need the following dependencies for local development:
 
 - Git `>=2.33.0`
 - Node.js `^18.12.0 || >=20.0.0`
-- Yarn `^1.22.5`
+- Yarn `^1.22.5` (use corepack)
 - C++ compiler
 
 We support Node.js versions according to the [Node.js release schedule](https://github.com/nodejs/Release#release-schedule).
@@ -23,15 +23,14 @@ You can use the following commands on Ubuntu.
 
 ```sh
 curl -sL https://deb.nodesource.com/setup_18.x | sudo -E bash -
-curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
 sudo apt-get update
-sudo apt-get install -y git build-essential nodejs yarn
+sudo apt-get install -y git build-essential nodejs
+corepack enable
 ```
 
 #### Nix
 
-To enter a development shell with the necessary packages, run `nix-shell --packages gcc gitFull nodejs yarn`.
+To enter a development shell with the necessary packages, run `nix-shell --packages gcc gitFull nodejs yarn` and then `corepack enable`.
 
 #### Windows
 
@@ -41,7 +40,7 @@ If you already installed a part, skip the corresponding step.
 - Install [Git](https://git-scm.com/downloads). Make sure you've [configured your username and email](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup)
 - Install [Node.js LTS](https://nodejs.org/en/download/)
 - In an Administrator PowerShell prompt, run `npm install -global npm` and then `npm --debug install --global windows-build-tools`
-- Install [Yarn](https://yarnpkg.com/lang/en/docs/install/#windows-stable)
+- Enable corepack: `corepack enable`
 
   You can see what versions you're using like this:
 
diff --git a/package.json b/package.json
index e3dd402f876f2f85615e82b7400d84c824d4b982..35ca504f0802d3bbdda6316fb2a2d860cb143bef 100644
--- a/package.json
+++ b/package.json
@@ -65,12 +65,14 @@
   },
   "keywords": [
     "automated",
+    "azure",
     "bazel",
     "bitbucket",
     "buildkite",
     "dependencies",
     "dependency",
     "docker",
+    "gitea",
     "github",
     "gitlab",
     "management",
@@ -79,6 +81,7 @@
     "npm",
     "outdated",
     "php",
+    "pnpm",
     "python",
     "update",
     "yarn"
@@ -250,9 +253,11 @@
   },
   "devDependencies": {
     "@hyrious/marshal": "0.2.5",
+    "@jest/environment": "29.6.2",
     "@jest/globals": "29.6.2",
     "@jest/reporters": "29.6.2",
     "@jest/test-result": "29.6.2",
+    "@jest/types": "29.6.1",
     "@ls-lint/ls-lint": "2.0.1",
     "@openpgp/web-stream-tools": "0.0.14",
     "@renovate/eslint-plugin": "file:./tools/eslint",
@@ -283,6 +288,7 @@
     "@types/markdown-it": "12.2.3",
     "@types/markdown-table": "2.0.0",
     "@types/marshal": "0.5.1",
+    "@types/mdast": "3.0.12",
     "@types/moo": "0.5.5",
     "@types/nock": "10.0.3",
     "@types/node": "18.17.1",
@@ -314,18 +320,22 @@
     "eslint-plugin-jest-formatting": "3.1.0",
     "eslint-plugin-promise": "6.1.1",
     "eslint-plugin-typescript-enum": "2.1.0",
+    "expect": "29.6.2",
     "expect-more-jest": "5.5.0",
     "graphql": "16.7.1",
     "husky": "8.0.3",
     "jest": "29.6.2",
     "jest-extended": "4.0.0",
+    "jest-mock": "29.6.2",
     "jest-mock-extended": "3.0.4",
+    "jest-snapshot": "29.6.2",
     "markdownlint-cli2": "0.8.1",
     "memfs": "4.2.0",
     "mock-fs": "5.2.0",
     "nock": "13.3.2",
     "npm-run-all": "4.1.5",
     "nyc": "15.1.0",
+    "pretty-format": "29.6.2",
     "rimraf": "5.0.1",
     "semantic-release": "21.0.7",
     "tar": "6.1.15",
@@ -339,6 +349,7 @@
   "resolutions": {
     "jackspeak": "2.1.1"
   },
+  "packageManager": "yarn@1.22.19",
   "files": [
     "dist",
     "renovate-schema.json"
diff --git a/yarn.lock b/yarn.lock
index cf8c98ae117701e1ebdc60b4c54dc93f74ad375f..da72b05a9943d81f511967a38ebeb8f3e038d2d6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1326,7 +1326,7 @@
     slash "^3.0.0"
     strip-ansi "^6.0.0"
 
-"@jest/environment@^29.6.2":
+"@jest/environment@29.6.2", "@jest/environment@^29.6.2":
   version "29.6.2"
   resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.6.2.tgz#794c0f769d85e7553439d107d3f43186dc6874a9"
   integrity sha512-AEcW43C7huGd/vogTddNNTDRpO6vQ2zaQNrttvWV18ArBx9Z56h7BIsXkNFJVOO4/kblWEQz30ckw0+L3izc+Q==
@@ -1467,7 +1467,7 @@
     slash "^3.0.0"
     write-file-atomic "^4.0.2"
 
-"@jest/types@^29.6.1":
+"@jest/types@29.6.1", "@jest/types@^29.6.1":
   version "29.6.1"
   resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.1.tgz#ae79080278acff0a6af5eb49d063385aaa897bf2"
   integrity sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==
@@ -3272,7 +3272,7 @@
   dependencies:
     "@types/node" "*"
 
-"@types/mdast@^3.0.0":
+"@types/mdast@3.0.12", "@types/mdast@^3.0.0":
   version "3.0.12"
   resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.12.tgz#beeb511b977c875a5b0cc92eab6fcac2f0895514"
   integrity sha512-DT+iNIRNX884cx0/Q1ja7NyUPpZuv0KPyL5rGNxm1WC1OtHstl7n4Jb7nk+xacNShQMbczJjt8uFzznpp6kYBg==
@@ -5461,7 +5461,7 @@ expect-more@1.3.0:
   resolved "https://registry.yarnpkg.com/expect-more/-/expect-more-1.3.0.tgz#fcc6e7477e36d91194d550684bf733a88228aaff"
   integrity sha512-HnXT5nJb9V3DMnr5RgA1TiKbu5kRaJ0GD1JkuhZvnr1Qe3HJq+ESnrcl/jmVUZ8Ycnl3Sp0OTYUhmO36d2+zow==
 
-expect@^29.6.2:
+expect@29.6.2, expect@^29.6.2:
   version "29.6.2"
   resolved "https://registry.yarnpkg.com/expect/-/expect-29.6.2.tgz#7b08e83eba18ddc4a2cf62b5f2d1918f5cd84521"
   integrity sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==
@@ -6974,7 +6974,7 @@ jest-mock-extended@3.0.4:
   dependencies:
     ts-essentials "^7.0.3"
 
-jest-mock@^29.6.2:
+jest-mock@29.6.2, jest-mock@^29.6.2:
   version "29.6.2"
   resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.6.2.tgz#ef9c9b4d38c34a2ad61010a021866dad41ce5e00"
   integrity sha512-hoSv3lb3byzdKfwqCuT6uTscan471GUECqgNYykg6ob0yiAw3zYc7OrPnI9Qv8Wwoa4lC7AZ9hyS4AiIx5U2zg==
@@ -7071,7 +7071,7 @@ jest-runtime@^29.6.2:
     slash "^3.0.0"
     strip-bom "^4.0.0"
 
-jest-snapshot@^29.6.2:
+jest-snapshot@29.6.2, jest-snapshot@^29.6.2:
   version "29.6.2"
   resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.6.2.tgz#9b431b561a83f2bdfe041e1cab8a6becdb01af9c"
   integrity sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==
@@ -8996,7 +8996,7 @@ pretty-bytes@^5.1.0:
   resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
   integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==
 
-pretty-format@^29.4.1, pretty-format@^29.6.2:
+pretty-format@29.6.2, pretty-format@^29.4.1, pretty-format@^29.6.2:
   version "29.6.2"
   resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.6.2.tgz#3d5829261a8a4d89d8b9769064b29c50ed486a47"
   integrity sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg==