diff --git a/.eslintignore b/.eslintignore index 410d575..1db1571 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,4 +3,5 @@ build/ coverage/ scripts/ jest.config.ts +jest.setup.js **/generated/ \ No newline at end of file diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..b50e63a --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,139 @@ +# AI Coding Agent Instructions for mock-github + +## Project Overview +**mock-github** is a testing library that provides tools to mock GitHub environments locally. It enables testing GitHub Actions and API calls without polluting real repositories or hitting rate limits. + +Two core abstractions: +1. **Moctokit**: Mocks GitHub REST API endpoints using OpenAPI spec (via `nock`) +2. **MockGithub**: Mocks full GitHub environment with repositories, branches, files, actions, and env vars + +## Architecture & Key Components + +### Layer 1: Endpoint Mocking (Foundation) +- `src/endpoint-mocker/abstract-endpoint-mocker.ts`: Base class using `nock` for HTTP interception +- `src/endpoint-mocker/request/abstract-request-mocker.ts`: Generic request parameter matching +- `src/endpoint-mocker/response/abstract-response-mocker.ts`: Response building with status/headers + +### Layer 2: API Mocking (Generated) +- `src/moctokit/moctokit.ts`: Extends `EndpointMocker`, wraps auto-generated endpoint methods +- `src/moctokit/generated/endpoint-request.ts`: **AUTO-GENERATED** from GitHub OpenAPI spec (~1817 lines) + - Maps 200+ GitHub API endpoints to `MoctokitRequestMocker` instances + - **Never manually edit** - regenerate via `npm run update:endpoint-requests` +- `src/moctokit/generated/endpoint-details.ts`: OpenAPI metadata for each endpoint + +### Layer 3: GitHub Environment Mocking +- `src/github/github-mocker.ts`: Orchestrates setup/teardown of repositories, env vars, actions +- `src/github/repository/repository-mocker.ts`: Creates local git repos via `simple-git` +- `src/github/env/env-mocker.ts`: Manages process environment variables +- `src/github/action/action-mocker.ts`: Simulates GitHub Action execution context + +### Type System (Critical for Development) +- Uses **OpenAPI path types** from generated endpoint details +- Generic constraints like `Path extends keyof paths, Method extends keyof paths[Path]` +- `src/moctokit/response/response-mocker.types.ts`: Complex conditional types for response validation +- `.types.ts` files excluded from coverage - contain domain models, not business logic + +## Critical Developer Workflows + +### Build & Dependencies +```bash +npm run build # TypeScript → JavaScript, alias resolution via tsc-alias +npm test # Jest with 90% coverage threshold +npm run test:report # Coverage report + SonarQube XML output +npm run lint # ESLint with auto-fix on commit via husky +``` + +### Updating Generated Code +```bash +npm run update:api-spec # Fetch latest GitHub OpenAPI spec +npm run update:endpoint-details # Parse endpoints from spec +npm run update:endpoint-requests # Generate endpoint method bindings +npm run update-all # Run all three steps +``` + +Scripts are in `scripts/` directory - regenerate when GitHub API changes. + +## Project-Specific Patterns + +### 1. **Module Path Aliases** +- Use `@mg/*` imports (configured in `tsconfig.json` paths) +- Example: `import { Moctokit } from "@mg/moctokit/moctokit"` +- Resolves to `src/*` during development, `build/src/*` in compiled output + +### 2. **Abstract Base Classes for Extension** +- `EndpointMocker`, `RequestMocker`, `ResponseMocker` are abstract - meant to be extended +- `MoctokitRequestMocker` and `MoctokitResponseMocker` extend these for GitHub API specifics +- Pattern: Abstract → Concrete implementation → Usage via interface + +### 3. **Config Validation with AJV** +- `MockGithub` constructor validates config against `GithubConfigSchema` (JSON Schema) +- Schema defined in `src/github/schema/` directory +- Config can be JSON file path (string) or object - validated before use + +### 4. **Setup/Teardown Lifecycle** +- `MockGithub` requires explicit `setup()` and `teardown()` calls +- Setup order matters: repositories → env vars → actions +- Throws if methods called before setup (e.g., `repo` getter checks `hasCalledSetup`) + +### 5. **Repository State Management** +- `RepositoryState` tracks branches, files, remotes (origin/upstream) +- State exposed via `repo.getState()`, `repo.getBranchState()`, etc. +- Branches can be local or pushed - tracked separately in `BranchState` + +### 6. **File Organization by Responsibility** +``` +src/ +├── endpoint-mocker/ # Generic HTTP mocking layer +├── moctokit/ # GitHub API-specific mocking +├── github/ # Full GitHub environment +│ ├── repository/ # Git repo + state management +│ ├── action/ # GitHub Actions simulation +│ ├── env/ # Environment variables +│ └── schema/ # JSON validation schemas +``` + +## Integration Points & Dependencies + +### External Libraries +- `nock`: HTTP mocking (≥1.0.0 incompatible with Node 18 native fetch) +- `simple-git`: Git operations (local repo creation/manipulation) +- `@octokit/rest`: Type definitions (v19, not runtime) +- `ajv`: JSON Schema validation +- `ts-jest`: TypeScript testing + +### Cross-Component Communication +1. **Config Flow**: JSON config → validated → distributed to Action/Env/Repo mockers +2. **Setup Coordination**: `MockGithub.setup()` → parallel repo/env setup → then action setup +3. **Query Interface**: `repo.getState()` returns `State` (path, branches, files) + +## Testing Patterns + +### Mocking Tests +- Located in `test/moctokit/moctokit.test.ts` and `test/github/` +- Create instance → configure mock → execute client → assert response +- Use `repeat` option in `reply()` for multiple matching calls +- Example: `moctokit.rest.repos.get({owner: "kie"}).reply({status: 200, data: {...}})` + +### Assertions +- Verify both status and data payload +- Repository tests check git history, branches, file contents via state queries +- Coverage threshold enforced: 90% branches/functions/lines/statements + +## Common Pitfalls & Guidelines + +- **Don't edit generated files**: `src/moctokit/generated/*` is auto-generated - run `npm run update:*` scripts instead +- **Always setup/teardown MockGithub**: Forgetting causes hard-to-debug state pollution +- **Path aliases in imports**: Use `@mg/` consistently, don't mix relative paths +- **Type-first development**: Leverage generic constraints in request/response mockers - they catch issues early +- **Config schema**: Validate before instantiating - bad config fails at constructor, not later + +## Key Files to Reference + +| File | Purpose | +|------|---------| +| `src/index.ts` | Public API exports | +| `src/github/github-mocker.ts` | Main entry point for environment mocking | +| `src/moctokit/moctokit.ts` | Main entry point for API mocking | +| `jest.config.ts` | Coverage thresholds (90%), path aliases, `ts-jest` config | +| `package.json` | Scripts, build output points, dependencies | +| `scripts/endpoint-details.js` | Generates endpoint metadata from OpenAPI | diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 5edfc16..b093736 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: - node-version: 16 + node-version: 24 registry-url: https://registry.npmjs.org/ - name: Install packages diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 4aada6f..036eecd 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -13,7 +13,7 @@ jobs: tests: strategy: matrix: - node-version: [16.x, 20.x] + node-version: [ 24.x ] os: [ubuntu-latest] fail-fast: false runs-on: ${{ matrix.os }} @@ -36,7 +36,7 @@ jobs: - uses: actions/setup-node@v6 with: - node-version: 20.x + node-version: 24.x - name: Install packages run: npm ci diff --git a/.github/workflows/report.yml b/.github/workflows/report.yml index 4ad1e7d..29c4dee 100644 --- a/.github/workflows/report.yml +++ b/.github/workflows/report.yml @@ -18,7 +18,7 @@ jobs: uses: warchant/setup-sonar-scanner@v10 - uses: actions/setup-node@v6 with: - node-version: 20 + node-version: 24 - run: npm ci - run: npm run test:report env: diff --git a/.github/workflows/update.yml b/.github/workflows/update.yml index c0afa45..f445978 100644 --- a/.github/workflows/update.yml +++ b/.github/workflows/update.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: - node-version: 20 + node-version: 24 cache: npm - run: npm install @octokit/openapi-types-ghec -D - run: npm ci diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..cabf43b --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +24 \ No newline at end of file diff --git a/jest.config.ts b/jest.config.ts index 9cbed94..3036a0a 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -10,6 +10,7 @@ const jestConfig: Config.InitialOptions = { }, clearMocks: true, resetMocks: true, + setupFilesAfterEnv: ["/jest.setup.js"], collectCoverageFrom: [ "src/**", "!**/*.types.ts", diff --git a/jest.setup.js b/jest.setup.js new file mode 100644 index 0000000..2253fbc --- /dev/null +++ b/jest.setup.js @@ -0,0 +1,10 @@ +// Suppress deprecation warning from @octokit/request-error +// The library warns about using error.code instead of error.status +// This can be safely suppressed as the functionality is not affected +const originalWarn = console.warn; +console.warn = function (...args) { + if (args[0] && typeof args[0] === 'string' && args[0].includes('[@octokit/request-error]')) { + return; + } + originalWarn.apply(console, args); +}; diff --git a/package-lock.json b/package-lock.json index f44d09f..fd3cee5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,17 +14,17 @@ "express": "^4.18.1", "fast-glob": "^3.2.12", "fs-extra": "^10.1.0", - "nock": "^13.2.7", + "nock": "^14.0.15", "simple-git": "^3.8.0", "totalist": "^3.0.0" }, "devDependencies": { "@actions/artifact": "^1.1.0", - "@octokit/rest": "^19.0.4", + "@octokit/rest": "^19.0.13", "@types/express": "^4.17.13", "@types/fs-extra": "^9.0.13", "@types/jest": "^28.1.3", - "@types/node": "^18.0.0", + "@types/node": "^24.0.0", "@typescript-eslint/eslint-plugin": "^5.48.2", "@typescript-eslint/parser": "^5.48.2", "@vercel/ncc": "^0.34.0", @@ -42,6 +42,9 @@ "ts-node": "^10.8.1", "tsc-alias": "^1.7.1", "typescript": "^4.7.4" + }, + "engines": { + "node": ">=24.0.0" } }, "node_modules/@actions/artifact": { @@ -1404,6 +1407,23 @@ "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" }, + "node_modules/@mswjs/interceptors": { + "version": "0.41.9", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@mswjs/interceptors/-/interceptors-0.41.9.tgz", + "integrity": "sha512-VVPPgHyQ6ShqnrmDWuxjmUIsO9gWyOZFmuOfLd9LfBGQJwZfy0gvv9pbHSJuoFNIYC7ZDX9aoFwowjcdSC4E8w==", + "license": "MIT", + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1437,28 +1457,27 @@ } }, "node_modules/@octokit/auth-token": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.2.tgz", - "integrity": "sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==", + "version": "3.0.4", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/auth-token/-/auth-token-3.0.4.tgz", + "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==", "dev": true, - "dependencies": { - "@octokit/types": "^8.0.0" - }, + "license": "MIT", "engines": { "node": ">= 14" } }, "node_modules/@octokit/core": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.1.0.tgz", - "integrity": "sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==", + "version": "4.2.4", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/core/-/core-4.2.4.tgz", + "integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/auth-token": "^3.0.0", "@octokit/graphql": "^5.0.0", "@octokit/request": "^6.0.0", "@octokit/request-error": "^3.0.0", - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" }, @@ -1467,12 +1486,13 @@ } }, "node_modules/@octokit/endpoint": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz", - "integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==", + "version": "7.0.6", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/endpoint/-/endpoint-7.0.6.tgz", + "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==", "dev": true, + "license": "MIT", "dependencies": { - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "is-plain-object": "^5.0.0", "universal-user-agent": "^6.0.0" }, @@ -1481,13 +1501,14 @@ } }, "node_modules/@octokit/graphql": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.4.tgz", - "integrity": "sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==", + "version": "5.0.6", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/graphql/-/graphql-5.0.6.tgz", + "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/request": "^6.0.0", - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "universal-user-agent": "^6.0.0" }, "engines": { @@ -1495,10 +1516,11 @@ } }, "node_modules/@octokit/openapi-types": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==", - "dev": true + "version": "18.1.1", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/openapi-types/-/openapi-types-18.1.1.tgz", + "integrity": "sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==", + "dev": true, + "license": "MIT" }, "node_modules/@octokit/openapi-types-ghec": { "version": "18.0.0", @@ -1506,12 +1528,14 @@ "integrity": "sha512-xY5FTR/DW2gUJdC5GyzkqrfMHhr3u3hg+dUG6bA5FvuuODw6A7+0JTTSS1ndLQEKGmFxP7chf1BKkhvhnqxCew==" }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz", - "integrity": "sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==", + "version": "6.1.2", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", + "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", "dev": true, + "license": "MIT", "dependencies": { - "@octokit/types": "^8.0.0" + "@octokit/tsconfig": "^1.0.2", + "@octokit/types": "^9.2.3" }, "engines": { "node": ">= 14" @@ -1522,21 +1546,22 @@ }, "node_modules/@octokit/plugin-request-log": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", "dev": true, + "license": "MIT", "peerDependencies": { "@octokit/core": ">=3" } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz", - "integrity": "sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==", + "version": "7.2.3", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz", + "integrity": "sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==", "dev": true, + "license": "MIT", "dependencies": { - "@octokit/types": "^8.0.0", - "deprecation": "^2.3.1" + "@octokit/types": "^10.0.0" }, "engines": { "node": ">= 14" @@ -1545,15 +1570,26 @@ "@octokit/core": ">=3" } }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { + "version": "10.0.0", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/types/-/types-10.0.0.tgz", + "integrity": "sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^18.0.0" + } + }, "node_modules/@octokit/request": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz", - "integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==", + "version": "6.2.8", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/request/-/request-6.2.8.tgz", + "integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "is-plain-object": "^5.0.0", "node-fetch": "^2.6.7", "universal-user-agent": "^6.0.0" @@ -1563,12 +1599,13 @@ } }, "node_modules/@octokit/request-error": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz", - "integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==", + "version": "3.0.3", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/request-error/-/request-error-3.0.3.tgz", + "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", "dev": true, + "license": "MIT", "dependencies": { - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "deprecation": "^2.0.0", "once": "^1.4.0" }, @@ -1577,29 +1614,60 @@ } }, "node_modules/@octokit/rest": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.5.tgz", - "integrity": "sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow==", + "version": "19.0.13", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/rest/-/rest-19.0.13.tgz", + "integrity": "sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA==", "dev": true, + "license": "MIT", "dependencies": { - "@octokit/core": "^4.1.0", - "@octokit/plugin-paginate-rest": "^5.0.0", + "@octokit/core": "^4.2.1", + "@octokit/plugin-paginate-rest": "^6.1.2", "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^6.7.0" + "@octokit/plugin-rest-endpoint-methods": "^7.1.2" }, "engines": { "node": ">= 14" } }, + "node_modules/@octokit/tsconfig": { + "version": "1.0.2", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", + "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==", + "dev": true, + "license": "MIT" + }, "node_modules/@octokit/types": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", - "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", + "version": "9.3.2", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/types/-/types-9.3.2.tgz", + "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", "dev": true, + "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^14.0.0" + "@octokit/openapi-types": "^18.0.0" } }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "license": "MIT" + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "license": "MIT", + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "license": "MIT" + }, "node_modules/@pnpm/config.env-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", @@ -2153,10 +2221,14 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==", - "dev": true + "version": "24.12.4", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@types/node/-/node-24.12.4.tgz", + "integrity": "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", @@ -2874,9 +2946,10 @@ }, "node_modules/before-after-hook": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/before-after-hook/-/before-after-hook-2.2.3.tgz", "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/binary-extensions": { "version": "2.2.0", @@ -3744,9 +3817,10 @@ }, "node_modules/deprecation": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/deprecation/-/deprecation-2.3.1.tgz", "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/destroy": { "version": "1.2.0", @@ -5440,6 +5514,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "license": "MIT" + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -5501,9 +5581,10 @@ }, "node_modules/is-plain-object": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/is-plain-object/-/is-plain-object-5.0.0.tgz", "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6810,7 +6891,8 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true }, "node_modules/lodash.capitalize": { "version": "4.2.1", @@ -7339,40 +7421,19 @@ "dev": true }, "node_modules/nock": { - "version": "13.2.9", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.2.9.tgz", - "integrity": "sha512-1+XfJNYF1cjGB+TKMWi29eZ0b82QOvQs2YoLNzbpWGqFMtRQHTa57osqdGj4FrFPgkO4D4AZinzUJR9VvW3QUA==", + "version": "14.0.15", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/nock/-/nock-14.0.15.tgz", + "integrity": "sha512-S0a47C9pLvcYx/Ugf0H30BVBEcUgMMBDk9VJIDlJ8XGrfH2QDUD4Tgdp45qDIiHttokBG+IbsOtsvIjGR/j3bg==", + "license": "MIT", "dependencies": { - "debug": "^4.1.0", + "@mswjs/interceptors": "^0.41.0", "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.21", "propagate": "^2.0.0" }, "engines": { - "node": ">= 10.13" + "node": ">=18.20.0 <20 || >=20.12.1" } }, - "node_modules/nock/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/nock/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", @@ -7383,10 +7444,11 @@ } }, "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.7.0", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, + "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -10275,6 +10337,12 @@ "node": ">= 0.8.0" } }, + "node_modules/outvariant": { + "version": "1.4.3", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", + "license": "MIT" + }, "node_modules/p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -11951,6 +12019,12 @@ "readable-stream": "^2.0.2" } }, + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "license": "MIT" + }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -12317,9 +12391,10 @@ }, "node_modules/tr46": { "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/traverse": { "version": "0.6.7", @@ -12558,6 +12633,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -12571,10 +12653,11 @@ } }, "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", - "dev": true + "version": "6.0.1", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "dev": true, + "license": "ISC" }, "node_modules/universalify": { "version": "2.0.0", @@ -12713,15 +12796,17 @@ }, "node_modules/webidl-conversions": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/whatwg-url": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dev": true, + "license": "MIT", "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -13956,6 +14041,19 @@ "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" }, + "@mswjs/interceptors": { + "version": "0.41.9", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@mswjs/interceptors/-/interceptors-0.41.9.tgz", + "integrity": "sha512-VVPPgHyQ6ShqnrmDWuxjmUIsO9gWyOZFmuOfLd9LfBGQJwZfy0gvv9pbHSJuoFNIYC7ZDX9aoFwowjcdSC4E8w==", + "requires": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -13980,55 +14078,52 @@ } }, "@octokit/auth-token": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.2.tgz", - "integrity": "sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==", - "dev": true, - "requires": { - "@octokit/types": "^8.0.0" - } + "version": "3.0.4", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/auth-token/-/auth-token-3.0.4.tgz", + "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==", + "dev": true }, "@octokit/core": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.1.0.tgz", - "integrity": "sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==", + "version": "4.2.4", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/core/-/core-4.2.4.tgz", + "integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==", "dev": true, "requires": { "@octokit/auth-token": "^3.0.0", "@octokit/graphql": "^5.0.0", "@octokit/request": "^6.0.0", "@octokit/request-error": "^3.0.0", - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" } }, "@octokit/endpoint": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz", - "integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==", + "version": "7.0.6", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/endpoint/-/endpoint-7.0.6.tgz", + "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==", "dev": true, "requires": { - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "is-plain-object": "^5.0.0", "universal-user-agent": "^6.0.0" } }, "@octokit/graphql": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.4.tgz", - "integrity": "sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==", + "version": "5.0.6", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/graphql/-/graphql-5.0.6.tgz", + "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", "dev": true, "requires": { "@octokit/request": "^6.0.0", - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "universal-user-agent": "^6.0.0" } }, "@octokit/openapi-types": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==", + "version": "18.1.1", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/openapi-types/-/openapi-types-18.1.1.tgz", + "integrity": "sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==", "dev": true }, "@octokit/openapi-types-ghec": { @@ -14037,77 +14132,113 @@ "integrity": "sha512-xY5FTR/DW2gUJdC5GyzkqrfMHhr3u3hg+dUG6bA5FvuuODw6A7+0JTTSS1ndLQEKGmFxP7chf1BKkhvhnqxCew==" }, "@octokit/plugin-paginate-rest": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz", - "integrity": "sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==", + "version": "6.1.2", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", + "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", "dev": true, "requires": { - "@octokit/types": "^8.0.0" + "@octokit/tsconfig": "^1.0.2", + "@octokit/types": "^9.2.3" } }, "@octokit/plugin-request-log": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", "dev": true, "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz", - "integrity": "sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==", + "version": "7.2.3", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz", + "integrity": "sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==", "dev": true, "requires": { - "@octokit/types": "^8.0.0", - "deprecation": "^2.3.1" + "@octokit/types": "^10.0.0" + }, + "dependencies": { + "@octokit/types": { + "version": "10.0.0", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/types/-/types-10.0.0.tgz", + "integrity": "sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==", + "dev": true, + "requires": { + "@octokit/openapi-types": "^18.0.0" + } + } } }, "@octokit/request": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz", - "integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==", + "version": "6.2.8", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/request/-/request-6.2.8.tgz", + "integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==", "dev": true, "requires": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "is-plain-object": "^5.0.0", "node-fetch": "^2.6.7", "universal-user-agent": "^6.0.0" } }, "@octokit/request-error": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz", - "integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==", + "version": "3.0.3", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/request-error/-/request-error-3.0.3.tgz", + "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", "dev": true, "requires": { - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "deprecation": "^2.0.0", "once": "^1.4.0" } }, "@octokit/rest": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.5.tgz", - "integrity": "sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow==", + "version": "19.0.13", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/rest/-/rest-19.0.13.tgz", + "integrity": "sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA==", "dev": true, "requires": { - "@octokit/core": "^4.1.0", - "@octokit/plugin-paginate-rest": "^5.0.0", + "@octokit/core": "^4.2.1", + "@octokit/plugin-paginate-rest": "^6.1.2", "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^6.7.0" + "@octokit/plugin-rest-endpoint-methods": "^7.1.2" } }, + "@octokit/tsconfig": { + "version": "1.0.2", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", + "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==", + "dev": true + }, "@octokit/types": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", - "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", + "version": "9.3.2", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@octokit/types/-/types-9.3.2.tgz", + "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", "dev": true, "requires": { - "@octokit/openapi-types": "^14.0.0" + "@octokit/openapi-types": "^18.0.0" + } + }, + "@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==" + }, + "@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "requires": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" } }, + "@open-draft/until": { + "version": "2.1.0", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==" + }, "@pnpm/config.env-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", @@ -14573,10 +14704,13 @@ "dev": true }, "@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==", - "dev": true + "version": "24.12.4", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/@types/node/-/node-24.12.4.tgz", + "integrity": "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==", + "dev": true, + "requires": { + "undici-types": "~7.16.0" + } }, "@types/normalize-package-data": { "version": "2.4.1", @@ -15096,7 +15230,7 @@ }, "before-after-hook": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/before-after-hook/-/before-after-hook-2.2.3.tgz", "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", "dev": true }, @@ -15736,7 +15870,7 @@ }, "deprecation": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/deprecation/-/deprecation-2.3.1.tgz", "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", "dev": true }, @@ -16973,6 +17107,11 @@ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "dev": true }, + "is-node-process": { + "version": "1.2.0", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==" + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -17013,7 +17152,7 @@ }, "is-plain-object": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/is-plain-object/-/is-plain-object-5.0.0.tgz", "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true }, @@ -17971,7 +18110,8 @@ "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true }, "lodash.capitalize": { "version": "4.2.1", @@ -18363,29 +18503,13 @@ "dev": true }, "nock": { - "version": "13.2.9", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.2.9.tgz", - "integrity": "sha512-1+XfJNYF1cjGB+TKMWi29eZ0b82QOvQs2YoLNzbpWGqFMtRQHTa57osqdGj4FrFPgkO4D4AZinzUJR9VvW3QUA==", + "version": "14.0.15", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/nock/-/nock-14.0.15.tgz", + "integrity": "sha512-S0a47C9pLvcYx/Ugf0H30BVBEcUgMMBDk9VJIDlJ8XGrfH2QDUD4Tgdp45qDIiHttokBG+IbsOtsvIjGR/j3bg==", "requires": { - "debug": "^4.1.0", + "@mswjs/interceptors": "^0.41.0", "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.21", "propagate": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } } }, "node-emoji": { @@ -18398,9 +18522,9 @@ } }, "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.7.0", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, "requires": { "whatwg-url": "^5.0.0" @@ -20429,6 +20553,11 @@ "word-wrap": "^1.2.3" } }, + "outvariant": { + "version": "1.4.3", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==" + }, "p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -21674,6 +21803,11 @@ "readable-stream": "^2.0.2" } }, + "strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==" + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -21950,7 +22084,7 @@ }, "tr46": { "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "dev": true }, @@ -22093,6 +22227,12 @@ "which-boxed-primitive": "^1.0.2" } }, + "undici-types": { + "version": "7.16.0", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true + }, "unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -22103,9 +22243,9 @@ } }, "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "version": "6.0.1", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", "dev": true }, "universalify": { @@ -22208,13 +22348,13 @@ }, "webidl-conversions": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "dev": true }, "whatwg-url": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "resolved": "https://nexus.corp.redhat.com/repository/npmjs/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dev": true, "requires": { diff --git a/package.json b/package.json index 33929d9..46d8f6b 100644 --- a/package.json +++ b/package.json @@ -37,13 +37,16 @@ }, "author": "Shubh Bapna ", "license": "SEE LICENSE IN LICENSE", + "engines": { + "node": ">=24.0.0" + }, "devDependencies": { "@actions/artifact": "^1.1.0", - "@octokit/rest": "^19.0.4", + "@octokit/rest": "^19.0.13", "@types/express": "^4.17.13", "@types/fs-extra": "^9.0.13", "@types/jest": "^28.1.3", - "@types/node": "^18.0.0", + "@types/node": "^24.0.0", "@typescript-eslint/eslint-plugin": "^5.48.2", "@typescript-eslint/parser": "^5.48.2", "@vercel/ncc": "^0.34.0", @@ -68,7 +71,7 @@ "express": "^4.18.1", "fast-glob": "^3.2.12", "fs-extra": "^10.1.0", - "nock": "^13.2.7", + "nock": "^14.0.15", "simple-git": "^3.8.0", "totalist": "^3.0.0" }, diff --git a/src/endpoint-mocker/request/abstract-request-mocker.ts b/src/endpoint-mocker/request/abstract-request-mocker.ts index 765b76f..9a20664 100644 --- a/src/endpoint-mocker/request/abstract-request-mocker.ts +++ b/src/endpoint-mocker/request/abstract-request-mocker.ts @@ -30,24 +30,59 @@ export abstract class RequestMocker { let path: string | RegExp = this.endpointDetails.path; let regexFlag = false; + // Escape special regex characters in the static parts of the path + // but preserve the parameter placeholders + // Note: We don't escape forward slashes as they're path separators + const escapeRegexExceptPlaceholders = (str: string): string => { + const parts: string[] = []; + let lastIndex = 0; + const placeholderRegex = /{[^{}]+}/g; + let match; + + while ((match = placeholderRegex.exec(str)) !== null) { + // Escape the part before the placeholder + if (match.index > lastIndex) { + const staticPart = str.substring(lastIndex, match.index); + parts.push(staticPart.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")); + } + // Keep the placeholder as-is + parts.push(match[0]); + lastIndex = match.index + match[0].length; + } + + // Escape any remaining part after the last placeholder + if (lastIndex < str.length) { + const staticPart = str.substring(lastIndex); + parts.push(staticPart.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")); + } + + return parts.join(""); + }; + + // Escape the path template if there are parameters + if (this.endpointDetails.path.match(/{[^{}]+}/g)) { + path = escapeRegexExceptPlaceholders(path); + } + // replace any path variables with either values or regex expression for (const match of this.endpointDetails.path.match(/{[^{}]+}/g) ?? []) { let replacementParam; if (pathParams[match.slice(1, -1)]) { const value = pathParams[match.slice(1, -1)]; - replacementParam = value instanceof RegExp ? value.source : `${value}`; + replacementParam = value instanceof RegExp ? value.source : `${value}`.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); regexFlag ||= value instanceof RegExp; } else { replacementParam = ".+"; regexFlag = true; } - path = path.replace(new RegExp(match), replacementParam); + path = path.replace(match, replacementParam); } // if a regex expression was encountered then path is used as a regex expression if (regexFlag) { - path = new RegExp(path); + // Add anchors to match the entire path + path = new RegExp(`^${path}$`); } return { path, query, requestBody }; diff --git a/test/github/action/archive/archive-mocker.test.ts b/test/github/action/archive/archive-mocker.test.ts index fd34d46..cc37e1f 100644 --- a/test/github/action/archive/archive-mocker.test.ts +++ b/test/github/action/archive/archive-mocker.test.ts @@ -47,7 +47,7 @@ describe("setup", () => { describe("teardown", () => { test("artifact store was created", async () => { - const archiveMocker = new ArchiveArtifactsMocker(process.cwd(), "8080"); + const archiveMocker = new ArchiveArtifactsMocker(process.cwd(), "8081"); await archiveMocker.setup(); // mimic the store being created @@ -67,8 +67,12 @@ describe("teardown", () => { test("archive store was not created", async () => { const storePath = path.join(__dirname, "store"); + // Clean up if it exists from previous test runs + if (existsSync(storePath)) { + await rm(storePath, { recursive: true, force: true }); + } mkdirSync(storePath); - const archiveMocker = new ArchiveArtifactsMocker(__dirname, "8080"); + const archiveMocker = new ArchiveArtifactsMocker(__dirname, "8082"); await archiveMocker.setup(); await archiveMocker.teardown(); @@ -86,7 +90,7 @@ describe("teardown", () => { }); test("server has not been started", async () => { - const archiveMocker = new ArchiveArtifactsMocker(process.cwd(), "8080"); + const archiveMocker = new ArchiveArtifactsMocker(process.cwd(), "8083"); await expect(archiveMocker.teardown()).rejects.toThrowError(); }); diff --git a/test/github/repository/branches/repository-branches.test.ts b/test/github/repository/branches/repository-branches.test.ts index 6765dcc..f0fefe7 100644 --- a/test/github/repository/branches/repository-branches.test.ts +++ b/test/github/repository/branches/repository-branches.test.ts @@ -2,6 +2,8 @@ import path from "path"; import simpleGit, { SimpleGit } from "simple-git"; import { RepositoryBranches } from "@mg/github/repository/branches/repository-branches"; import { RepositoryMocker } from "@mg/github/repository/repository-mocker"; +import { existsSync } from "fs"; +import { rm } from "fs/promises"; let repoMocker: RepositoryMocker; let branchCreator: RepositoryBranches; @@ -23,6 +25,15 @@ beforeEach(async () => { afterEach(async () => { await repoMocker.teardown(); + // Extra cleanup to ensure repo directory is removed + const repoDir = path.join(__dirname, "repo"); + if (existsSync(repoDir)) { + try { + await rm(repoDir, { recursive: true, force: true }); + } catch (err) { + // Ignore cleanup errors + } + } }); describe("setup local branches", () => { diff --git a/test/github/repository/history/repository-histor-mocker.test.ts b/test/github/repository/history/repository-histor-mocker.test.ts index 0b4e5aa..69c02a0 100644 --- a/test/github/repository/history/repository-histor-mocker.test.ts +++ b/test/github/repository/history/repository-histor-mocker.test.ts @@ -37,6 +37,15 @@ beforeEach(async () => { afterEach(async () => { await repoMocker.teardown(); + // Extra cleanup to ensure repo directory is removed + const repoDir = path.join(__dirname, "repo"); + if (existsSync(repoDir)) { + try { + await rm(repoDir, { recursive: true, force: true }); + } catch (err) { + // Ignore cleanup errors + } + } }); describe.each([ diff --git a/test/github/repository/repository-mocker.test.ts b/test/github/repository/repository-mocker.test.ts index 553902b..ff39c0b 100644 --- a/test/github/repository/repository-mocker.test.ts +++ b/test/github/repository/repository-mocker.test.ts @@ -13,6 +13,18 @@ import { const setupPath = __dirname; +afterEach(async () => { + // Clean up any repositories created during tests + const repoPath = path.join(setupPath, "repo"); + if (existsSync(repoPath)) { + try { + await rm(repoPath, { recursive: true, force: true }); + } catch (err) { + // Ignore cleanup errors + } + } +}); + describe("setup", () => { test("no repositories", async () => { const repoMocker = new RepositoryMocker({}, setupPath); diff --git a/test/github/repository/state/repository-state.test.ts b/test/github/repository/state/repository-state.test.ts index 7fb479d..ad6117a 100644 --- a/test/github/repository/state/repository-state.test.ts +++ b/test/github/repository/state/repository-state.test.ts @@ -345,12 +345,13 @@ describe("checkout", () => { }); test("repository and branch does exist", async () => { - const simpleGitMock = simpleGit as jest.Mock; const checkoutMock = jest.fn(async _branch => undefined); + const mockedSimpleGit = simpleGit as jest.MockedFunction; - simpleGitMock.mockReturnValue({ + mockedSimpleGit.mockReturnValue({ checkout: checkoutMock - }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any); const repoState = new RepositoryState({ repoA: { @@ -364,7 +365,7 @@ describe("checkout", () => { await expect(repoState.checkout("repoA", "pushed1")).resolves.not.toThrowError(); expect(repoState.getBranchState("repoA")).toMatchObject({currentBranch: "pushed1"}); - expect(simpleGitMock).toHaveBeenCalledWith(repoState.getPath("repoA")); + expect(mockedSimpleGit).toHaveBeenCalledWith(repoState.getPath("repoA")); expect(checkoutMock).toHaveBeenCalledWith("pushed1"); }); }); diff --git a/test/moctokit/moctokit.test.ts b/test/moctokit/moctokit.test.ts index ebbac83..0a81d79 100644 --- a/test/moctokit/moctokit.test.ts +++ b/test/moctokit/moctokit.test.ts @@ -1,11 +1,23 @@ import { Moctokit } from "@mg/moctokit/moctokit"; import { Octokit } from "@octokit/rest"; +import nock from "nock"; + +beforeEach(() => { + // Ensure nock is clean before each test + nock.cleanAll(); +}); + +afterEach(() => { + // Also clean up after each test + nock.cleanAll(); +}); test("with default base url", async () => { const moctokit = new Moctokit(); moctokit.rest.repos .get({ owner: "kie", + repo: /^(project|drools)$/, }) .reply({ status: 200, data: { full_name: "it definitely worked" }, repeat: 2 }); @@ -31,6 +43,7 @@ test("with base url", async () => { moctokit.rest.repos .get({ owner: "kie", + repo: /^(project|drools)$/, }) .reply({ status: 200, data: { full_name: "it definitely worked" }, repeat: 2 }); diff --git a/test/moctokit/request-response-mocker.test.ts b/test/moctokit/request-response-mocker.test.ts index 3d10f87..ee99796 100644 --- a/test/moctokit/request-response-mocker.test.ts +++ b/test/moctokit/request-response-mocker.test.ts @@ -2,12 +2,17 @@ import axios from "axios"; import { EndpointMethod } from "@mg/endpoint-mocker/endpoint-mocker.types"; import { MoctokitRequestMocker } from "@mg/moctokit/request/request-mocker"; +import nock from "nock"; const url = "http://localhost:8000"; const instance = axios.create({ baseURL: url, }); +afterEach(() => { + nock.cleanAll(); +}); + describe.each(["get", "post", "delete", "put", "patch"])( "Method - %p", (method: string) => {