From 3ad03a5dcec7a4498624165b053a434c775e2540 Mon Sep 17 00:00:00 2001 From: "Michael D. Stemle, Jr" Date: Thu, 29 Jun 2023 12:15:50 -0400 Subject: [PATCH] Schema 2.1 update (#41) * Checkpoint. - Reconciling the schemas - Determining my path toward compatibility shifts I need to be able to use another machine for this as well, so I'll be committing incomplete changes. * Create devcontainer.json Signed-off-by: Michael D. Stemle, Jr. * Checkin - Started work on versioning. - Trying to get the Codespaces workflow going * Update devcontainer.json Signed-off-by: Michael D. Stemle, Jr. * Container checkin. * Checkpoint. * Got a bunch of field mappings done. * Got integrations and application in. - Also added some safeties * Primary fields are in the mapping now - Got the fields in - Got the tests working - Time to add convenience fields * Some convenience mappings added. * Tidying up some internal constants. * Mappings with versions are working now! - Org rule files are broken still - Documentation still needs to be updated * Tests are passing! - Still need to work on org-rules file functionality - Still need to update documentation * Massive documentation updates. - Added info about schema versions - Added examples showing the differences in schema versions - Still need to think about org rules file more * I think org rules files are done! * Version bump and docs. * Fixing versions in docs. --------- Signed-off-by: Michael D. Stemle, Jr. --- .devcontainer/devcontainer.json | 14 + .gitignore | 1 + CHANGELOG.md | 11 + README.md | 401 +- __mocks__/@actions/core.js | 3 + .../datadog-service-catalog-schema-v2.1.json | 212 + ...=> datadog-service-catalog-schema-v2.json} | 0 .../fieldMappings-schema.test.js.snap | 87 + .../__snapshots__/fieldMappings.test.js.snap | 87 + .../input-to-registry-document.test.js.snap | 233 +- .../lib/fieldMappings-convenience.test.js | 251 + __tests__/lib/fieldMappings-schema.test.js | 406 ++ __tests__/lib/fieldMappings.test.js | 37 + .../lib/input-to-registry-document.test.js | 232 +- .../org-rules-determineRuleCompliance.test.js | 31 + __tests__/lib/org-rules-extra.test.js | 301 ++ ...rules-determineApplicabilityOfRule.test.js | 95 + action.yml | 59 +- dist/index.js | 4128 +++++++++++------ lib/fieldMappings.js | 293 ++ lib/input-expander.js | 62 +- lib/input-to-registry-document.js | 134 +- lib/input-validation.js | 12 +- lib/org-rules.js | 86 +- package-lock.json | 150 +- package.json | 8 +- 26 files changed, 5710 insertions(+), 1624 deletions(-) create mode 100644 .devcontainer/devcontainer.json create mode 100644 __tests__/data/datadog-service-catalog-schema-v2.1.json rename __tests__/data/{datadog-service-catalog-schema.json => datadog-service-catalog-schema-v2.json} (100%) create mode 100644 __tests__/lib/__snapshots__/fieldMappings-schema.test.js.snap create mode 100644 __tests__/lib/__snapshots__/fieldMappings.test.js.snap create mode 100644 __tests__/lib/fieldMappings-convenience.test.js create mode 100644 __tests__/lib/fieldMappings-schema.test.js create mode 100644 __tests__/lib/fieldMappings.test.js create mode 100644 __tests__/lib/org-rules-extra.test.js create mode 100644 lib/fieldMappings.js diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..a4e6e67 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,14 @@ +{ + "image": "mcr.microsoft.com/devcontainers/typescript-node:20-buster", + "features": { + "ghcr.io/devcontainers-contrib/features/prettier:1": { + "version": "latest" + }, + "ghcr.io/devcontainers-contrib/features/jest:2": { "version": "latest" } + }, + "customizations": { + "vscode": { + "extensions": ["Orta.vscode-jest", "esbenp.prettier-vscode"] + } + } +} diff --git a/.gitignore b/.gitignore index 3292446..34a43a9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ tags node_modules/* coverage +.nova diff --git a/CHANGELOG.md b/CHANGELOG.md index eec5fbe..b8fa146 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog], and this project adheres to [Semantic Versioning]. +## [2.0.0] - 2023-06-29 + +### Added + +- Support for the Datadog Service Catalog v2.1 schema version. + +### Changed + +- Version updates to dependencies. +- Corrected a bunch of documentation problems. + ## [1.1.2] - 2023-03-16 ### Fixed diff --git a/README.md b/README.md index 741e5bb..14d4283 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ The Datadog Service Catalog is a marvelous new way to track which services are i With the Service Catalog registration API, you can supply the Service Catalog with all of the support information you might want: - The name of the service +- The name of the application to which the service belongs - The team which supports and maintains the service - The email address of the team - The URL of the service's documentation, which has a special subtype for runbooks (we _all_ need more runbooks) @@ -22,6 +23,13 @@ Supporting services can be tricky, and the Datadog Service Catalog can make it e **NOTE ABOUT VERSIONING:** This GitHub Action uses the [Service Catalog Definition APIs](https://docs.datadoghq.com/tracing/service_catalog/service_definition_api/#post-a-service-definition) at version 2. Datadog is always working to improve their APIs, and this Action will be updated to support the newer versions of the API as they become available. +## Supported Versions + +At this time, this GitHub Action supports the following versions of the Service Catalog schema: + +- `v2` +- `v2.1` + ## Wait, but why? Datadog already has methods for supplying this information. Why do we need another one? The answer is pretty simple: constraints. @@ -34,47 +42,73 @@ Another reason to use this Action is that it permits your organization to establ ## Supported Metadata Fields -The registration API's links are below, and it takes input per its own JSON schema (also below), but this Action seeks to make things simpler and easier still! Here's a simplified list of the metadata fields that are supported by the Datadog Service Catalog Metadata Provider: +The registration API's links are below, and it takes input per its own JSON schema (also below), but this Action seeks to make things simpler and easier still! There are a lot of fields to choose from across the supported versions, we're going to group them into: Action Fields, Schema Fields, and Convenience Fields. + +- Action Fields are fields that are specific to this GitHub Action. They are not part of the Service Catalog API, but they are used by this Action to make things easier for you. +- Schema Fields are fields that are part of the Service Catalog API. They are not specific to this GitHub Action, but they are used by this Action to make things easier for you. These may vary by `schema-version`. +- Convenience Fields are fields that are not part of the Service Catalog API, but they are used by this Action to make things easier for you. With these fields you need not worry about schema version, this action will map them to supported fields for you. + +### Action Fields + +All of these fields are used for the functioning of this Action. | Field | Description | Required | Default | | --- | --- | --- | --- | +| `schema-version` | This is the version of the schema you're using. This action supports versions `v2` and `v2.1`, with `v2` being the default if no version is specified. | No | `v2` | | `github-token` | This action will use the built-in `GITHUB_TOKEN` for all GitHub access. If you would prefer to use a different GitHub token for the action, please specify it here. | No | `GITHUB_TOKEN` | | `org-rules-file` | If you would prefer to use a different name for your Org Rules File, you can specify it here. This parameter only supports a different file name within the `.github` repository, it will not support an alternate repository. Please make sure that your Org Rules File is accessible to whichever token you use (either `GITHUB_TOKEN` or the `github-token` input value). | No | `.github/service-catalog-rules.yml` | | `datadog-hostname` | The Datadog host to use for the integration, which varies by Datadog customer. [See here for more details:](https://docs.datadoghq.com/getting_started/site/) . Please make sure that you are sure about this value. You'll get an error if it's incorrect. | Yes | `https://api.datadoghq.com` | | `datadog-key` | The Datadog API key to use for the integration. _Please_ use [Encrypted Secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets) to secure your secrets. | Yes | | | `datadog-app-key` | The Datadog Application key to use for the integration. _Please_ use [Encrypted Secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets) to secure your secrets. | Yes | | -| `service-name` | The name of the service. This must be unique across all services. | Yes | | -| `team` | The team that owns the service. | Yes | | -| `email` | The email address of the team that owns the service. | Yes | | -| `slack-support-channel` | The Slack channel where folks can get support for the service. **This must be a Slack URL.** | No | | -| `repo` | The GitHub repository where the service is hosted. This is a convenience input for when you only have one repository for the service. You must either have this value, or you must have values specified in the `repos` object. | No | | -Here's a larger set of metadata fields that are supported by the Datadog Service Catalog Metadata Provider: +### Schema Fields + +These fields directly map to the Service Catalog API. Please see the [Service Catalog API Documentation](https://docs.datadoghq.com/tracing/service_catalog/service_definition_api/#post-a-service-definition) for more information. + +Using a field which is not supported in the schema version you've selected will result in an error. + +| Field | Description | Required | Default | Schema Versions | +| --- | --- | --- | --- | --- | +| `service-name` | The name of the service. This must be unique across all services. | Yes | | `v2`, `v2.1` | +| `team` | The team that owns the service. | Yes | | `v2`, `v2.1` | +| `description` | A description of the service. | No | | `v2.1` | +| `application` | The application that the service belongs to. | No | | `v2.1` | +| `tier` | The importance tier of the service. This is an unconstrained text field where you can use your own tiering definitions. Examples would be `High`, `Critical`, or however you or your organization classify criticality tiers. | No | | `v2.1` | +| `lifecycle` | This is the lifecycle of the service. This text field is unconstrained, and some examples are `production`, `development`, `staging`. | No | | `v2.1` | +| `contacts` | The list of contacts for the service. Each of these contacts is an object. Keep in mind that `email` and `slack-support-channel` are already included as contacts. This list should be in addition to that. These values are supplied as objects, but due to the limitations of GitHub Actions, please supply these object properties as a multi-line string. | No | `[]` | `v2`, `v2.1` | +| `contacts[].name` | The name of the contact. | Yes | | `v2`, `v2.1` | +| `contacts[].type` | The type of the contact. Acceptable values are: `email`, `slack`, and `microsoft-teams` | Yes | | `v2`, `v2.1` | +| `contacts[].contact` | The actual contact information for the contact. For example, if the type is `email`, this would be the email address. | Yes | | `v2`, `v2.1` | +| `repos` | The list of GitHub repositories that are part of the service. You must supply at least one repository. The repositories are supplied as objects, but due to the limitations of GitHub Actions, please supply these object properties as a multi-line string. In `v2.1`, this field is moved under `links`. | Yes | `[]` | `v2` | +| `repos[].name` | The name of the repository. | Yes | | `v2` | +| `repos[].url` | The URL of the repository. | Yes | | `v2` | +| `repos[].provider` | The provider of the repository. Acceptable values are: `Github`. | No | | `v2` | +| `tags` | The list of tags that are associated with the service. This should be a list of key-value pairs separated by colons. | No | | +| `links` | A list of links associated with the service. These links are objects with a variety of properties, but due to the limitations of GitHub Actions, please supply these object properties as a multi-line string. | No | `[]` | `v2`, `v2.1` | +| `links[].name` | The name of the link. | Yes | | `v2`, `v2.1` | +| `links[].url` | The URL of the link. | Yes | | `v2`, `v2.1` | +| `links[].type` | The type for the link. Acceptable values are: `doc`, `wiki`, `runbook`, `url`, `repo`, `dashboard`, `oncall`, `code`, and `link` | Yes | | `v2`, `v2.1` | +| `docs` | A list of documentation links associated with the service. These links are objects with a variety of properties, but due to the limitations of GitHub Actions, please supply these object properties as a multi-line string. In `v2.1`, this field moved under `links`. | No | `[]` | `v2` | +| `docs[].name` | The name of the document. | Yes | | `v2` | +| `docs[].url` | The URL of the document. | Yes | | `v2` | +| `docs[].provider` | The provider for where the documentation lives. Acceptable values are: `Confluence`, `GoogleDocs`, `Github`, `Jira`, `OneNote`, `SharePoint`, and `Dropbox` | No | | `v2` | +| `integrations` | Integrations associated with the service. These integrations are objects with a variety of properties, but due to the limitations of GitHub Actions, please supply these object properties as a multi-line string. | No | `{}` | `v2`, `v2.1` | +| `integrations.opsgenie` | The OpsGenie details for the service. | No | | `v2`, `v2.1` | +| `integrations.opsgenie.service_url` | The service URL for the OpsGenie integration. A team URL will work, but if you want on-call metadata then make sure that this URL is to a service, not a team. | Yes | | `v2`, `v2.1` | +| `integrations.opsgenie.region` | The region for the OpsGenie integration. Acceptable values are `US` and `EU`. | No | | `v2`, `v2.1` | +| `integrations.pagerduty` | The PagerDuty URL for the service. **Important:** In `v2`, this field is just a URL. In `v2.1` this field is a dictionary with a `service-url` property. | No | | `v2`, `v2.1` | +| `integrations.pagerduty.service-url` | The PagerDuty URL for the service. | Yes | | `v2.1` | + +### Convenience Fields | Field | Description | Required | Default | | --- | --- | --- | --- | -| `contacts` | The list of contacts for the service. Each of these contacts is an object. Keep in mind that `email` and `slack-support-channel` are already included as contacts. This list should be in addition to that. These values are supplied as objects, but due to the limitations of GitHub Actions, please supply these object properties as a multi-line string. | No | `[]` | -| `contacts[].name` | The name of the contact. | Yes | | -| `contacts[].type` | The type of the contact. Acceptable values are: `email`, `slack`, and `microsoft-teams` | Yes | | -| `contacts[].value` | The value of the contact. For example, if the type is `email`, this would be the email address. | Yes | | -| `repos` | The list of GitHub repositories that are part of the service. You must supply at least one repository. The repositories are supplied as objects, but due to the limitations of GitHub Actions, please supply these object properties as a multi-line string. | Yes | `[]` | -| `repos[].name` | The name of the repository. | Yes | | -| `repos[].url` | The URL of the repository. | Yes | | -| `repos[].provider` | The provider of the repository. Acceptable values are: `Github`. | No | | -| `tags` | The list of tags that are associated with the service. This should be a list of key-value pairs separated by colons. | No | | -| `links` | A list of links associated with the service. These links are objects with a variety of properties, but due to the limitations of GitHub Actions, please supply these object properties as a multi-line string. | No | `[]` | -| `links[].name` | The name of the link. | Yes | | -| `links[].url` | The URL of the link. | Yes | | -| `links[].type` | The type for the link. Acceptable values are: `doc`, `wiki`, `runbook`, `url`, `repo`, `dashboard`, `oncall`, `code`, and `link` | Yes | | -| `docs` | A list of documentation links associated with the service. These links are objects with a variety of properties, but due to the limitations of GitHub Actions, please supply these object properties as a multi-line string. | No | `[]` | -| `docs[].name` | The name of the document. | Yes | | -| `docs[].url` | The URL of the document. | Yes | | -| `docs[].provider` | The provider for where the documentation lives. Acceptable values are: `Confluence`, `GoogleDocs`, `Github`, `Jira`, `OneNote`, `SharePoint`, and `Dropbox` | No | | -| `integrations` | Integrations associated with the service. These integrations are objects with a variety of properties, but due to the limitations of GitHub Actions, please supply these object properties as a multi-line string. | No | `{}` | -| `integrations.opsgenie` | The OpsGenie details for the service. | No | | -| `integrations.opsgenie.service_url` | The service URL for the OpsGenie integration. A team URL will work, but if you want on-call metadata then make sure that this URL is to a service, not a team. | Yes | | -| `integrations.opsgenie.region` | The region for the OpsGenie integration. Acceptable values are `US` and `EU`. | No | | -| `integrations.pagerduty` | The PagerDuty URL for the service. | No | | +| `email` | The email address of the team that owns the service. | Yes | | +| `slack-support-channel` | The Slack channel where folks can get support for the service. **This must be a Slack URL.** | No | | +| `slack` | This field is an alias for the `slack-support-channel` field. **This must be a Slack URL.** | No | | +| `repo` | The GitHub repository where the service is hosted. In `v2`, this field maps into the `repos` field, but in `v2.1` it maps into the `links` field. | No | | +| `opsgenie` | This is a convenience field for your OpsGenie service URL. | No | | +| `pagerduty` | This is a convenience field for your PagerDuty service URL. | No | | ## Example @@ -88,8 +122,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: arcxp/datadog-service-catalog-metadata-provider@v1 + - uses: arcxp/datadog-service-catalog-metadata-provider@v2 with: + schema-version: v2.1 datadog-hostname: api.us5.datadoghq.com datadog-key: ${{ secrets.DATADOG_KEY }} datadog-app-key: ${{ secrets.DATADOG_APP_KEY }} @@ -109,8 +144,9 @@ jobs: deploy: runs-on: ubuntu-latest steps: - - uses: arcxp/datadog-service-catalog-metadata-provider@v1 + - uses: arcxp/datadog-service-catalog-metadata-provider@v2 with: + schema-version: v2 datadog-hostname: api.us5.datadoghq.com datadog-key: ${{ secrets.DATADOG_API_KEY }} datadog-app-key: ${{ secrets.DATADOG_APPLICATION_KEY }} @@ -130,6 +166,9 @@ jobs: opsgenie: service_url: https://fake-org.hello-world.opsgenie.com region: US + contacts: | + - name: Product Owner + email: john.doe@fake-email-host.com ``` ### Example with multiple repositories @@ -141,8 +180,9 @@ jobs: deploy: runs-on: ubuntu-latest steps: - - uses: arcxp/datadog-service-catalog-metadata-provider@v1 + - uses: arcxp/datadog-service-catalog-metadata-provider@v2 with: + schema-version: v2 datadog-hostname: api.us5.datadoghq.com datadog-key: ${{ secrets.DATADOG_API_KEY }} datadog-app-key: ${{ secrets.DATADOG_APPLICATION_KEY }} @@ -165,12 +205,17 @@ jobs: opsgenie: service_url: https://fake-org.hello-world.opsgenie.com region: US + contacts: | + - name: Product Owner + email: john.doe@fake-email-host.com ``` ### The whole enchilada This is the maximal configuration you could use, in a complete workflow that you could copy-and-paste. It's a bit verbose, but it shows you all the options you have complete with "why." +#### Here it is for schema version `v2` + ```yaml --- name: Datadog Service Catalog Metadata Provider @@ -189,8 +234,9 @@ jobs: runs-on: ubuntu-latest steps: # This uses the custom action to push the service definition to Datadog. - - uses: arcxp/datadog-service-catalog-metadata-provider@v1 + - uses: arcxp/datadog-service-catalog-metadata-provider@v2 with: + service-version: v2 # You should use GitHub's encrypted secrets feature to manage secrets for Datadog. # Don't store your secrets in your workflow files, and don't do anything fancy to get them. # GitHub already gave us a great tool for managing secrets, and it's super easy to use. @@ -249,6 +295,107 @@ jobs: service_url: https://fake-org.hello-world.opsgenie.com region: US pagerduty: https://fake-org.hello-world.pagerduty.com + + # This is the Product Owner, you should contact them if you have suggestions. + contacts: | + - name: Product Owner + email: john.doe@fake-email-host.com +``` + +#### Here it is for schema version `v2.1` + +This is ported over from `v2`, and `v2.1` fields are added. + +```yaml +--- +name: Datadog Service Catalog Metadata Provider + +on: + # This will make my service definition get pushed any time I push a change + # to the main branch of my repository. + push: + branches: + - main + # This trigger will allow me to manually run the Action in GitHub. + workflow_dispatch: + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + # This uses the custom action to push the service definition to Datadog. + - uses: arcxp/datadog-service-catalog-metadata-provider@v2 + with: + service-version: v2.1 + # You should use GitHub's encrypted secrets feature to manage secrets for Datadog. + # Don't store your secrets in your workflow files, and don't do anything fancy to get them. + # GitHub already gave us a great tool for managing secrets, and it's super easy to use. + datadog-hostname: api.us5.datadoghq.com + datadog-key: ${{ secrets.DATADOG_API_KEY }} + datadog-app-key: ${{ secrets.DATADOG_APPLICATION_KEY }} + + # This maps to the `dd-service` field in Datadog, it's just the name of your service. + service-name: hello-world + + # This is the application name, which is used to group services together. + application: hello-world + + # This application is critically important, so let's outline that with the tier field. + tier: critical + + # This service is in production, so let's put that into the lifecycle field + lifecycle: production + + # The name of the team which owns and/or supports the service. + team: Global Greetings + + # The email address of the team which owns and/or supports the service. This is a convenience field + email: global.greetings@fake-email-host.com + + # The URL of the Slack channel where support for the service is handled. + # Keep in mind, this _must_ be a URL. To get the URL, right-click on the channel + # in the Slack app, and select "Copy link" in the "Copy" submenu. + slack-support-channel: 'https://team-name-here.slack.com/archives/ABC123' + + tags: | + - isprod:true + - lang:nodejs + + # Links are great for runbooks, other documentation, other services which + # could be helpful, as well as dashboards. In v2.1 repos and docs move here. + links: | + - name: hello-world (primary service repo) + url: https://github.com/fake-org/hello-world + type: repo + provider: github + - name: some-library + url: https://github.com/fake-org/some-library + type: repo + provider: github + - name: outage-runbook + url: https://fake-org.github.io/hello-world-outage-runbook + type: runbook + - name: hello-world dashboard + url: https://app.datadoghq.com/dashboard/1234567890 + type: dashboard + - name: API Docs + url: https://fake-org.github.io/hello-world-api-docs + type: doc + provider: github + + # These integrations allow folks to be able to see who's on-call for the + # service right from the Datadog Service Catalog. + integrations: | + opsgenie: + service_url: https://fake-org.hello-world.opsgenie.com + region: US + pagerduty: + service-url: https://fake-org.hello-world.pagerduty.com + + # This is the Product Owner, you should contact them if you have suggestions. + contacts: | + - name: Product Owner + email: john.doe@fake-email-host.com ``` ## Quick note on triggers @@ -265,7 +412,11 @@ One of the challenges of running a large set of services is keeping track of wha ### The organization rules YAML file -The place where you will configure your organization's rules is `.github/service-catalog-rules.yml` in your organization's `.github` repository. This file will be a YAML file which contains a list of rules. The syntax of this file is simple YAML, and the rules are simple as well. Here's an example: +The place where you will configure your organization's rules is `.github/service-catalog-rules.yml` in your organization's `.github` repository. This file will be a YAML file which contains a list of rules. The syntax of this file is simple YAML, and the rules are simple as well. + +For schema versioning, backwards compatibility will be maintained. If you would like to make schema version a constraint, there is a field for that in the Org Rules File. + +Here's an example: ```yaml --- @@ -304,32 +455,44 @@ This is the key of your org. There are two reasons why we have this key: #### The `rules` fields +A quick note on versioning and backwards-compatibility: If a field is backwards-compatible, it will be marked as such in the table below. Not all fields are backwards-compatible, and if they are not then they will be skipped if the schema version is mismatched. We are intentionally using the same version numbers here that we use in the Service Catalog schema, this way there is less confusion. If you would like to make schema version a constraint, there is a field for that in the Org Rules File. + The Org Rules File is pretty light-weight, here's a breakdown of the fields: -| Field | Description | Required? | Default Value | -| --- | --- | --- | --- | -| `name` | The name of the rule. This is just for your own reference, it's not used by the Action. | `false` | `undefined` | -| `selection` | The selection criteria for the rule. This is a list of criteria which will be used to select the services which the rule applies to. The word `all` for the value of this field indicates that it is applicable to all definitions for the whole org. This field must be a list, except for the case of `all`. | `true` | No default | -| `selection[].tags` | These are the tags which you can use as selection criteria for this rule. These key-value pairs allow the Metadata Provider to choose which rules will apply. See examples below. | `false` | `{}` | -| `selection[].service-name` | This is the name of the service which you can use as selection criteria for this rule. | `false` | `undefined` | -| `selection[].team` | This is the name of the team which you can use as selection criteria for this rule. | `false` | `undefined` | -| `requirements` | These are the requirements which must be met for the rule to pass. More details for this field are below in "On Requirements." | `true` | No default | -| `requirements[].tags` | These are the tags which you can require for this rule. | `false` | `undefined` | -| `requirements[].tags.` | These are the tag values which you can require for this rule. If you only wish to validate the presence of the tag, use the value `ANY` to indicate that any value is valid. | `false` | `undefined` | -| `requirements[].tags..[]` | You may supply a list of acceptable values as a sequence. Keep in mind that outside of special values (such as `ANY`), all value checks are forced to locale-sensitive lower case. | `false` | `undefined` | -| `requirements[].links` | This structure allows you to have requirements surrounding the `links` section. | `false` | `undefined` | -| `requirements[].links.count` | Require at least this many `links` entries. If you require at least 1 link, you'd put a value here. | `false` | `undefined` | -| `requirements[].links.type` | Require at least one of the `links` entry to have a specific type. If you need more than one, please use two rules, one for each type. | `false` | `undefined` | -| `requirements[].docs` | This structure allows you to have requirements surrounding the `docs` section. | `false` | `undefined` | -| `requirements[].docs.provider` | Require at least one of the `docs` entry to have a specific provider. If you need more than one, please use two rules, one for each provider. **PLEASE NOTE**: This is check is case-sensitive. | `false` | `undefined` | -| `requirements[].docs.count` | Require at least this many `docs` entries. If you require at least 1 doc, you'd put a value here. | `false` | `undefined` | -| `requirements[].contacts` | This structure allows you to have requirements surrounding the `contacts` section. | `false` | `undefined` | -| `requirements[].contacts.count` | Require at least this many `contacts` entries. If you require at least 1 link, you'd put a value here. | `false` | `undefined` | -| `requirements[].contacts.type` | Require at least one of the `contacts` entry to have a specific type. If you need more than one, please use two rules, one for each type. | `false` | `undefined` | -| `requirements[].repos` | This structure allows you to have requirements surrounding the `repos` section. | `false` | `undefined` | -| `requirements[].repos.count` | Require at least this many `repos` entries. If you require at least 1 repo, you'd put a value here. | `false` | `undefined` | -| `requirements[].integrations` | This structure allows you to have requirements surrounding the `integrations` section. | `false` | `undefined` | -| `requirements[].integrations[(opsgenie|pagerduty)]` | With this requirement you can require either an OpsGenie or a PagerDuty integration. | `false` | `[]` | +| Field | Description | Required? | Default Value | Versions Supported | +| --- | --- | --- | --- | --- | +| `name` | The name of the rule. This is just for your own reference, it's not used by the Action. | `false` | `undefined` | all | +| `selection` | The selection criteria for the rule. This is a list of criteria which will be used to select the services which the rule applies to. The word `all` for the value of this field indicates that it is applicable to all definitions for the whole org. This field must be a list, except for the case of `all`. | `true` | No default | all | +| `selection[].schema-version` | The version of the schema which this rule applies to. This is a string which is used to determine which version of the schema to use. If this field is not present then the version will not be considered. Note that fields which are version-specific will cause an error if there is a mismatch, so you may wish to consider having versioned rules in those instances. The value of this field should match one of the supported versions above. | `false` | `undefined` | all | +| `selection[].tags` | These are the tags which you can use as selection criteria for this rule. These key-value pairs allow the Metadata Provider to choose which rules will apply. See examples below. | `false` | `{}` | all | +| `selection[].service-name` | This is the name of the service which you can use as selection criteria for this rule. | `false` | `undefined` | all | +| `selection[].application` | This is the name of the application which you can use as selection criteria for this rule. | `false` | `undefined` | `v2.1` | +| `selection[].tier` | This is the name of the tier which you can use as selection criteria for this rule. | `false` | `undefined` | `v2.1` | +| `selection[].lifecycle` | This is the name of the lifecycle which you can use as selection criteria for this rule. | `false` | `undefined` | `v2.1` | +| `selection[].team` | This is the name of the team which you can use as selection criteria for this rule. | `false` | `undefined` | all | +| `requirements` | These are the requirements which must be met for the rule to pass. More details for this field are below in "On Requirements." | `true` | No default | all | +| `requirements[].schema-version` | This is the version that the schema is constrained to. If this field is not present, this field is not constrained. The value of this field should match one of the supported versions above. | `false` | `undefined` | all | +| `requirements[].application` | This is the name of the application which you can use as a requirement for this rule. | `false` | `undefined` | `v2.1` | +| `requirements[].description` | This is a description of the service which you can use as a requirement for this rule. | `false` | `undefined` | `v2.1` | +| `requirements[].tier` | This is the name of the tier which you can use as a requirement for this rule. | `false` | `undefined` | `v2.1` | +| `requirements[].lifecycle` | This is the name of the lifecycle which you can use as a requirement for this rule. | `false` | `undefined` | `v2.1` | +| `requirements[].tags` | These are the tags which you can require for this rule. | `false` | `undefined` | all | +| `requirements[].tags.` | These are the tag values which you can require for this rule. If you only wish to validate the presence of the tag, use the value `ANY` to indicate that any value is valid. | `false` | `undefined` | all | +| `requirements[].tags..[]` | You may supply a list of acceptable values as a sequence. Keep in mind that outside of special values (such as `ANY`), all value checks are forced to locale-sensitive lower case. | `false` | `undefined` | all | +| `requirements[].links` | This structure allows you to have requirements surrounding the `links` section. | `false` | `undefined` | all | +| `requirements[].links.count` | Require at least this many `links` entries. If you require at least 1 link, you'd put a value here. | `false` | `undefined` | all | +| `requirements[].links.type` | Require at least one of the `links` entry to have a specific type. If you need more than one, please use two rules, one for each type. | `false` | `undefined` | all | +| `requirements[].links.provider` | Require at least one of the `links` entry to have a specific provider. If you need more than one, please use two rules, one for each provider. **PLEASE NOTE**: This is check is case-sensitive, and this property is version-specific. | `false` | `undefined` | `v2.1` | +| `requirements[].docs` | This structure allows you to have requirements surrounding the `docs` section. | `false` | `undefined` | `v2` | +| `requirements[].docs.provider` | Require at least one of the `docs` entry to have a specific provider. If you need more than one, please use two rules, one for each provider. **PLEASE NOTE**: This is check is case-sensitive. | `false` | `undefined` | `v2` | +| `requirements[].docs.count` | Require at least this many `docs` entries. If you require at least 1 doc, you'd put a value here. | `false` | `undefined` | `v2` | +| `requirements[].contacts` | This structure allows you to have requirements surrounding the `contacts` section. | `false` | `undefined` | all | +| `requirements[].contacts.count` | Require at least this many `contacts` entries. If you require at least 1 link, you'd put a value here. | `false` | `undefined` | all | +| `requirements[].contacts.type` | Require at least one of the `contacts` entry to have a specific type. If you need more than one, please use two rules, one for each type. | `false` | `undefined` | all | +| `requirements[].repos` | This structure allows you to have requirements surrounding the `repos` section. | `false` | `undefined` | `v2` | +| `requirements[].repos.count` | Require at least this many `repos` entries. If you require at least 1 repo, you'd put a value here. | `false` | `undefined` | `v2` | +| `requirements[].integrations` | This structure allows you to have requirements surrounding the `integrations` section. | `false` | `undefined` | all | +| `requirements[].integrations[(opsgenie|pagerduty)]` | With this requirement you can require either an OpsGenie or a PagerDuty integration. | `false` | `[]` | all | ##### On Selection @@ -345,38 +508,31 @@ Wildcards are _not_ supported, so all values must be exact matches. Wildcards ma ##### On Requirements -The `requirements` section of the Org Rules file is where you will define the requirements which must be met for the rule to pass. The requirements are a list of requirements, and each requirement is a list of fields which must be present in the service definition. The fields which you can require are: - -- `tags` - - You can require that a service have a specific tag, and you can further constrain that to a list of values. -- `links` - - You can require that a service have a minimum count of links, and you can further constrain that to a type. -- `docs` - - You can require that a service have a at least a certain number of docs. -- `contacts` - - You can require that a service have a minimum count of contacts, and you can further constrain that to a type. -- `repos` - - You can require that a service have a minimum count of repos. -- `integrations(.opsgenie|.pagerduty)` - - You can require that a service have an integration for a specific provider. No further constraints are supported for integrations. +The `requirements` section of the Org Rules file is where you will define the requirements which must be met for the rule to pass. The requirements are a list of requirements, and each requirement is a list of fields which must be present in the service definition. + + The syntax for these requirements is as follows: ```yaml +--- + +org: "my-org" + rules: - name: "This is a test." selection: - - tags: - - isprod: "true" + tags: + isprod: "true" requirements: tags: - - data-sensitivity: - - critical - - high - - medium - - low - - public - - isprod: ANY + - data-sensitivity: + - critical + - high + - medium + - low + - public + - isprod: ANY links: count: 1 type: "runbook" @@ -391,19 +547,84 @@ rules: - pagerduty ``` -This is a maximal set of requirements, but here's what it means: +This is a maximal set of requirements for `v2`, but here's what it means: - The rule applies only to services which have the `isprod` tag, and the value of that tag is `true`. - The service is required to have a tag named `data-sensitivity`, and the value of that tag must be one of `critical`, `high`, `medium`, `low`, or `public`. - The rule requires that the service have at least one `links` entry with the type `runbook`. -- The rule requires that the service have at least one `docs` entry with the name `design` and the provider `confluence`. -- The rule requires that the service have at least one `contacts` entry with the name `oncall` and the type `email`. -- The rule requires that the service also have a second `contacts` entry with the type `slack`. -- The rule requires that the service have at least one `repos` entry with the name `primary`. +- The rule requires that the service have at least one `docs`. +- The rule requires that the service have at least one `contacts` entry with the type `email`. +- The rule requires that the service have at least one `repos`. - The rule requires that the service have at least one `integrations` entry called `pagerduty`. It's encouraged to be judicious in how these are required. Restrictions are inherently, well, restrictive. If you're not careful, you can end up with a situation where you're not able to add new services to your org because they don't meet the requirements of a rule. It's a good idea to start with a minimal set of requirements, and then add more as you go. +### Working with versions + +Because of versioning, the above schema will break with schema `v2.1`. Let's take a look at what this would look like if we wanted the same rules to work across all versions of the schema: + +```yaml +--- + +org: "my-org" + +rules: + - name: "This is a test. (v2)" + selection: + schema-version: v2 + tags: + isprod: "true" + requirements: + tags: + - data-sensitivity: + - critical + - high + - medium + - low + - public + - isprod: ANY + links: + count: 1 + type: "runbook" + docs: + count: 1 + contacts: + type: "email" + count: 2 + repos: + count: 1 + integrations: + - pagerduty + + - name: "This is a test. (v2.1)" + selection: + schema-version: v2.1 + tags: + isprod: "true" + requirements: + tags: + - data-sensitivity: + - critical + - high + - medium + - low + - public + - isprod: ANY + links: + count: 3 + type: + - "runbook" + - "repo" + - "doc" + contacts: + type: "email" + count: 2 + integrations: + - pagerduty +``` + +Since the `repos` and `docs` fields were rolled up under `links` in `v2.1`, this second rule now requires three links, at least one of type `runbook`, one `doc`, and one `repo`. The first rule still shows the older schema version, and works just the way it used to in `v2`. + ## Weird stuff - Datadog will _always_ force your tag names and values to lowercase. The use of lower-case characters in all tags is encouraged, in order to avoid inconsistencies between your definitions and Datadog's. @@ -431,6 +652,14 @@ As with any other application, there are a number of decisions that were made in - If there _is_ a file, but it does not parse, the action will fail. This is to prevent a user from accidentally breaking the Org Rules File, and then not knowing why the action is failing, but also to make sure that if someone intended for rules to be followed, we respect that. - If there is an Org Rules File, but it does not contain any rules, the action will still run, but it will not enforce any rules (because there aren't any). +## Trust, Privacy, and Security + +While this Custom Action does handle sensitive information (mostly your Datadog and GitHub secrets), this information is only used for the purpose of interacting with the Datadog and GitHub APIs. This information is not stored anywhere, and is not used for any other purpose. This Action is open source, and you are encouraged to review the code. + +All security reports and dependency vulnerabilities via GitHub's security features are reviewed and addressed as quickly as possible. If you have more questions, please review the `SECURITY.md` file in this repository. + +In no way does this Action phone home or otherwise send any information to any service other than GitHub or Datadog. + ## References - [Datadog Service Definition API](https://docs.datadoghq.com/tracing/service_catalog/service_definition_api/) diff --git a/__mocks__/@actions/core.js b/__mocks__/@actions/core.js index 92adf84..eb8225f 100644 --- a/__mocks__/@actions/core.js +++ b/__mocks__/@actions/core.js @@ -3,9 +3,12 @@ const core = require('@actions/core') let inputs = {} core.__setInputsObject = (obj) => (inputs = obj) core.__resetInputsObject = () => (inputs = {}) +core.__dumpInputsObject = () => console.debug({ CORE_INPUTS: inputs }) core.getInput = jest.fn().mockImplementation((name) => { return inputs[name] }) +core.setFailed = jest.fn() + module.exports = core diff --git a/__tests__/data/datadog-service-catalog-schema-v2.1.json b/__tests__/data/datadog-service-catalog-schema-v2.1.json new file mode 100644 index 0000000..4410abc --- /dev/null +++ b/__tests__/data/datadog-service-catalog-schema-v2.1.json @@ -0,0 +1,212 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://github.com/DataDog/schema/tree/main/service-catalog/v2.1/schema.json", + "title": "Service Definition Schema v2.1", + "description": "A service definition for providing additional service metadata and integrations v2.1", + "type": "object", + "properties": { + "schema-version": { + "description": "Schema version being used", + "examples": ["v2.1"], + "type": "string", + "default": "v2.1", + "enum": ["v2.1"] + }, + "dd-service": { + "description": "Unique identifier of the service. Must be unique across all services, and is used to match with a service in Datadog", + "examples": ["my-service"], + "type": "string" + }, + "team": { + "description": "Team that owns the service. It is used to locate a team defined in Datadog Teams if it exists", + "examples": ["my-team"], + "type": "string" + }, + "application": { + "description": "Identifier for a group of related services serving a product feature, which the service is a part of", + "examples": ["my-app"], + "type": "string" + }, + "description": { + "description": "A short description of the service", + "examples": ["My app description"], + "type": "string" + }, + "tier": { + "description": "Importance of the service", + "examples": ["1", "High"], + "type": "string" + }, + "lifecycle": { + "description": "The current life cycle phase of the service.", + "examples": ["sandbox", "staging", "production", "deprecated"], + "type": "string" + }, + "contacts": { + "description": "A list of contacts related to the services. ", + "type": "array", + "items": { + "$ref": "#/$defs/contact" + } + }, + "links": { + "description": "A list of links related to the services. ", + "type": "array", + "items": { + "$ref": "#/$defs/link" + } + }, + "tags": { + "description": "A set of custom tags", + "examples": [["my:tag"]], + "type": "array", + "items": { + "type": "string" + } + }, + "integrations": { + "description": "Third party integrations that Datadog supports", + "type": "object", + "properties": { + "pagerduty": { + "description": "Pagerduty integration for the service", + "type": "object", + "properties": { + "service-url": { + "description": "Pagerduty Service URL", + "examples": [ + "https://my-org.pagerduty.com/service-directory/PMyService" + ], + "type": "string", + "pattern": "^(https?://)?[a-zA-Z\\d_\\-.]+\\.pagerduty\\.com/service-directory/(P[a-zA-Z\\d_\\-]+)/?$" + } + }, + "required": ["service-url"], + "additionalProperties": false + }, + "opsgenie": { + "description": "Opsgenie integration for the service", + "type": "object", + "properties": { + "service-url": { + "description": "Opsgenie Service URL", + "examples": [ + "https://www.opsgenie.com/service/123e4567-e89b-12d3-a456-426614174000" + ], + "type": "string", + "pattern": "^(https?://)?[a-zA-Z\\d_\\-.]+\\.opsgenie\\.com/service/([a-zA-Z\\d_\\-]+)/?$" + }, + "region": { + "description": "Opsgenie Instance Region", + "type": "string", + "examples": ["US", "EU"], + "enum": ["US", "EU"] + } + }, + "required": ["service-url"], + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "extensions": { + "description": "Custom extensions", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": false, + "required": ["schema-version", "dd-service"], + "$defs": { + "link": { + "additionalProperties": false, + "type": "object", + "properties": { + "name": { + "description": "Link name", + "examples": ["Runbook", "Dashboard"], + "type": "string" + }, + "type": { + "description": "Link type", + "examples": ["runbook", "doc"], + "type": "string", + "enum": ["doc", "runbook", "repo", "dashboard", "other"] + }, + "url": { + "description": "Link url", + "examples": ["https://my-runbook"], + "type": "string", + "format": "uri" + }, + "provider": { + "description": "Link provider", + "examples": ["Github", "Confluence"], + "type": "string" + } + }, + "required": ["name", "type", "url"] + }, + "contact": { + "additionalProperties": false, + "type": "object", + "properties": { + "name": { + "description": "Contact name", + "examples": ["Oncall Slack", "Team Email"], + "type": "string", + "minLength": 2 + }, + "type": { + "description": "Contact type", + "examples": ["email", "slack", "microsoft-teams"], + "type": "string", + "enum": ["email", "slack", "microsoft-teams"] + }, + "contact": { + "description": "Contact value", + "examples": [ + "contact@datadoghq.com", + "https://my-org.slack.com/archives/my-channel" + ], + "type": "string" + } + }, + "allOf": [ + { + "if": { + "properties": { + "type": { + "const": "email" + } + } + }, + "then": { + "properties": { + "contact": { + "format": "email" + } + } + } + }, + { + "if": { + "properties": { + "type": { + "const": "slack" + } + } + }, + "then": { + "properties": { + "contact": { + "pattern": "https://[a-zA-Z0-9_\\-]+.slack\\.com/archives/[a-zA-Z0-9_\\-]+" + } + } + } + } + ], + "required": ["type", "contact"] + } + } +} diff --git a/__tests__/data/datadog-service-catalog-schema.json b/__tests__/data/datadog-service-catalog-schema-v2.json similarity index 100% rename from __tests__/data/datadog-service-catalog-schema.json rename to __tests__/data/datadog-service-catalog-schema-v2.json diff --git a/__tests__/lib/__snapshots__/fieldMappings-schema.test.js.snap b/__tests__/lib/__snapshots__/fieldMappings-schema.test.js.snap new file mode 100644 index 0000000..d641ec0 --- /dev/null +++ b/__tests__/lib/__snapshots__/fieldMappings-schema.test.js.snap @@ -0,0 +1,87 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`constants convenienceFields 1`] = ` +[ + "email", + "slack", + "repo", + "opsgenie", + "pagerduty", + "slack-support-channel", +] +`; + +exports[`constants mappings 1`] = ` +{ + "application": { + "v2": [Function], + "v2.1": [Function], + }, + "contacts": { + "v2": [Function], + "v2.1": [Function], + }, + "description": { + "v2": [Function], + "v2.1": [Function], + }, + "docs": { + "v2": [Function], + "v2.1": [Function], + }, + "integrations": { + "v2": [Function], + "v2.1": [Function], + }, + "lifecycle": { + "v2": [Function], + "v2.1": [Function], + }, + "links": { + "v2": [Function], + "v2.1": [Function], + }, + "repos": { + "v2": [Function], + "v2.1": [Function], + }, + "schema-version": { + "v2": [Function], + "v2.1": [Function], + }, + "service-name": { + "v2": [Function], + "v2.1": [Function], + }, + "tags": { + "v2": [Function], + "v2.1": [Function], + }, + "team": { + "v2": [Function], + "v2.1": [Function], + }, + "tier": { + "v2": [Function], + "v2.1": [Function], + }, +} +`; + +exports[`constants schemaFields 1`] = ` +[ + "schema-version", + "service-name", + "team", + "contacts", + "tags", + "links", + "integrations", + "docs", + "repos", + "application", + "description", + "tier", + "lifecycle", +] +`; diff --git a/__tests__/lib/__snapshots__/fieldMappings.test.js.snap b/__tests__/lib/__snapshots__/fieldMappings.test.js.snap new file mode 100644 index 0000000..d641ec0 --- /dev/null +++ b/__tests__/lib/__snapshots__/fieldMappings.test.js.snap @@ -0,0 +1,87 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`constants convenienceFields 1`] = ` +[ + "email", + "slack", + "repo", + "opsgenie", + "pagerduty", + "slack-support-channel", +] +`; + +exports[`constants mappings 1`] = ` +{ + "application": { + "v2": [Function], + "v2.1": [Function], + }, + "contacts": { + "v2": [Function], + "v2.1": [Function], + }, + "description": { + "v2": [Function], + "v2.1": [Function], + }, + "docs": { + "v2": [Function], + "v2.1": [Function], + }, + "integrations": { + "v2": [Function], + "v2.1": [Function], + }, + "lifecycle": { + "v2": [Function], + "v2.1": [Function], + }, + "links": { + "v2": [Function], + "v2.1": [Function], + }, + "repos": { + "v2": [Function], + "v2.1": [Function], + }, + "schema-version": { + "v2": [Function], + "v2.1": [Function], + }, + "service-name": { + "v2": [Function], + "v2.1": [Function], + }, + "tags": { + "v2": [Function], + "v2.1": [Function], + }, + "team": { + "v2": [Function], + "v2.1": [Function], + }, + "tier": { + "v2": [Function], + "v2.1": [Function], + }, +} +`; + +exports[`constants schemaFields 1`] = ` +[ + "schema-version", + "service-name", + "team", + "contacts", + "tags", + "links", + "integrations", + "docs", + "repos", + "application", + "description", + "tier", + "lifecycle", +] +`; diff --git a/__tests__/lib/__snapshots__/input-to-registry-document.test.js.snap b/__tests__/lib/__snapshots__/input-to-registry-document.test.js.snap index f86ca72..6d3268e 100644 --- a/__tests__/lib/__snapshots__/input-to-registry-document.test.js.snap +++ b/__tests__/lib/__snapshots__/input-to-registry-document.test.js.snap @@ -1,32 +1,52 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`input-to-registry-document.js #inputsToRegistryDocument() - less input 1`] = ` +exports[`input-to-registry-document.js - schema v2 #inputsToRegistryDocument() - 100% input 1`] = ` { "contacts": [ + { + "contact": "dba-team-name-here@fakeemaildomainthatdoesntexist.com", + "name": "DBA Team Email Alias", + "type": "email", + }, { "contact": "team-name-here@fakeemaildomainthatdoesntexist.com", - "name": "Team Email", "type": "email", }, { "contact": "https://fakeorg.slack.com/archives/A0000000000", - "name": "Support Slack Channel", "type": "slack", }, ], "dd-service": "datadog-service-catalog-metadata-provider-test", - "docs": [], + "docs": [ + { + "name": "GitHub Actions!", + "provider": "Github", + "url": "https://github.com/features/actions", + }, + ], "integrations": { "opsgenie": { "region": "US", "service-url": "https://yourorghere.app.opsgenie.com/service/00000000-0000-0000-0000-000000000000", }, + "pagerduty": "https://my-org.pagerduty.com/service-directory/PMyService", }, - "links": [], + "links": [ + { + "name": "AMI Version Status Dashboard", + "type": "dashboard", + "url": "https://thisisanentirelyfakeurl.seriouslythisisafakehostname.com/dashboard", + }, + ], "repos": [ { - "name": "Service Repository", + "name": "@actions/toolkit", "provider": "Github", + "url": "https://github.com/actions/toolkit", + }, + { + "name": "Repo", "url": "https://github.com/arcxp/datadog-service-catalog-metadata-provider", }, ], @@ -36,22 +56,57 @@ exports[`input-to-registry-document.js #inputsToRegistryDocument() - less input "env:prod", "infrastructure:serverless", "language:nodejs", + "other:value", ], "team": "Team Name Here", } `; -exports[`input-to-registry-document.js #inputsToRegistryDocument() - normal input 1`] = ` +exports[`input-to-registry-document.js - schema v2 #inputsToRegistryDocument() - less input 1`] = ` +{ + "contacts": [ + { + "contact": "team-name-here@fakeemaildomainthatdoesntexist.com", + "type": "email", + }, + { + "contact": "https://fakeorg.slack.com/archives/A0000000000", + "type": "slack", + }, + ], + "dd-service": "datadog-service-catalog-metadata-provider-test", + "integrations": { + "opsgenie": { + "region": "US", + "service-url": "https://yourorghere.app.opsgenie.com/service/00000000-0000-0000-0000-000000000000", + }, + }, + "repos": [ + { + "name": "Repo", + "url": "https://github.com/arcxp/datadog-service-catalog-metadata-provider", + }, + ], + "schema-version": "v2", + "tags": [ + "application:GitHub Action Config Test", + "env:prod", + "infrastructure:serverless", + "language:nodejs", + ], + "team": "Team Name Here", +} +`; + +exports[`input-to-registry-document.js - schema v2 #inputsToRegistryDocument() - normal input 1`] = ` { "contacts": [ { "contact": "team-name-here@fakeemaildomainthatdoesntexist.com", - "name": "Team Email", "type": "email", }, { "contact": "https://fakeorg.slack.com/archives/A0000000000", - "name": "Support Slack Channel", "type": "slack", }, ], @@ -78,17 +133,170 @@ exports[`input-to-registry-document.js #inputsToRegistryDocument() - normal inpu ], "repos": [ { - "name": "Service Repository", + "name": "@actions/toolkit", "provider": "Github", + "url": "https://github.com/actions/toolkit", + }, + { + "name": "Repo", + "url": "https://github.com/arcxp/datadog-service-catalog-metadata-provider", + }, + ], + "schema-version": "v2", + "tags": [ + "application:GitHub Action Config Test", + "env:prod", + "infrastructure:serverless", + "language:nodejs", + "other:value", + ], + "team": "Team Name Here", +} +`; + +exports[`input-to-registry-document.js - schema v2.1 #inputsToRegistryDocument() - 100% input 1`] = ` +{ + "contacts": [ + { + "contact": "dba-team-name-here@fakeemaildomainthatdoesntexist.com", + "name": "DBA Team Email Alias", + "type": "email", + }, + { + "contact": "team-name-here@fakeemaildomainthatdoesntexist.com", + "type": "email", + }, + { + "contact": "https://fakeorg.slack.com/archives/A0000000000", + "type": "slack", + }, + ], + "dd-service": "datadog-service-catalog-metadata-provider-test", + "integrations": { + "opsgenie": { + "region": "US", + "service-url": "https://yourorghere.app.opsgenie.com/service/00000000-0000-0000-0000-000000000000", + }, + "pagerduty": { + "service-url": "https://my-org.pagerduty.com/service-directory/PMyService", + }, + }, + "links": [ + { + "name": "AMI Version Status Dashboard", + "type": "dashboard", + "url": "https://thisisanentirelyfakeurl.seriouslythisisafakehostname.com/dashboard", + }, + { + "name": "@actions/toolkit", + "type": "repo", + "url": "https://github.com/actions/toolkit", + }, + { + "name": "GitHub Actions!", + "type": "doc", + "url": "https://github.com/features/actions", + }, + { + "name": "Repo", + "type": "repo", "url": "https://github.com/arcxp/datadog-service-catalog-metadata-provider", }, + ], + "schema-version": "v2.1", + "tags": [ + "application:GitHub Action Config Test", + "env:prod", + "infrastructure:serverless", + "language:nodejs", + "other:value", + ], + "team": "Team Name Here", +} +`; + +exports[`input-to-registry-document.js - schema v2.1 #inputsToRegistryDocument() - less input 1`] = ` +{ + "contacts": [ + { + "contact": "team-name-here@fakeemaildomainthatdoesntexist.com", + "type": "email", + }, + { + "contact": "https://fakeorg.slack.com/archives/A0000000000", + "type": "slack", + }, + ], + "dd-service": "datadog-service-catalog-metadata-provider-test", + "integrations": { + "opsgenie": { + "region": "US", + "service-url": "https://yourorghere.app.opsgenie.com/service/00000000-0000-0000-0000-000000000000", + }, + }, + "links": [ + { + "name": "Repo", + "type": "repo", + "url": "https://github.com/arcxp/datadog-service-catalog-metadata-provider", + }, + ], + "schema-version": "v2.1", + "tags": [ + "application:GitHub Action Config Test", + "env:prod", + "infrastructure:serverless", + "language:nodejs", + ], + "team": "Team Name Here", +} +`; + +exports[`input-to-registry-document.js - schema v2.1 #inputsToRegistryDocument() - normal input 1`] = ` +{ + "contacts": [ + { + "contact": "team-name-here@fakeemaildomainthatdoesntexist.com", + "type": "email", + }, + { + "contact": "https://fakeorg.slack.com/archives/A0000000000", + "type": "slack", + }, + ], + "dd-service": "datadog-service-catalog-metadata-provider-test", + "description": "This description describes a service.", + "integrations": { + "opsgenie": { + "region": "US", + "service-url": "https://yourorghere.app.opsgenie.com/service/00000000-0000-0000-0000-000000000000", + }, + }, + "lifecycle": "production", + "links": [ { "name": "@actions/toolkit", - "provider": "Github", + "provider": "GitHub", + "type": "repo", "url": "https://github.com/actions/toolkit", }, + { + "name": "AMI Version Status Dashboard", + "type": "dashboard", + "url": "https://thisisanentirelyfakeurl.seriouslythisisafakehostname.com/dashboard", + }, + { + "name": "GitHub Actions!", + "type": "doc", + "url": "https://github.com/features/actions", + }, + { + "name": "Repo", + "type": "repo", + "url": "https://github.com/arcxp/datadog-service-catalog-metadata-provider", + }, ], - "schema-version": "v2", + "schema-version": "v2.1", "tags": [ "application:GitHub Action Config Test", "env:prod", @@ -97,5 +305,6 @@ exports[`input-to-registry-document.js #inputsToRegistryDocument() - normal inpu "other:value", ], "team": "Team Name Here", + "tier": "Tier 1", } `; diff --git a/__tests__/lib/fieldMappings-convenience.test.js b/__tests__/lib/fieldMappings-convenience.test.js new file mode 100644 index 0000000..e2f56c9 --- /dev/null +++ b/__tests__/lib/fieldMappings-convenience.test.js @@ -0,0 +1,251 @@ +/** + * @fileoverview This test covers all of the field mappings across versions. + * @jest-environment node + * @group ci + * @author Mike Stemle + **/ + +const core = require('@actions/core') +const { + mappings, + convenienceFields, + schemaFields, + mapField, +} = require('../../lib/fieldMappings') + +describe.each([ + { + version: 'v2', + field: 'email', + input: 'testing@manchicken.io', + doc: {}, + value: { + contacts: [{ type: 'email', contact: 'testing@manchicken.io' }], + }, + }, + { + version: 'v2', + field: 'email', + input: 'testing@manchicken.io', + doc: { + contacts: [ + { + name: 'test', + type: 'slack', + contact: 'https://my-org.slack.com/archives/my-channel', + }, + ], + }, + value: { + contacts: [ + { + name: 'test', + type: 'slack', + contact: 'https://my-org.slack.com/archives/my-channel', + }, + { type: 'email', contact: 'testing@manchicken.io' }, + ], + }, + }, + { + version: 'v2.1', + field: 'email', + input: 'testing@manchicken.io', + doc: { + contacts: [ + { + name: 'test', + type: 'slack', + contact: 'https://my-org.slack.com/archives/my-channel', + }, + ], + }, + value: { + contacts: [ + { + name: 'test', + type: 'slack', + contact: 'https://my-org.slack.com/archives/my-channel', + }, + { type: 'email', contact: 'testing@manchicken.io' }, + ], + }, + }, + { + version: 'v2', + field: 'slack', + input: 'https://my-org.slack.com/archives/my-channel', + doc: {}, + value: { + contacts: [ + { + type: 'slack', + contact: 'https://my-org.slack.com/archives/my-channel', + }, + ], + }, + }, + { + version: 'v2', + field: 'repo', + input: 'https://github.com/arcxp/datadog-service-catalog-metadata-provider', + doc: { + contacts: [{ type: 'email', contact: 'testing@manchicken.io' }], + }, + value: { + contacts: [{ type: 'email', contact: 'testing@manchicken.io' }], + repos: [ + { + name: 'Repo', + url: 'https://github.com/arcxp/datadog-service-catalog-metadata-provider', + }, + ], + }, + }, + { + version: 'v2.1', + field: 'repo', + input: 'https://github.com/arcxp/datadog-service-catalog-metadata-provider', + doc: { + contacts: [{ type: 'email', contact: 'testing@manchicken.io' }], + }, + value: { + contacts: [{ type: 'email', contact: 'testing@manchicken.io' }], + links: [ + { + name: 'Repo', + type: 'repo', + url: 'https://github.com/arcxp/datadog-service-catalog-metadata-provider', + }, + ], + }, + }, + { + version: 'v2', + field: 'slack', + input: 'https://my-org.slack.com/archives/my-channel', + doc: { + contacts: [{ type: 'email', contact: 'testing@manchicken.io' }], + }, + value: { + contacts: [ + { type: 'email', contact: 'testing@manchicken.io' }, + { + type: 'slack', + contact: 'https://my-org.slack.com/archives/my-channel', + }, + ], + }, + }, + { + version: 'v2.1', + field: 'slack', + input: 'https://my-org.slack.com/archives/my-channel', + doc: { + contacts: [{ type: 'email', contact: 'testing@manchicken.io' }], + }, + value: { + contacts: [ + { type: 'email', contact: 'testing@manchicken.io' }, + { + type: 'slack', + contact: 'https://my-org.slack.com/archives/my-channel', + }, + ], + }, + }, + { + version: 'v2', + field: 'opsgenie', + input: + 'https://www.opsgenies.com/service/123e4567-e89b-12d3-a456-426614174000', + doc: { + contacts: [{ type: 'email', contact: 'testing@manchicken.io' }], + }, + value: { + contacts: [{ type: 'email', contact: 'testing@manchicken.io' }], + integrations: { + opsgenie: { + 'service-url': + 'https://www.opsgenies.com/service/123e4567-e89b-12d3-a456-426614174000', + }, + }, + }, + }, + { + version: 'v2.1', + field: 'opsgenie', + input: + 'https://www.opsgenies.com/service/123e4567-e89b-12d3-a456-426614174000', + doc: { + contacts: [{ type: 'email', contact: 'testing@manchicken.io' }], + }, + value: { + contacts: [{ type: 'email', contact: 'testing@manchicken.io' }], + integrations: { + opsgenie: { + 'service-url': + 'https://www.opsgenies.com/service/123e4567-e89b-12d3-a456-426614174000', + }, + }, + }, + }, + { + version: 'v2', + field: 'pagerduty', + input: 'https://my-org.pagerduty.com/service-directory/PMyService', + doc: { + integrations: { + opsgenie: { + 'service-url': + 'https://www.opsgenies.com/service/123e4567-e89b-12d3-a456-426614174000', + }, + }, + }, + value: { + integrations: { + opsgenie: { + 'service-url': + 'https://www.opsgenies.com/service/123e4567-e89b-12d3-a456-426614174000', + }, + pagerduty: 'https://my-org.pagerduty.com/service-directory/PMyService', + }, + }, + }, + { + version: 'v2.1', + field: 'pagerduty', + input: 'https://my-org.pagerduty.com/service-directory/PMyService', + doc: { + integrations: { + opsgenie: { + 'service-url': + 'https://www.opsgenies.com/service/123e4567-e89b-12d3-a456-426614174000', + }, + }, + }, + value: { + integrations: { + opsgenie: { + 'service-url': + 'https://www.opsgenies.com/service/123e4567-e89b-12d3-a456-426614174000', + }, + pagerduty: { + 'service-url': + 'https://my-org.pagerduty.com/service-directory/PMyService', + }, + }, + }, + }, +])('$field:$version', ({ version, field, input, doc, value }) => { + afterAll(() => { + core.setFailed.mockClear() + core.setFailed.mockReset() + }) + beforeEach(() => { + core.setFailed.mockClear() + }) + test('mapping', () => { + expect(mapField(field, version)(input, doc)).toEqual(value) + }) +}) diff --git a/__tests__/lib/fieldMappings-schema.test.js b/__tests__/lib/fieldMappings-schema.test.js new file mode 100644 index 0000000..8c9b119 --- /dev/null +++ b/__tests__/lib/fieldMappings-schema.test.js @@ -0,0 +1,406 @@ +/** + * @fileoverview This test covers all of the field mappings across versions. + * @jest-environment node + * @group ci + * @author Mike Stemle + **/ + +const core = require('@actions/core') +const { + mappings, + convenienceFields, + schemaFields, + mapField, +} = require('../../lib/fieldMappings') + +describe.each([ + { + version: 'v2', + field: 'schema-version', + input: 'v2', + value: { 'schema-version': 'v2' }, + }, + { + version: 'v2.1', + field: 'schema-version', + input: 'v2.1', + value: { 'schema-version': 'v2.1' }, + }, + { + version: 'v2', + field: 'service-name', + input: 'test-service', + value: { 'dd-service': 'test-service' }, + }, + { + version: 'v2.1', + field: 'service-name', + input: 'test-service', + value: { 'dd-service': 'test-service' }, + }, + { + version: 'v2', + field: 'team', + input: 'app-team-name', + value: { team: 'app-team-name' }, + }, + { + version: 'v2.1', + field: 'team', + input: 'app-team-name', + value: { team: 'app-team-name' }, + }, + { + version: 'v2', + field: 'contacts', + input: ` +- name: Testy McTester + type: email + contact: testy@mctester.com +`, + value: { + contacts: [ + { + name: 'Testy McTester', + type: 'email', + contact: 'testy@mctester.com', + }, + ], + }, + }, + { + version: 'v2.1', + field: 'contacts', + input: ` +- name: Testy McTester + type: email + contact: testy@mctester.com +`, + value: { + contacts: [ + { + name: 'Testy McTester', + type: 'email', + contact: 'testy@mctester.com', + }, + ], + }, + }, + { + version: 'v2', + field: 'tags', + input: ` +- plain:nospaces +- compat1: space-in-value +- compat2 : space-in-both +- number_value : 42 +`, + value: { + tags: [ + 'plain:nospaces', + 'compat1:space-in-value', + 'compat2:space-in-both', + 'number_value:42', + ], + }, + }, + { + version: 'v2.1', + field: 'tags', + input: ` +- plain:nospaces +- compat1: space-in-value +- compat2 : space-in-both +`, + value: { + tags: [ + 'plain:nospaces', + 'compat1:space-in-value', + 'compat2:space-in-both', + ], + }, + }, + { + version: 'v2', + field: 'links', + input: ` +- name: 'first-link' + type: url + url: https://manchicken.io/testing +`, + value: { + links: [ + { + name: 'first-link', + type: 'url', + url: 'https://manchicken.io/testing', + }, + ], + }, + }, + { + version: 'v2', + field: 'links', + input: ` +- name: 'first-link' + type: url + url: https://manchicken.io/testing + provider: Website +`, + value: { + links: [ + { + name: 'first-link', + type: 'url', + url: 'https://manchicken.io/testing', + }, + ], + }, + }, + { + version: 'v2.1', + field: 'links', + input: ` +- name: 'first-link' + type: url + url: https://manchicken.io/testing + provider: Website +`, + value: { + links: [ + { + name: 'first-link', + type: 'url', + url: 'https://manchicken.io/testing', + provider: 'Website', + }, + ], + }, + }, + { + version: 'v2', + field: 'integrations', + input: ` +pagerduty: "https://my-org.pagerduty.com/service-directory/PMyService" +`, + value: { + integrations: { + pagerduty: 'https://my-org.pagerduty.com/service-directory/PMyService', + }, + }, + }, + { + version: 'v2', + field: 'integrations', + input: ` +opsgenie: + service-url: "https://www.opsgenies.com/service/123e4567-e89b-12d3-a456-426614174000" + region: US +`, + value: { + integrations: { + opsgenie: { + 'service-url': + 'https://www.opsgenies.com/service/123e4567-e89b-12d3-a456-426614174000', + region: 'US', + }, + }, + }, + }, + { + version: 'v2.1', + field: 'integrations', + input: ` +pagerduty: + service-url: "https://my-org.pagerduty.com/service-directory/PMyService" +`, + value: { + integrations: { + pagerduty: { + 'service-url': + 'https://my-org.pagerduty.com/service-directory/PMyService', + }, + }, + }, + }, + { + version: 'v2.1', + field: 'integrations', + input: ` +opsgenie: + service-url: "https://www.opsgenies.com/service/123e4567-e89b-12d3-a456-426614174000" + region: US +`, + value: { + integrations: { + opsgenie: { + 'service-url': + 'https://www.opsgenies.com/service/123e4567-e89b-12d3-a456-426614174000', + region: 'US', + }, + }, + }, + }, + { + version: 'v2', + field: 'application', + input: 'app-name', + value: { + error: + 'Sorry, but the «application» field is not avaiable in version v2 of the Datadog Service Catalog schema; this field is only available in version(s): v2.1', + }, + }, + { + version: 'v2.1', + field: 'application', + input: 'app-name', + value: { application: 'app-name' }, + }, + { + version: 'v2', + field: 'description', + input: 'some description', + value: { + error: + 'Sorry, but the «description» field is not avaiable in version v2 of the Datadog Service Catalog schema; this field is only available in version(s): v2.1', + }, + }, + { + version: 'v2.1', + field: 'description', + input: 'some description', + value: { description: 'some description' }, + }, + { + version: 'v2', + field: 'tier', + input: 'high', + value: { + error: + 'Sorry, but the «tier» field is not avaiable in version v2 of the Datadog Service Catalog schema; this field is only available in version(s): v2.1', + }, + }, + { + version: 'v2.1', + field: 'tier', + input: 'high', + value: { tier: 'high' }, + }, + { + version: 'v2', + field: 'lifecycle', + input: 'production', + value: { + error: + 'Sorry, but the «lifecycle» field is not avaiable in version v2 of the Datadog Service Catalog schema; this field is only available in version(s): v2.1', + }, + }, + { + version: 'v2.1', + field: 'lifecycle', + input: 'production', + value: { lifecycle: 'production' }, + }, + { + version: 'v2', + field: 'docs', + input: ` +- name: 'first-doc' + provider: jira + url: https://my-org.atlassian.net/wiki/spaces/PROJ/pages/1234567890 +`, + value: { + docs: [ + { + name: 'first-doc', + provider: 'jira', + url: 'https://my-org.atlassian.net/wiki/spaces/PROJ/pages/1234567890', + }, + ], + }, + }, + { + version: 'v2.1', + field: 'docs', + input: ` +- name: 'first-doc' + provider: jira + url: https://my-org.atlassian.net/wiki/spaces/PROJ/pages/1234567890 +`, + value: { + error: + 'Sorry, but the «docs» field is not avaiable in version v2.1 of the Datadog Service Catalog schema; this field is only available in version(s): v2', + }, + }, + { + version: 'v2', + field: 'repos', + input: ` +- name: 'first-repo' + provider: github + url: https://github.com/arcxp/datadog-service-catalog-metadata-provider +`, + value: { + repos: [ + { + name: 'first-repo', + provider: 'github', + url: 'https://github.com/arcxp/datadog-service-catalog-metadata-provider', + }, + ], + }, + }, + { + version: 'v2.1', + field: 'repos', + input: ` +- name: 'first-repo' + provider: github + url: https://github.com/arcxp/datadog-service-catalog-metadata-provider +`, + value: { + error: + 'Sorry, but the «repos» field is not avaiable in version v2.1 of the Datadog Service Catalog schema; this field is only available in version(s): v2', + }, + }, +])('$field:$version', ({ version, field, input, value }) => { + afterAll(() => { + core.setFailed.mockClear() + core.setFailed.mockReset() + }) + beforeEach(() => { + core.setFailed.mockClear() + }) + test('mapping', () => { + if (value?.error) { + expect(mapField(field, version)(input)).toBeUndefined() + return + } + expect(mapField(field, version)(input)).toEqual(value) + }) + + test('failures', () => { + if (!value?.error) { + expect(core.setFailed).not.toHaveBeenCalled() + return + } + + mapField(field, version)(input) + expect(core.setFailed).toHaveBeenCalledTimes(1) + expect(core.setFailed).toHaveBeenLastCalledWith(value.error) + }) +}) + +describe('constants', () => { + test('mappings', () => { + expect(mappings).toMatchSnapshot() + }) + + test('convenienceFields', () => { + expect(convenienceFields).toMatchSnapshot() + }) + + test('schemaFields', () => { + expect(schemaFields).toMatchSnapshot() + }) +}) diff --git a/__tests__/lib/fieldMappings.test.js b/__tests__/lib/fieldMappings.test.js new file mode 100644 index 0000000..377aecb --- /dev/null +++ b/__tests__/lib/fieldMappings.test.js @@ -0,0 +1,37 @@ +/** + * @fileoverview This test covers all of the field mappings across versions. + * @jest-environment node + * @group ci + * @author Mike Stemle + **/ + +const core = require('@actions/core') +const { + mappings, + convenienceFields, + schemaFields, + mapField, +} = require('../../lib/fieldMappings') + +describe('constants', () => { + test('mappings', () => { + expect(mappings).toMatchSnapshot() + }) + + test('convenienceFields', () => { + expect(convenienceFields).toMatchSnapshot() + }) + + test('schemaFields', () => { + expect(schemaFields).toMatchSnapshot() + }) + + test('mapField for invalid field', () => { + core.setFailed.mockReset() + core.setFailed.mockClear() + mapField('v2', 'invalid-field', 'test')('foo:bar') + expect(core.setFailed).toHaveBeenCalledTimes(1) + core.setFailed.mockReset() + core.setFailed.mockClear() + }) +}) \ No newline at end of file diff --git a/__tests__/lib/input-to-registry-document.test.js b/__tests__/lib/input-to-registry-document.test.js index 3837228..a1ee398 100644 --- a/__tests__/lib/input-to-registry-document.test.js +++ b/__tests__/lib/input-to-registry-document.test.js @@ -1,17 +1,83 @@ +/** + * Tests. + * @jest-environment node + * @group ci + * @author Mike Stemle + **/ + const YAML = require('yaml') const core = require('@actions/core') const Ajv = require('ajv') -const ddSchema = require('../data/datadog-service-catalog-schema.json') -const validate = new Ajv({ strict: false, validateFormats: false }).compile( - ddSchema, +const ddSchema_v2 = require('../data/datadog-service-catalog-schema-v2.json') +const ddSchema_v2_1 = require('../data/datadog-service-catalog-schema-v2.1.json') +const validate_v2 = new Ajv({ strict: false, validateFormats: false }).compile( + ddSchema_v2, ) +const validate_v2_1 = new Ajv({ + strict: false, + validateFormats: false, +}).compile(ddSchema_v2_1) const { inputsToRegistryDocument, } = require('../../lib/input-to-registry-document') -describe('input-to-registry-document.js', () => { +/// ---------------------------- +/// SCHEMA V2.1 +/// ---------------------------- + +describe('input-to-registry-document.js - schema v2', () => { + test('#inputsToRegistryDocument() - 100% input', async () => { + const testInput = ` +--- +schema-version: v2 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: datadog-service-catalog-metadata-provider-test +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +slack-support-channel: 'https://fakeorg.slack.com/archives/A0000000000' +repo: https://github.com/arcxp/datadog-service-catalog-metadata-provider +tags: | + - 'application:GitHub Action Config Test' + - env:prod + - infrastructure:serverless + - language:nodejs + - other : value +repos: | + - url: https://github.com/actions/toolkit + provider: Github + name: "@actions/toolkit" +links: | + - name: AMI Version Status Dashboard + url: https://thisisanentirelyfakeurl.seriouslythisisafakehostname.com/dashboard + type: dashboard +docs: | + - name: GitHub Actions! + url: https://github.com/features/actions + provider: Github +integrations: | + opsgenie: + service-url: https://yourorghere.app.opsgenie.com/service/00000000-0000-0000-0000-000000000000 + region: US + pagerduty: https://my-org.pagerduty.com/service-directory/PMyService +contacts: | + - name: DBA Team Email Alias + type: email + contact: dba-team-name-here@fakeemaildomainthatdoesntexist.com + ` + + core.__setInputsObject(YAML.parse(testInput)) + const inputs = await inputsToRegistryDocument() + expect(validate_v2(inputs)).toStrictEqual(true) + if (validate_v2.errors) { + console.log(validate_v2.errors) + } + expect(validate_v2.errors).toBeNull() + expect(inputs).toMatchSnapshot() + }) + test('#inputsToRegistryDocument() - normal input', async () => { const testInput = ` --- @@ -27,7 +93,7 @@ tags: | - env:prod - infrastructure:serverless - language:nodejs - - other : value + - other : value repos: | - url: https://github.com/actions/toolkit provider: Github @@ -48,14 +114,154 @@ integrations: | core.__setInputsObject(YAML.parse(testInput)) const inputs = await inputsToRegistryDocument() - expect(validate(inputs)).toStrictEqual(true) - expect(validate.errors).toBeNull() + expect(validate_v2(inputs)).toStrictEqual(true) + if (validate_v2.errors) { + console.log(validate_v2.errors) + } + expect(validate_v2.errors).toBeNull() + expect(inputs).toMatchSnapshot() + }) + + test('#inputsToRegistryDocument() - less input', async () => { + const testInput = ` +--- +schema-version: v2 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: datadog-service-catalog-metadata-provider-test +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +slack-support-channel: 'https://fakeorg.slack.com/archives/A0000000000' +repo: https://github.com/arcxp/datadog-service-catalog-metadata-provider +tags: | + - 'application:GitHub Action Config Test' + - env:prod + - infrastructure:serverless + - language:nodejs +integrations: | + opsgenie: + service-url: https://yourorghere.app.opsgenie.com/service/00000000-0000-0000-0000-000000000000 + region: US + ` + + core.__setInputsObject(YAML.parse(testInput)) + const inputs = await inputsToRegistryDocument() + expect(validate_v2(inputs)).toStrictEqual(true) + if (!validate_v2(inputs)) { + console.log(validate_v2_1.errors) + } + expect(validate_v2.errors).toBeNull() + expect(inputs).toMatchSnapshot() + expect(inputs.links).toBeUndefined() + expect(inputs.docs).toBeUndefined() + }) +}) + +/// ---------------------------- +/// SCHEMA V2.1 +/// ---------------------------- + +describe('input-to-registry-document.js - schema v2.1', () => { + test('#inputsToRegistryDocument() - 100% input', async () => { + const testInput = ` +--- +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: datadog-service-catalog-metadata-provider-test +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +slack-support-channel: 'https://fakeorg.slack.com/archives/A0000000000' +repo: https://github.com/arcxp/datadog-service-catalog-metadata-provider +tags: | + - 'application:GitHub Action Config Test' + - env:prod + - infrastructure:serverless + - language:nodejs + - other : value +links: | + - name: AMI Version Status Dashboard + url: https://thisisanentirelyfakeurl.seriouslythisisafakehostname.com/dashboard + type: dashboard + - url: https://github.com/actions/toolkit + type: repo + name: "@actions/toolkit" + - name: GitHub Actions! + url: https://github.com/features/actions + type: doc +integrations: | + opsgenie: + service-url: https://yourorghere.app.opsgenie.com/service/00000000-0000-0000-0000-000000000000 + region: US + pagerduty: + service-url: https://my-org.pagerduty.com/service-directory/PMyService +contacts: | + - name: DBA Team Email Alias + type: email + contact: dba-team-name-here@fakeemaildomainthatdoesntexist.com + ` + + core.__setInputsObject(YAML.parse(testInput)) + const inputs = await inputsToRegistryDocument() + if (!validate_v2_1(inputs)) { + console.log(validate_v2_1.errors) + } + expect(validate_v2_1(inputs)).toStrictEqual(true) + expect(validate_v2_1.errors).toBeNull() + expect(inputs).toMatchSnapshot() + }) + + test('#inputsToRegistryDocument() - normal input', async () => { + const testInput = ` +--- +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: datadog-service-catalog-metadata-provider-test +team: Team Name Here +description: This description describes a service. +tier: Tier 1 +lifecycle: production +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +slack-support-channel: 'https://fakeorg.slack.com/archives/A0000000000' +repo: https://github.com/arcxp/datadog-service-catalog-metadata-provider +tags: | + - 'application:GitHub Action Config Test' + - env:prod + - infrastructure:serverless + - language:nodejs + - other : value +links: | + - url: https://github.com/actions/toolkit + type: repo + name: "@actions/toolkit" + provider: GitHub + - name: AMI Version Status Dashboard + url: https://thisisanentirelyfakeurl.seriouslythisisafakehostname.com/dashboard + type: dashboard + - name: GitHub Actions! + url: https://github.com/features/actions + type: doc +integrations: | + opsgenie: + service-url: https://yourorghere.app.opsgenie.com/service/00000000-0000-0000-0000-000000000000 + region: US + ` + + core.__setInputsObject(YAML.parse(testInput)) + const inputs = await inputsToRegistryDocument() + if (!validate_v2_1(inputs)) { + console.log(validate_v2_1.errors) + } + expect(validate_v2_1(inputs)).toStrictEqual(true) + expect(validate_v2_1.errors).toBeNull() expect(inputs).toMatchSnapshot() }) test('#inputsToRegistryDocument() - less input', async () => { const testInput = ` --- +schema-version: v2.1 datadog-key: FAKE_KEY datadog-app-key: FAKE_KEY service-name: datadog-service-catalog-metadata-provider-test @@ -76,12 +282,14 @@ integrations: | core.__setInputsObject(YAML.parse(testInput)) const inputs = await inputsToRegistryDocument() - expect(validate(inputs)).toStrictEqual(true) - expect(validate.errors).toBeNull() + if (!validate_v2_1(inputs)) { + console.log(validate_v2_1.errors) + } + expect(validate_v2_1(inputs)).toStrictEqual(true) + expect(validate_v2_1.errors).toBeNull() expect(inputs).toMatchSnapshot() expect(Array.isArray(inputs.links)).toBeTruthy() - expect(Array.isArray(inputs.docs)).toBeTruthy() - expect(inputs.links.length).toEqual(0) - expect(inputs.docs.length).toEqual(0) + expect(inputs.links.length).toBe(1) + expect(inputs.docs).toBeUndefined() }) }) diff --git a/__tests__/lib/org-rules-determineRuleCompliance.test.js b/__tests__/lib/org-rules-determineRuleCompliance.test.js index 5883b8a..de2e8c2 100644 --- a/__tests__/lib/org-rules-determineRuleCompliance.test.js +++ b/__tests__/lib/org-rules-determineRuleCompliance.test.js @@ -1054,4 +1054,35 @@ integrations: | determineRuleCompliance(ruleDefinition.rules[0], serviceDefinition), ).toBeFalsy() }) + + test('#determineRuleCompliance() - schema-version selection v2.1', async () => { + const ruleDefinition = YAML.parse(` +--- +org: test-org +rules: + - name: "All services" + selection: + schema-version: v2.1 + requirements: + lifecycle: any + `) + core.__setInputsObject( + YAML.parse(` +--- + +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +lifecycle: production + `), + ) + const serviceDefinition = await inputsToRegistryDocument() + + expect( + determineRuleCompliance(ruleDefinition.rules[0], serviceDefinition), + ).toBeTruthy() + }) }) diff --git a/__tests__/lib/org-rules-extra.test.js b/__tests__/lib/org-rules-extra.test.js new file mode 100644 index 0000000..fa5d96b --- /dev/null +++ b/__tests__/lib/org-rules-extra.test.js @@ -0,0 +1,301 @@ +// Seed these for GitHub's toolkit +const path = require('path') +process.env.GITHUB_EVENT_PATH = path.join( + __dirname, + '../data/github-context-payload.json', +) +process.env.GITHUB_REPOSITORY = + 'arcxp/datadog-service-catalog-metadata-provider' + +const YAML = require('yaml') + +// Pulling this in here activates the mocking of the github module +const github = require('@actions/github') + +// Need to use inputs for some of our parameters +const core = require('@actions/core') + +// This lets us get the inputs the way that they will actually come in. +const { + inputsToRegistryDocument, +} = require('../../lib/input-to-registry-document') +const { + applyOrgRules, + _test: { + fetchRemoteRules, + ghHandle, + determineApplicabilityOfRule, + determineRuleCompliance, + }, +} = require('../../lib/org-rules') + +describe.each([ + { + name: 'application', + orgRules: ` +--- + +org: test-org +rules: + - name: "All services" + selection: + schema-version: v2.1 + requirements: + application: any +`, + tests: [ + { + type: 'selection', + inputs: ` +--- + +schema-version: v2 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +`, + expected: false, + }, + { + type: 'selection', + inputs: ` +--- + +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +application: test-app +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +`, + expected: true, + }, + { + type: 'compliance', + inputs: ` +--- + +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +application: test-app +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +`, + expected: true, + }, + { + type: 'compliance', + inputs: ` +--- + +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +`, + expected: false, + }, + ], + }, + { + name: 'tier', + orgRules: ` +--- + +org: test-org +rules: + - name: "All services" + selection: + schema-version: v2.1 + requirements: + tier: + - p0 + - p1 + - p2 + - p3 +`, + tests: [ + { + type: 'compilance', + inputs: ` +--- + +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +tier: p1 +`, + expected: true, + }, + { + type: 'compilance', + inputs: ` +--- + +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +tier: horse +`, + expected: false, + }, + { + type: 'compilance', + inputs: ` +--- + +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +`, + expected: false, + }, + ], + }, + { + name: 'lifecycle', + orgRules: ` +--- + +org: test-org +rules: + - name: "All services" + selection: + schema-version: v2.1 + requirements: + lifecycle: + - dev + - staging + - beta + - production + - retired +`, + tests: [ + { + type: 'compilance', + inputs: ` +--- + +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +lifecycle: production +`, + expected: true, + }, + { + type: 'compilance', + inputs: ` +--- + +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +`, + expected: false, + }, + { + type: 'compilance', + inputs: ` +--- + +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +lifecycle: chicken +`, + expected: false, + }, + ], + }, + { + name: 'description', + orgRules: ` +--- + +org: test-org +rules: + - name: "All services" + selection: + schema-version: v2.1 + requirements: + description: any +`, + tests: [ + { + type: 'compilance', + inputs: ` +--- + +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +description: testing +`, + expected: true, + }, + { + type: 'compilance', + inputs: ` +--- + +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +`, + expected: false, + }, + ], + }, +])('determineApplicabilityOfRule() - $name', ({ name, orgRules, tests }) => { + beforeEach(() => { + console.warn = jest.fn() // Remove this for debugging details + core.setFailed.mockClear() + core.getInput.mockClear() + }) + + const ruleDefinition = YAML.parse(orgRules) + + test.each(tests)(`${name} - $type`, async ({ type, inputs, expected }) => { + core.__setInputsObject(YAML.parse(inputs)) + const serviceDefinition = await inputsToRegistryDocument() + + const func = + type === 'selection' + ? determineApplicabilityOfRule + : determineRuleCompliance + + expect(func(ruleDefinition.rules[0], serviceDefinition)).toEqual(expected) + }) +}) diff --git a/__tests__/org-rules-determineApplicabilityOfRule.test.js b/__tests__/org-rules-determineApplicabilityOfRule.test.js index 13d0764..8b766c5 100644 --- a/__tests__/org-rules-determineApplicabilityOfRule.test.js +++ b/__tests__/org-rules-determineApplicabilityOfRule.test.js @@ -30,6 +30,10 @@ const { } = require('../lib/org-rules') describe('org-rules.js Org Rules selection', () => { + afterAll(() => { + core.setFailed.mockClear() + core.getInput.mockClear() + }) test('#determineApplicabilityOfRule() - all', async () => { const ruleDefinition = YAML.parse(` --- @@ -373,4 +377,95 @@ repo: foo ), ).toBeFalsy() }) + + test('#determineApplicabilityOfRule() - schema-version safe default v2', async () => { + const ruleDefinition = YAML.parse(` +--- +org: test-org +rules: + - name: "All services" + selection: all + requirements: + lifecycle: any + `) + core.__setInputsObject( + YAML.parse(` +--- + +schema-version: v2 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +lifecycle: production + `), + ) + const serviceDefinition = await inputsToRegistryDocument() + + expect( + determineApplicabilityOfRule(ruleDefinition.rules[0], serviceDefinition), + ).toBeTruthy() + }) + + test('#determineApplicabilityOfRule() - schema-version safe default v2.1', async () => { + const ruleDefinition = YAML.parse(` +--- +org: test-org +rules: + - name: "All services" + selection: all + requirements: + lifecycle: any + `) + core.__setInputsObject( + YAML.parse(` +--- + +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +lifecycle: production + `), + ) + const serviceDefinition = await inputsToRegistryDocument() + + expect( + determineApplicabilityOfRule(ruleDefinition.rules[0], serviceDefinition), + ).toBeTruthy() + }) + + test('#determineApplicabilityOfRule() - schema-version selection v2.1', async () => { + const ruleDefinition = YAML.parse(` +--- +org: test-org +rules: + - name: "All services" + selection: + schema-version: v2.1 + requirements: + lifecycle: any + `) + core.__setInputsObject( + YAML.parse(` +--- + +schema-version: v2.1 +datadog-key: FAKE_KEY +datadog-app-key: FAKE_KEY +service-name: test1 +team: Team Name Here +email: 'team-name-here@fakeemaildomainthatdoesntexist.com' +lifecycle: production + `), + ) + const serviceDefinition = await inputsToRegistryDocument() + + expect( + determineApplicabilityOfRule(ruleDefinition.rules[0], serviceDefinition), + ).toBeTruthy() + }) }) diff --git a/action.yml b/action.yml index d567f0f..fdd5c32 100644 --- a/action.yml +++ b/action.yml @@ -1,20 +1,23 @@ --- name: 'Datadog Service Catalog Metadata Provider' description: 'This is an action which allows you to provide your Datadog Service Catalog metadata to the Datadog Service Catalog' -author: 'Arc XP' +author: 'Mike Stemle ' branding: icon: 'monitor' - color: 'blue' + color: 'purple' runs: using: node16 main: dist/index.js inputs: + # Stuff we need for this action github-token: description: 'The GitHub token to use for the action; default is `secrets.GITHUB_TOKEN`' required: false org-rules-file: description: 'The path to the org rules file; default is repository `ORG-NAME-HERE/.github` and the `service-catalog-rules.yml` file is expected in the root of that repository.' required: false + + # Stuff we need for the Datadog API datadog-hostname: description: 'The Datadog API hostname (this varies by Datadog customer!)' required: true @@ -25,36 +28,60 @@ inputs: datadog-app-key: description: 'The Datadog Application key' required: true + + # Fields which are common to all schema versions + schema-version: + description: 'The version of the Datadog Service Catalog Schema. The default is v2. Valid values are `v2` and `v2.1`.' + required: false + default: 'v2' service-name: description: 'The name of the service' required: true team: description: 'The team responsible for the service' - required: true - email: - description: 'The email address of the team responsible for the service' - required: true - slack-support-channel: - description: 'The slack support channel for the service' - required: false - repo: - description: 'The repository URL for the service. This is a convenience input for when you only have one repository for the service.' required: false contacts: description: 'The contacts for the service' required: false - repos: - description: 'The repositories for the service' - required: true tags: description: 'The tags to apply to the service' required: false links: description: 'The links to related to the service' required: false + integrations: + description: 'The integrations for the service' + required: false + + # Fields which are unique to v2 docs: description: 'The documentation for the service' required: false - integrations: - description: 'The integrations for the service' + repos: + description: 'The repositories for the service' + required: false + + # Fields which are unique to v2.1 + application: + description: '(v2.1 only) The name of the application that the service belongs to.' + required: false + description: + description: '(v2.1 only) A description of the service.' + required: false + tier: + description: '(v2.1 only) A representation of how important this service is. You can use any string that conveys meaning for you or your organization.' + required: false + lifecycle: + description: '(v2.1 only) The current life cycle phase of the service. For example: sandbox, staging, production, deprecated' + required: false + + # These are convenience inputs which are unique to this action. + email: + description: 'The email address of the team responsible for the service' + required: true + slack-support-channel: + description: 'The slack support channel for the service' + required: false + repo: + description: 'The repository URL for the service. This is a convenience input for when you only have one repository for the service.' required: false \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 0e6c595..a94792f 100644 --- a/dist/index.js +++ b/dist/index.js @@ -4,12 +4,24 @@ /***/ 8454: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/** + * input-expander.js + * DDSCMP + * @desc This module contains all of the functions which expand scalar + * input from GitHub Actions into hydrated structures for the DD API. + * + * @author Michael D. Stemle, Jr + */ + const core = __nccwpck_require__(2186) const YAML = __nccwpck_require__(4083) -/* +/** * As part of our recursive implementation, we need * to engage in a little bit of type inference. + * @private + * @param {string} x - The input value. + * @returns {Object|Symbol} The parsed YAML object, or a Symbol. */ const parseSafely = (x) => { try { @@ -18,11 +30,38 @@ const parseSafely = (x) => { return Symbol('This will never match.') } } + +/** + * As part of our recursive implementation, we need to be able to break down different types. This tells us if it's an Array. + * @returns {boolean} Whether or not the input is an array. + * @private + **/ const isArray = Array.isArray + +/** + * As part of our recursive implementation, we need to be able to break down different types. This tells us if it's an Object. + * @param {Object} x - The input value. + * @returns {boolean} Whether or not the input is an object. + * @private + **/ const isObject = (x) => x?.constructor === Object // this is because `YAML.parse(1)` returns `null`. + +/** + * As part of our recursive implementation, we need to be able to break down different types. This tells us if it's a scalar or scalar equivalent. + * @param {any} x - The input value. + * @returns {boolean} Whether or not the input is a scalar or scalar equivalent. + * @private + **/ const isYamlScalarEquivalent = (x) => !x || ['string', 'number', 'boolean'].includes(typeof x) + +/** + * As part of our recursive implementation, we need to be able to break down different types. This tells us if it's a scalar. + * @param {any} x - The input value. + * @returns {boolean} Whether or not the input is a scalar. + * @private + **/ const isJustAScalar = (x) => !x || x[0] === '@' || x === parseSafely(`${x}`) /** @@ -67,27 +106,11 @@ const expandObjectInputs = (str) => { } } -module.exports = { - expandObjectInputs, -} - - -/***/ }), - -/***/ 339: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -const fs = __nccwpck_require__(7147) -const path = __nccwpck_require__(1017) -const core = __nccwpck_require__(2186) -const _ = __nccwpck_require__(250) -const { expandObjectInputs } = __nccwpck_require__(8454) - /** * This function takes an input and forces it to be an array. * @param {any} input - The input to force into an array. * @returns {array} - The input as an array. - * @private + * @public * @function */ const forceArray = (input) => @@ -97,11 +120,38 @@ const forceArray = (input) => * This function takes an input and forces it to be an object. * @param {any} input - The input to force into an object. * @returns {object} - The input as an object. - * @private + * @public * @function */ const forceObject = (input) => (typeof input === 'object' ? input : {}) +module.exports = { + expandObjectInputs, + forceArray, + forceObject, +} + + +/***/ }), + +/***/ 339: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/** + * This module contains the logic for converting the Action inputs into a registry document for Datadog. + * @module lib/input-to-registry-document + * @requires fs + * @requires path + * @requires @actions/core + * @requires lodash + **/ + +const fs = __nccwpck_require__(7147) +const path = __nccwpck_require__(1017) +const core = __nccwpck_require__(2186) +const _ = __nccwpck_require__(250) +const { expandObjectInputs, forceArray, forceObject } = __nccwpck_require__(8454) + /** * This function takes the inputs from the Action and converts them into a registry document for Datadog. * @returns {object} - The registry document. @@ -204,7 +254,7 @@ module.exports = { inputsToRegistryDocument } */ const validateDatadogHostname = (ddHost) => { // Verify the host. - if (!ddHost || !ddHost.match(/^[a-z0-9.-]+\.datadoghq\.(com|eu|us)$/)) { + if (!ddHost || !ddHost.match(/^[a-z0-9.-]+\.(datadoghq\.(com|eu|us)|ddog-gov\.com)$/)) { throw new Error( `Invalid DataDog host: ${ddHost}. See here for more details: https://docs.datadoghq.com/getting_started/site/`, ) @@ -5199,41 +5249,90 @@ exports.request = request; /***/ }), /***/ 5375: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); -Object.defineProperty(exports, "__esModule", ({ value: true })); - -var core = __nccwpck_require__(4952); -var pluginRequestLog = __nccwpck_require__(8883); -var pluginPaginateRest = __nccwpck_require__(606); -var pluginRestEndpointMethods = __nccwpck_require__(4923); - -const VERSION = "19.0.7"; - -const Octokit = core.Octokit.plugin(pluginRequestLog.requestLog, pluginRestEndpointMethods.legacyRestEndpointMethods, pluginPaginateRest.paginateRest).defaults({ +// pkg/dist-src/index.js +var dist_src_exports = {}; +__export(dist_src_exports, { + Octokit: () => Octokit +}); +module.exports = __toCommonJS(dist_src_exports); +var import_core = __nccwpck_require__(4952); +var import_plugin_request_log = __nccwpck_require__(8883); +var import_plugin_paginate_rest = __nccwpck_require__(606); +var import_plugin_rest_endpoint_methods = __nccwpck_require__(4923); + +// pkg/dist-src/version.js +var VERSION = "19.0.12"; + +// pkg/dist-src/index.js +var Octokit = import_core.Octokit.plugin( + import_plugin_request_log.requestLog, + import_plugin_rest_endpoint_methods.legacyRestEndpointMethods, + import_plugin_paginate_rest.paginateRest +).defaults({ userAgent: `octokit-rest.js/${VERSION}` }); - -exports.Octokit = Octokit; -//# sourceMappingURL=index.js.map +// Annotate the CommonJS export names for ESM import in node: +0 && (0); /***/ }), /***/ 7633: -/***/ ((__unused_webpack_module, exports) => { +/***/ ((module) => { "use strict"; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); -Object.defineProperty(exports, "__esModule", ({ value: true })); +// pkg/dist-src/index.js +var dist_src_exports = {}; +__export(dist_src_exports, { + createTokenAuth: () => createTokenAuth +}); +module.exports = __toCommonJS(dist_src_exports); -const REGEX_IS_INSTALLATION_LEGACY = /^v1\./; -const REGEX_IS_INSTALLATION = /^ghs_/; -const REGEX_IS_USER_TO_SERVER = /^ghu_/; +// pkg/dist-src/auth.js +var REGEX_IS_INSTALLATION_LEGACY = /^v1\./; +var REGEX_IS_INSTALLATION = /^ghs_/; +var REGEX_IS_USER_TO_SERVER = /^ghu_/; async function auth(token) { const isApp = token.split(/\./).length === 3; const isInstallation = REGEX_IS_INSTALLATION_LEGACY.test(token) || REGEX_IS_INSTALLATION.test(token); @@ -5241,16 +5340,12 @@ async function auth(token) { const tokenType = isApp ? "app" : isInstallation ? "installation" : isUserToServer ? "user-to-server" : "oauth"; return { type: "token", - token: token, + token, tokenType }; } -/** - * Prefix token for usage in the Authorization header - * - * @param token OAuth token or JSON Web Token - */ +// pkg/dist-src/with-authorization-prefix.js function withAuthorizationPrefix(token) { if (token.split(/\./).length === 3) { return `bearer ${token}`; @@ -5258,52 +5353,118 @@ function withAuthorizationPrefix(token) { return `token ${token}`; } +// pkg/dist-src/hook.js async function hook(token, request, route, parameters) { - const endpoint = request.endpoint.merge(route, parameters); + const endpoint = request.endpoint.merge( + route, + parameters + ); endpoint.headers.authorization = withAuthorizationPrefix(token); return request(endpoint); } -const createTokenAuth = function createTokenAuth(token) { +// pkg/dist-src/index.js +var createTokenAuth = function createTokenAuth2(token) { if (!token) { throw new Error("[@octokit/auth-token] No token passed to createTokenAuth"); } if (typeof token !== "string") { - throw new Error("[@octokit/auth-token] Token passed to createTokenAuth is not a string"); + throw new Error( + "[@octokit/auth-token] Token passed to createTokenAuth is not a string" + ); } token = token.replace(/^(token|bearer) +/i, ""); return Object.assign(auth.bind(null, token), { hook: hook.bind(null, token) }); }; - -exports.createTokenAuth = createTokenAuth; -//# sourceMappingURL=index.js.map +// Annotate the CommonJS export names for ESM import in node: +0 && (0); /***/ }), /***/ 4952: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); -Object.defineProperty(exports, "__esModule", ({ value: true })); - -var universalUserAgent = __nccwpck_require__(5030); -var beforeAfterHook = __nccwpck_require__(3682); -var request = __nccwpck_require__(6206); -var graphql = __nccwpck_require__(7461); -var authToken = __nccwpck_require__(7633); - -const VERSION = "4.2.0"; - -class Octokit { +// pkg/dist-src/index.js +var dist_src_exports = {}; +__export(dist_src_exports, { + Octokit: () => Octokit +}); +module.exports = __toCommonJS(dist_src_exports); +var import_universal_user_agent = __nccwpck_require__(5030); +var import_before_after_hook = __nccwpck_require__(3682); +var import_request = __nccwpck_require__(6206); +var import_graphql = __nccwpck_require__(7461); +var import_auth_token = __nccwpck_require__(7633); + +// pkg/dist-src/version.js +var VERSION = "4.2.3"; + +// pkg/dist-src/index.js +var Octokit = class { + static defaults(defaults) { + const OctokitWithDefaults = class extends this { + constructor(...args) { + const options = args[0] || {}; + if (typeof defaults === "function") { + super(defaults(options)); + return; + } + super( + Object.assign( + {}, + defaults, + options, + options.userAgent && defaults.userAgent ? { + userAgent: `${options.userAgent} ${defaults.userAgent}` + } : null + ) + ); + } + }; + return OctokitWithDefaults; + } + /** + * Attach a plugin (or many) to your Octokit instance. + * + * @example + * const API = Octokit.plugin(plugin1, plugin2, plugin3, ...) + */ + static plugin(...newPlugins) { + var _a; + const currentPlugins = this.plugins; + const NewOctokit = (_a = class extends this { + }, _a.plugins = currentPlugins.concat( + newPlugins.filter((plugin) => !currentPlugins.includes(plugin)) + ), _a); + return NewOctokit; + } constructor(options = {}) { - const hook = new beforeAfterHook.Collection(); + const hook = new import_before_after_hook.Collection(); const requestDefaults = { - baseUrl: request.request.endpoint.DEFAULTS.baseUrl, + baseUrl: import_request.request.endpoint.DEFAULTS.baseUrl, headers: {}, request: Object.assign({}, options.request, { // @ts-ignore internal usage only, no need to type @@ -5313,133 +5474,110 @@ class Octokit { previews: [], format: "" } - }; // prepend default user agent with `options.userAgent` if set - - requestDefaults.headers["user-agent"] = [options.userAgent, `octokit-core.js/${VERSION} ${universalUserAgent.getUserAgent()}`].filter(Boolean).join(" "); - + }; + requestDefaults.headers["user-agent"] = [ + options.userAgent, + `octokit-core.js/${VERSION} ${(0, import_universal_user_agent.getUserAgent)()}` + ].filter(Boolean).join(" "); if (options.baseUrl) { requestDefaults.baseUrl = options.baseUrl; } - if (options.previews) { requestDefaults.mediaType.previews = options.previews; } - if (options.timeZone) { requestDefaults.headers["time-zone"] = options.timeZone; } - - this.request = request.request.defaults(requestDefaults); - this.graphql = graphql.withCustomRequest(this.request).defaults(requestDefaults); - this.log = Object.assign({ - debug: () => {}, - info: () => {}, - warn: console.warn.bind(console), - error: console.error.bind(console) - }, options.log); - this.hook = hook; // (1) If neither `options.authStrategy` nor `options.auth` are set, the `octokit` instance - // is unauthenticated. The `this.auth()` method is a no-op and no request hook is registered. - // (2) If only `options.auth` is set, use the default token authentication strategy. - // (3) If `options.authStrategy` is set then use it and pass in `options.auth`. Always pass own request as many strategies accept a custom request instance. - // TODO: type `options.auth` based on `options.authStrategy`. - + this.request = import_request.request.defaults(requestDefaults); + this.graphql = (0, import_graphql.withCustomRequest)(this.request).defaults(requestDefaults); + this.log = Object.assign( + { + debug: () => { + }, + info: () => { + }, + warn: console.warn.bind(console), + error: console.error.bind(console) + }, + options.log + ); + this.hook = hook; if (!options.authStrategy) { if (!options.auth) { - // (1) this.auth = async () => ({ type: "unauthenticated" }); } else { - // (2) - const auth = authToken.createTokenAuth(options.auth); // @ts-ignore ¯\_(ツ)_/¯ - + const auth = (0, import_auth_token.createTokenAuth)(options.auth); hook.wrap("request", auth.hook); this.auth = auth; } } else { - const { - authStrategy, - ...otherOptions - } = options; - const auth = authStrategy(Object.assign({ - request: this.request, - log: this.log, - // we pass the current octokit instance as well as its constructor options - // to allow for authentication strategies that return a new octokit instance - // that shares the same internal state as the current one. The original - // requirement for this was the "event-octokit" authentication strategy - // of https://github.com/probot/octokit-auth-probot. - octokit: this, - octokitOptions: otherOptions - }, options.auth)); // @ts-ignore ¯\_(ツ)_/¯ - + const { authStrategy, ...otherOptions } = options; + const auth = authStrategy( + Object.assign( + { + request: this.request, + log: this.log, + // we pass the current octokit instance as well as its constructor options + // to allow for authentication strategies that return a new octokit instance + // that shares the same internal state as the current one. The original + // requirement for this was the "event-octokit" authentication strategy + // of https://github.com/probot/octokit-auth-probot. + octokit: this, + octokitOptions: otherOptions + }, + options.auth + ) + ); hook.wrap("request", auth.hook); this.auth = auth; - } // apply plugins - // https://stackoverflow.com/a/16345172 - - + } const classConstructor = this.constructor; - classConstructor.plugins.forEach(plugin => { + classConstructor.plugins.forEach((plugin) => { Object.assign(this, plugin(this, options)); }); } - - static defaults(defaults) { - const OctokitWithDefaults = class extends this { - constructor(...args) { - const options = args[0] || {}; - - if (typeof defaults === "function") { - super(defaults(options)); - return; - } - - super(Object.assign({}, defaults, options, options.userAgent && defaults.userAgent ? { - userAgent: `${options.userAgent} ${defaults.userAgent}` - } : null)); - } - - }; - return OctokitWithDefaults; - } - /** - * Attach a plugin (or many) to your Octokit instance. - * - * @example - * const API = Octokit.plugin(plugin1, plugin2, plugin3, ...) - */ - - - static plugin(...newPlugins) { - var _a; - - const currentPlugins = this.plugins; - const NewOctokit = (_a = class extends this {}, _a.plugins = currentPlugins.concat(newPlugins.filter(plugin => !currentPlugins.includes(plugin))), _a); - return NewOctokit; - } - -} +}; Octokit.VERSION = VERSION; Octokit.plugins = []; - -exports.Octokit = Octokit; -//# sourceMappingURL=index.js.map +// Annotate the CommonJS export names for ESM import in node: +0 && (0); /***/ }), /***/ 6065: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); -Object.defineProperty(exports, "__esModule", ({ value: true })); - -var isPlainObject = __nccwpck_require__(3287); -var universalUserAgent = __nccwpck_require__(5030); +// pkg/dist-src/index.js +var dist_src_exports = {}; +__export(dist_src_exports, { + endpoint: () => endpoint +}); +module.exports = __toCommonJS(dist_src_exports); +// pkg/dist-src/util/lowercase-keys.js function lowercaseKeys(object) { if (!object) { return {}; @@ -5450,64 +5588,62 @@ function lowercaseKeys(object) { }, {}); } +// pkg/dist-src/util/merge-deep.js +var import_is_plain_object = __nccwpck_require__(3287); function mergeDeep(defaults, options) { const result = Object.assign({}, defaults); - Object.keys(options).forEach(key => { - if (isPlainObject.isPlainObject(options[key])) { - if (!(key in defaults)) Object.assign(result, { - [key]: options[key] - });else result[key] = mergeDeep(defaults[key], options[key]); + Object.keys(options).forEach((key) => { + if ((0, import_is_plain_object.isPlainObject)(options[key])) { + if (!(key in defaults)) + Object.assign(result, { [key]: options[key] }); + else + result[key] = mergeDeep(defaults[key], options[key]); } else { - Object.assign(result, { - [key]: options[key] - }); + Object.assign(result, { [key]: options[key] }); } }); return result; } +// pkg/dist-src/util/remove-undefined-properties.js function removeUndefinedProperties(obj) { for (const key in obj) { - if (obj[key] === undefined) { + if (obj[key] === void 0) { delete obj[key]; } } return obj; } +// pkg/dist-src/merge.js function merge(defaults, route, options) { if (typeof route === "string") { let [method, url] = route.split(" "); - options = Object.assign(url ? { - method, - url - } : { - url: method - }, options); + options = Object.assign(url ? { method, url } : { url: method }, options); } else { options = Object.assign({}, route); } - // lowercase header names before merging with defaults to avoid duplicates options.headers = lowercaseKeys(options.headers); - // remove properties with undefined values before merging removeUndefinedProperties(options); removeUndefinedProperties(options.headers); const mergedOptions = mergeDeep(defaults || {}, options); - // mediaType.previews arrays are merged, instead of overwritten if (defaults && defaults.mediaType.previews.length) { - mergedOptions.mediaType.previews = defaults.mediaType.previews.filter(preview => !mergedOptions.mediaType.previews.includes(preview)).concat(mergedOptions.mediaType.previews); + mergedOptions.mediaType.previews = defaults.mediaType.previews.filter((preview) => !mergedOptions.mediaType.previews.includes(preview)).concat(mergedOptions.mediaType.previews); } - mergedOptions.mediaType.previews = mergedOptions.mediaType.previews.map(preview => preview.replace(/-preview/, "")); + mergedOptions.mediaType.previews = mergedOptions.mediaType.previews.map( + (preview) => preview.replace(/-preview/, "") + ); return mergedOptions; } +// pkg/dist-src/util/add-query-parameters.js function addQueryParameters(url, parameters) { const separator = /\?/.test(url) ? "&" : "?"; const names = Object.keys(parameters); if (names.length === 0) { return url; } - return url + separator + names.map(name => { + return url + separator + names.map((name) => { if (name === "q") { return "q=" + parameters.q.split("+").map(encodeURIComponent).join("+"); } @@ -5515,7 +5651,8 @@ function addQueryParameters(url, parameters) { }).join("&"); } -const urlVariableRegex = /\{[^}]+\}/g; +// pkg/dist-src/util/extract-url-variable-names.js +var urlVariableRegex = /\{[^}]+\}/g; function removeNonChars(variableName) { return variableName.replace(/^\W+|\W+$/g, "").split(/,/); } @@ -5527,41 +5664,17 @@ function extractUrlVariableNames(url) { return matches.map(removeNonChars).reduce((a, b) => a.concat(b), []); } +// pkg/dist-src/util/omit.js function omit(object, keysToOmit) { - return Object.keys(object).filter(option => !keysToOmit.includes(option)).reduce((obj, key) => { + return Object.keys(object).filter((option) => !keysToOmit.includes(option)).reduce((obj, key) => { obj[key] = object[key]; return obj; }, {}); } -// Based on https://github.com/bramstein/url-template, licensed under BSD -// TODO: create separate package. -// -// Copyright (c) 2012-2014, Bram Stein -// All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// 3. The name of the author may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -/* istanbul ignore file */ +// pkg/dist-src/util/url-template.js function encodeReserved(str) { - return str.split(/(%[0-9A-Fa-f]{2})/g).map(function (part) { + return str.split(/(%[0-9A-Fa-f]{2})/g).map(function(part) { if (!/%[0-9A-Fa-f]/.test(part)) { part = encodeURI(part).replace(/%5B/g, "[").replace(/%5D/g, "]"); } @@ -5569,7 +5682,7 @@ function encodeReserved(str) { }).join(""); } function encodeUnreserved(str) { - return encodeURIComponent(str).replace(/[!'()*]/g, function (c) { + return encodeURIComponent(str).replace(/[!'()*]/g, function(c) { return "%" + c.charCodeAt(0).toString(16).toUpperCase(); }); } @@ -5582,29 +5695,32 @@ function encodeValue(operator, value, key) { } } function isDefined(value) { - return value !== undefined && value !== null; + return value !== void 0 && value !== null; } function isKeyOperator(operator) { return operator === ";" || operator === "&" || operator === "?"; } function getValues(context, operator, key, modifier) { - var value = context[key], - result = []; + var value = context[key], result = []; if (isDefined(value) && value !== "") { if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") { value = value.toString(); if (modifier && modifier !== "*") { value = value.substring(0, parseInt(modifier, 10)); } - result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : "")); + result.push( + encodeValue(operator, value, isKeyOperator(operator) ? key : "") + ); } else { if (modifier === "*") { if (Array.isArray(value)) { - value.filter(isDefined).forEach(function (value) { - result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : "")); + value.filter(isDefined).forEach(function(value2) { + result.push( + encodeValue(operator, value2, isKeyOperator(operator) ? key : "") + ); }); } else { - Object.keys(value).forEach(function (k) { + Object.keys(value).forEach(function(k) { if (isDefined(value[k])) { result.push(encodeValue(operator, value[k], k)); } @@ -5613,11 +5729,11 @@ function getValues(context, operator, key, modifier) { } else { const tmp = []; if (Array.isArray(value)) { - value.filter(isDefined).forEach(function (value) { - tmp.push(encodeValue(operator, value)); + value.filter(isDefined).forEach(function(value2) { + tmp.push(encodeValue(operator, value2)); }); } else { - Object.keys(value).forEach(function (k) { + Object.keys(value).forEach(function(k) { if (isDefined(value[k])) { tmp.push(encodeUnreserved(k)); tmp.push(encodeValue(operator, value[k].toString())); @@ -5651,67 +5767,77 @@ function parseUrl(template) { } function expand(template, context) { var operators = ["+", "#", ".", "/", ";", "?", "&"]; - return template.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g, function (_, expression, literal) { - if (expression) { - let operator = ""; - const values = []; - if (operators.indexOf(expression.charAt(0)) !== -1) { - operator = expression.charAt(0); - expression = expression.substr(1); - } - expression.split(/,/g).forEach(function (variable) { - var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable); - values.push(getValues(context, operator, tmp[1], tmp[2] || tmp[3])); - }); - if (operator && operator !== "+") { - var separator = ","; - if (operator === "?") { - separator = "&"; - } else if (operator !== "#") { - separator = operator; + return template.replace( + /\{([^\{\}]+)\}|([^\{\}]+)/g, + function(_, expression, literal) { + if (expression) { + let operator = ""; + const values = []; + if (operators.indexOf(expression.charAt(0)) !== -1) { + operator = expression.charAt(0); + expression = expression.substr(1); + } + expression.split(/,/g).forEach(function(variable) { + var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable); + values.push(getValues(context, operator, tmp[1], tmp[2] || tmp[3])); + }); + if (operator && operator !== "+") { + var separator = ","; + if (operator === "?") { + separator = "&"; + } else if (operator !== "#") { + separator = operator; + } + return (values.length !== 0 ? operator : "") + values.join(separator); + } else { + return values.join(","); } - return (values.length !== 0 ? operator : "") + values.join(separator); } else { - return values.join(","); + return encodeReserved(literal); } - } else { - return encodeReserved(literal); } - }); + ); } +// pkg/dist-src/parse.js function parse(options) { - // https://fetch.spec.whatwg.org/#methods let method = options.method.toUpperCase(); - // replace :varname with {varname} to make it RFC 6570 compatible let url = (options.url || "/").replace(/:([a-z]\w+)/g, "{$1}"); let headers = Object.assign({}, options.headers); let body; - let parameters = omit(options, ["method", "baseUrl", "url", "headers", "request", "mediaType"]); - // extract variable names from URL to calculate remaining variables later + let parameters = omit(options, [ + "method", + "baseUrl", + "url", + "headers", + "request", + "mediaType" + ]); const urlVariableNames = extractUrlVariableNames(url); url = parseUrl(url).expand(parameters); if (!/^http/.test(url)) { url = options.baseUrl + url; } - const omittedParameters = Object.keys(options).filter(option => urlVariableNames.includes(option)).concat("baseUrl"); + const omittedParameters = Object.keys(options).filter((option) => urlVariableNames.includes(option)).concat("baseUrl"); const remainingParameters = omit(parameters, omittedParameters); const isBinaryRequest = /application\/octet-stream/i.test(headers.accept); if (!isBinaryRequest) { if (options.mediaType.format) { - // e.g. application/vnd.github.v3+json => application/vnd.github.v3.raw - headers.accept = headers.accept.split(/,/).map(preview => preview.replace(/application\/vnd(\.\w+)(\.v3)?(\.\w+)?(\+json)?$/, `application/vnd$1$2.${options.mediaType.format}`)).join(","); + headers.accept = headers.accept.split(/,/).map( + (preview) => preview.replace( + /application\/vnd(\.\w+)(\.v3)?(\.\w+)?(\+json)?$/, + `application/vnd$1$2.${options.mediaType.format}` + ) + ).join(","); } if (options.mediaType.previews.length) { const previewsFromAcceptHeader = headers.accept.match(/[\w-]+(?=-preview)/g) || []; - headers.accept = previewsFromAcceptHeader.concat(options.mediaType.previews).map(preview => { + headers.accept = previewsFromAcceptHeader.concat(options.mediaType.previews).map((preview) => { const format = options.mediaType.format ? `.${options.mediaType.format}` : "+json"; return `application/vnd.github.${preview}-preview${format}`; }).join(","); } } - // for GET/HEAD requests, set URL query parameters from remaining parameters - // for PATCH/POST/PUT/DELETE requests, set request body from remaining parameters if (["GET", "HEAD"].includes(method)) { url = addQueryParameters(url, remainingParameters); } else { @@ -5723,48 +5849,45 @@ function parse(options) { } } } - // default content-type for JSON if body is set if (!headers["content-type"] && typeof body !== "undefined") { headers["content-type"] = "application/json; charset=utf-8"; } - // GitHub expects 'content-length: 0' header for PUT/PATCH requests without body. - // fetch does not allow to set `content-length` header, but we can set body to an empty string if (["PATCH", "PUT"].includes(method) && typeof body === "undefined") { body = ""; } - // Only return body/request keys if present - return Object.assign({ - method, - url, - headers - }, typeof body !== "undefined" ? { - body - } : null, options.request ? { - request: options.request - } : null); + return Object.assign( + { method, url, headers }, + typeof body !== "undefined" ? { body } : null, + options.request ? { request: options.request } : null + ); } +// pkg/dist-src/endpoint-with-defaults.js function endpointWithDefaults(defaults, route, options) { return parse(merge(defaults, route, options)); } +// pkg/dist-src/with-defaults.js function withDefaults(oldDefaults, newDefaults) { - const DEFAULTS = merge(oldDefaults, newDefaults); - const endpoint = endpointWithDefaults.bind(null, DEFAULTS); - return Object.assign(endpoint, { - DEFAULTS, - defaults: withDefaults.bind(null, DEFAULTS), - merge: merge.bind(null, DEFAULTS), + const DEFAULTS2 = merge(oldDefaults, newDefaults); + const endpoint2 = endpointWithDefaults.bind(null, DEFAULTS2); + return Object.assign(endpoint2, { + DEFAULTS: DEFAULTS2, + defaults: withDefaults.bind(null, DEFAULTS2), + merge: merge.bind(null, DEFAULTS2), parse }); } -const VERSION = "7.0.5"; +// pkg/dist-src/defaults.js +var import_universal_user_agent = __nccwpck_require__(5030); -const userAgent = `octokit-endpoint.js/${VERSION} ${universalUserAgent.getUserAgent()}`; -// DEFAULTS has all properties set that EndpointOptions has, except url. -// So we use RequestParameters and add method as additional required property. -const DEFAULTS = { +// pkg/dist-src/version.js +var VERSION = "7.0.6"; + +// pkg/dist-src/defaults.js +var userAgent = `octokit-endpoint.js/${VERSION} ${(0, import_universal_user_agent.getUserAgent)()}`; +var DEFAULTS = { method: "GET", baseUrl: "https://api.github.com", headers: { @@ -5777,65 +5900,102 @@ const DEFAULTS = { } }; -const endpoint = withDefaults(null, DEFAULTS); - -exports.endpoint = endpoint; -//# sourceMappingURL=index.js.map +// pkg/dist-src/index.js +var endpoint = withDefaults(null, DEFAULTS); +// Annotate the CommonJS export names for ESM import in node: +0 && (0); /***/ }), /***/ 7461: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// pkg/dist-src/index.js +var dist_src_exports = {}; +__export(dist_src_exports, { + GraphqlResponseError: () => GraphqlResponseError, + graphql: () => graphql2, + withCustomRequest: () => withCustomRequest +}); +module.exports = __toCommonJS(dist_src_exports); +var import_request = __nccwpck_require__(6206); +var import_universal_user_agent = __nccwpck_require__(5030); -Object.defineProperty(exports, "__esModule", ({ value: true })); - -var request = __nccwpck_require__(6206); -var universalUserAgent = __nccwpck_require__(5030); - -const VERSION = "5.0.5"; +// pkg/dist-src/version.js +var VERSION = "5.0.6"; +// pkg/dist-src/error.js function _buildMessageForResponseErrors(data) { - return `Request failed due to following response errors:\n` + data.errors.map(e => ` - ${e.message}`).join("\n"); + return `Request failed due to following response errors: +` + data.errors.map((e) => ` - ${e.message}`).join("\n"); } -class GraphqlResponseError extends Error { - constructor(request, headers, response) { +var GraphqlResponseError = class extends Error { + constructor(request2, headers, response) { super(_buildMessageForResponseErrors(response)); - this.request = request; + this.request = request2; this.headers = headers; this.response = response; this.name = "GraphqlResponseError"; - // Expose the errors and response data in their shorthand properties. this.errors = response.errors; this.data = response.data; - // Maintains proper stack trace (only available on V8) - /* istanbul ignore next */ if (Error.captureStackTrace) { Error.captureStackTrace(this, this.constructor); } } -} +}; -const NON_VARIABLE_OPTIONS = ["method", "baseUrl", "url", "headers", "request", "query", "mediaType"]; -const FORBIDDEN_VARIABLE_OPTIONS = ["query", "method", "url"]; -const GHES_V3_SUFFIX_REGEX = /\/api\/v3\/?$/; -function graphql(request, query, options) { +// pkg/dist-src/graphql.js +var NON_VARIABLE_OPTIONS = [ + "method", + "baseUrl", + "url", + "headers", + "request", + "query", + "mediaType" +]; +var FORBIDDEN_VARIABLE_OPTIONS = ["query", "method", "url"]; +var GHES_V3_SUFFIX_REGEX = /\/api\/v3\/?$/; +function graphql(request2, query, options) { if (options) { if (typeof query === "string" && "query" in options) { - return Promise.reject(new Error(`[@octokit/graphql] "query" cannot be used as variable name`)); + return Promise.reject( + new Error(`[@octokit/graphql] "query" cannot be used as variable name`) + ); } for (const key in options) { - if (!FORBIDDEN_VARIABLE_OPTIONS.includes(key)) continue; - return Promise.reject(new Error(`[@octokit/graphql] "${key}" cannot be used as variable name`)); + if (!FORBIDDEN_VARIABLE_OPTIONS.includes(key)) + continue; + return Promise.reject( + new Error(`[@octokit/graphql] "${key}" cannot be used as variable name`) + ); } } - const parsedOptions = typeof query === "string" ? Object.assign({ - query - }, options) : query; - const requestOptions = Object.keys(parsedOptions).reduce((result, key) => { + const parsedOptions = typeof query === "string" ? Object.assign({ query }, options) : query; + const requestOptions = Object.keys( + parsedOptions + ).reduce((result, key) => { if (NON_VARIABLE_OPTIONS.includes(key)) { result[key] = parsedOptions[key]; return result; @@ -5846,26 +6006,29 @@ function graphql(request, query, options) { result.variables[key] = parsedOptions[key]; return result; }, {}); - // workaround for GitHub Enterprise baseUrl set with /api/v3 suffix - // https://github.com/octokit/auth-app.js/issues/111#issuecomment-657610451 - const baseUrl = parsedOptions.baseUrl || request.endpoint.DEFAULTS.baseUrl; + const baseUrl = parsedOptions.baseUrl || request2.endpoint.DEFAULTS.baseUrl; if (GHES_V3_SUFFIX_REGEX.test(baseUrl)) { requestOptions.url = baseUrl.replace(GHES_V3_SUFFIX_REGEX, "/api/graphql"); } - return request(requestOptions).then(response => { + return request2(requestOptions).then((response) => { if (response.data.errors) { const headers = {}; for (const key of Object.keys(response.headers)) { headers[key] = response.headers[key]; } - throw new GraphqlResponseError(requestOptions, headers, response.data); + throw new GraphqlResponseError( + requestOptions, + headers, + response.data + ); } return response.data.data; }); } -function withDefaults(request, newDefaults) { - const newRequest = request.defaults(newDefaults); +// pkg/dist-src/with-defaults.js +function withDefaults(request2, newDefaults) { + const newRequest = request2.defaults(newDefaults); const newApi = (query, options) => { return graphql(newRequest, query, options); }; @@ -5875,9 +6038,10 @@ function withDefaults(request, newDefaults) { }); } -const graphql$1 = withDefaults(request.request, { +// pkg/dist-src/index.js +var graphql2 = withDefaults(import_request.request, { headers: { - "user-agent": `octokit-graphql.js/${VERSION} ${universalUserAgent.getUserAgent()}` + "user-agent": `octokit-graphql.js/${VERSION} ${(0, import_universal_user_agent.getUserAgent)()}` }, method: "POST", url: "/graphql" @@ -5888,43 +6052,50 @@ function withCustomRequest(customRequest) { url: "/graphql" }); } - -exports.GraphqlResponseError = GraphqlResponseError; -exports.graphql = graphql$1; -exports.withCustomRequest = withCustomRequest; -//# sourceMappingURL=index.js.map +// Annotate the CommonJS export names for ESM import in node: +0 && (0); /***/ }), /***/ 606: -/***/ ((__unused_webpack_module, exports) => { +/***/ ((module) => { "use strict"; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// pkg/dist-src/index.js +var dist_src_exports = {}; +__export(dist_src_exports, { + composePaginateRest: () => composePaginateRest, + isPaginatingEndpoint: () => isPaginatingEndpoint, + paginateRest: () => paginateRest, + paginatingEndpoints: () => paginatingEndpoints +}); +module.exports = __toCommonJS(dist_src_exports); -Object.defineProperty(exports, "__esModule", ({ value: true })); - -const VERSION = "6.0.0"; +// pkg/dist-src/version.js +var VERSION = "7.1.2"; -/** - * Some “list” response that can be paginated have a different response structure - * - * They have a `total_count` key in the response (search also has `incomplete_results`, - * /installation/repositories also has `repository_selection`), as well as a key with - * the list of the items which name varies from endpoint to endpoint. - * - * Octokit normalizes these responses so that paginated results are always returned following - * the same structure. One challenge is that if the list response has only one page, no Link - * header is provided, so this header alone is not sufficient to check wether a response is - * paginated or not. - * - * We check if a "total_count" key is present in the response data, but also make sure that - * a "url" property is not, as the "Get the combined status for a specific ref" endpoint would - * otherwise match: https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref - */ +// pkg/dist-src/normalize-paginated-list-response.js function normalizePaginatedListResponse(response) { - // endpoints can respond with 204 if repository is empty if (!response.data) { return { ...response, @@ -5932,9 +6103,8 @@ function normalizePaginatedListResponse(response) { }; } const responseNeedsNormalization = "total_count" in response.data && !("url" in response.data); - if (!responseNeedsNormalization) return response; - // keep the additional properties intact as there is currently no other way - // to retrieve the same information. + if (!responseNeedsNormalization) + return response; const incompleteResults = response.data.incomplete_results; const repositorySelection = response.data.repository_selection; const totalCount = response.data.total_count; @@ -5954,6 +6124,7 @@ function normalizePaginatedListResponse(response) { return response; } +// pkg/dist-src/iterator.js function iterator(octokit, route, parameters) { const options = typeof route === "function" ? route.endpoint(parameters) : octokit.request.endpoint(route, parameters); const requestMethod = typeof route === "function" ? route : octokit.request; @@ -5963,25 +6134,18 @@ function iterator(octokit, route, parameters) { return { [Symbol.asyncIterator]: () => ({ async next() { - if (!url) return { - done: true - }; + if (!url) + return { done: true }; try { - const response = await requestMethod({ - method, - url, - headers - }); + const response = await requestMethod({ method, url, headers }); const normalizedResponse = normalizePaginatedListResponse(response); - // `response.headers.link` format: - // '; rel="next", ; rel="last"' - // sets `url` to undefined if "next" URL is not present or `link` header is not set - url = ((normalizedResponse.headers.link || "").match(/<([^>]+)>;\s*rel="next"/) || [])[1]; - return { - value: normalizedResponse - }; + url = ((normalizedResponse.headers.link || "").match( + /<([^>]+)>;\s*rel="next"/ + ) || [])[1]; + return { value: normalizedResponse }; } catch (error) { - if (error.status !== 409) throw error; + if (error.status !== 409) + throw error; url = ""; return { value: { @@ -5996,15 +6160,21 @@ function iterator(octokit, route, parameters) { }; } +// pkg/dist-src/paginate.js function paginate(octokit, route, parameters, mapFn) { if (typeof parameters === "function") { mapFn = parameters; - parameters = undefined; + parameters = void 0; } - return gather(octokit, [], iterator(octokit, route, parameters)[Symbol.asyncIterator](), mapFn); + return gather( + octokit, + [], + iterator(octokit, route, parameters)[Symbol.asyncIterator](), + mapFn + ); } -function gather(octokit, results, iterator, mapFn) { - return iterator.next().then(result => { +function gather(octokit, results, iterator2, mapFn) { + return iterator2.next().then((result) => { if (result.done) { return results; } @@ -6012,20 +6182,251 @@ function gather(octokit, results, iterator, mapFn) { function done() { earlyExit = true; } - results = results.concat(mapFn ? mapFn(result.value, done) : result.value.data); + results = results.concat( + mapFn ? mapFn(result.value, done) : result.value.data + ); if (earlyExit) { return results; } - return gather(octokit, results, iterator, mapFn); + return gather(octokit, results, iterator2, mapFn); }); } -const composePaginateRest = Object.assign(paginate, { +// pkg/dist-src/compose-paginate.js +var composePaginateRest = Object.assign(paginate, { iterator }); -const paginatingEndpoints = ["GET /app/hook/deliveries", "GET /app/installations", "GET /enterprises/{enterprise}/actions/runner-groups", "GET /enterprises/{enterprise}/dependabot/alerts", "GET /enterprises/{enterprise}/secret-scanning/alerts", "GET /events", "GET /gists", "GET /gists/public", "GET /gists/starred", "GET /gists/{gist_id}/comments", "GET /gists/{gist_id}/commits", "GET /gists/{gist_id}/forks", "GET /installation/repositories", "GET /issues", "GET /licenses", "GET /marketplace_listing/plans", "GET /marketplace_listing/plans/{plan_id}/accounts", "GET /marketplace_listing/stubbed/plans", "GET /marketplace_listing/stubbed/plans/{plan_id}/accounts", "GET /networks/{owner}/{repo}/events", "GET /notifications", "GET /organizations", "GET /orgs/{org}/actions/cache/usage-by-repository", "GET /orgs/{org}/actions/permissions/repositories", "GET /orgs/{org}/actions/required_workflows", "GET /orgs/{org}/actions/runner-groups", "GET /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories", "GET /orgs/{org}/actions/runner-groups/{runner_group_id}/runners", "GET /orgs/{org}/actions/runners", "GET /orgs/{org}/actions/secrets", "GET /orgs/{org}/actions/secrets/{secret_name}/repositories", "GET /orgs/{org}/actions/variables", "GET /orgs/{org}/actions/variables/{name}/repositories", "GET /orgs/{org}/blocks", "GET /orgs/{org}/code-scanning/alerts", "GET /orgs/{org}/codespaces", "GET /orgs/{org}/codespaces/secrets", "GET /orgs/{org}/codespaces/secrets/{secret_name}/repositories", "GET /orgs/{org}/dependabot/alerts", "GET /orgs/{org}/dependabot/secrets", "GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories", "GET /orgs/{org}/events", "GET /orgs/{org}/failed_invitations", "GET /orgs/{org}/hooks", "GET /orgs/{org}/hooks/{hook_id}/deliveries", "GET /orgs/{org}/installations", "GET /orgs/{org}/invitations", "GET /orgs/{org}/invitations/{invitation_id}/teams", "GET /orgs/{org}/issues", "GET /orgs/{org}/members", "GET /orgs/{org}/members/{username}/codespaces", "GET /orgs/{org}/migrations", "GET /orgs/{org}/migrations/{migration_id}/repositories", "GET /orgs/{org}/outside_collaborators", "GET /orgs/{org}/packages", "GET /orgs/{org}/packages/{package_type}/{package_name}/versions", "GET /orgs/{org}/projects", "GET /orgs/{org}/public_members", "GET /orgs/{org}/repos", "GET /orgs/{org}/secret-scanning/alerts", "GET /orgs/{org}/teams", "GET /orgs/{org}/teams/{team_slug}/discussions", "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments", "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions", "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions", "GET /orgs/{org}/teams/{team_slug}/invitations", "GET /orgs/{org}/teams/{team_slug}/members", "GET /orgs/{org}/teams/{team_slug}/projects", "GET /orgs/{org}/teams/{team_slug}/repos", "GET /orgs/{org}/teams/{team_slug}/teams", "GET /projects/columns/{column_id}/cards", "GET /projects/{project_id}/collaborators", "GET /projects/{project_id}/columns", "GET /repos/{org}/{repo}/actions/required_workflows", "GET /repos/{owner}/{repo}/actions/artifacts", "GET /repos/{owner}/{repo}/actions/caches", "GET /repos/{owner}/{repo}/actions/required_workflows/{required_workflow_id_for_repo}/runs", "GET /repos/{owner}/{repo}/actions/runners", "GET /repos/{owner}/{repo}/actions/runs", "GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts", "GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs", "GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs", "GET /repos/{owner}/{repo}/actions/secrets", "GET /repos/{owner}/{repo}/actions/variables", "GET /repos/{owner}/{repo}/actions/workflows", "GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs", "GET /repos/{owner}/{repo}/assignees", "GET /repos/{owner}/{repo}/branches", "GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations", "GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs", "GET /repos/{owner}/{repo}/code-scanning/alerts", "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances", "GET /repos/{owner}/{repo}/code-scanning/analyses", "GET /repos/{owner}/{repo}/codespaces", "GET /repos/{owner}/{repo}/codespaces/devcontainers", "GET /repos/{owner}/{repo}/codespaces/secrets", "GET /repos/{owner}/{repo}/collaborators", "GET /repos/{owner}/{repo}/comments", "GET /repos/{owner}/{repo}/comments/{comment_id}/reactions", "GET /repos/{owner}/{repo}/commits", "GET /repos/{owner}/{repo}/commits/{commit_sha}/comments", "GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls", "GET /repos/{owner}/{repo}/commits/{ref}/check-runs", "GET /repos/{owner}/{repo}/commits/{ref}/check-suites", "GET /repos/{owner}/{repo}/commits/{ref}/status", "GET /repos/{owner}/{repo}/commits/{ref}/statuses", "GET /repos/{owner}/{repo}/contributors", "GET /repos/{owner}/{repo}/dependabot/alerts", "GET /repos/{owner}/{repo}/dependabot/secrets", "GET /repos/{owner}/{repo}/deployments", "GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses", "GET /repos/{owner}/{repo}/environments", "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies", "GET /repos/{owner}/{repo}/events", "GET /repos/{owner}/{repo}/forks", "GET /repos/{owner}/{repo}/hooks", "GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries", "GET /repos/{owner}/{repo}/invitations", "GET /repos/{owner}/{repo}/issues", "GET /repos/{owner}/{repo}/issues/comments", "GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions", "GET /repos/{owner}/{repo}/issues/events", "GET /repos/{owner}/{repo}/issues/{issue_number}/comments", "GET /repos/{owner}/{repo}/issues/{issue_number}/events", "GET /repos/{owner}/{repo}/issues/{issue_number}/labels", "GET /repos/{owner}/{repo}/issues/{issue_number}/reactions", "GET /repos/{owner}/{repo}/issues/{issue_number}/timeline", "GET /repos/{owner}/{repo}/keys", "GET /repos/{owner}/{repo}/labels", "GET /repos/{owner}/{repo}/milestones", "GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels", "GET /repos/{owner}/{repo}/notifications", "GET /repos/{owner}/{repo}/pages/builds", "GET /repos/{owner}/{repo}/projects", "GET /repos/{owner}/{repo}/pulls", "GET /repos/{owner}/{repo}/pulls/comments", "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions", "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments", "GET /repos/{owner}/{repo}/pulls/{pull_number}/commits", "GET /repos/{owner}/{repo}/pulls/{pull_number}/files", "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews", "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments", "GET /repos/{owner}/{repo}/releases", "GET /repos/{owner}/{repo}/releases/{release_id}/assets", "GET /repos/{owner}/{repo}/releases/{release_id}/reactions", "GET /repos/{owner}/{repo}/secret-scanning/alerts", "GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations", "GET /repos/{owner}/{repo}/stargazers", "GET /repos/{owner}/{repo}/subscribers", "GET /repos/{owner}/{repo}/tags", "GET /repos/{owner}/{repo}/teams", "GET /repos/{owner}/{repo}/topics", "GET /repositories", "GET /repositories/{repository_id}/environments/{environment_name}/secrets", "GET /repositories/{repository_id}/environments/{environment_name}/variables", "GET /search/code", "GET /search/commits", "GET /search/issues", "GET /search/labels", "GET /search/repositories", "GET /search/topics", "GET /search/users", "GET /teams/{team_id}/discussions", "GET /teams/{team_id}/discussions/{discussion_number}/comments", "GET /teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions", "GET /teams/{team_id}/discussions/{discussion_number}/reactions", "GET /teams/{team_id}/invitations", "GET /teams/{team_id}/members", "GET /teams/{team_id}/projects", "GET /teams/{team_id}/repos", "GET /teams/{team_id}/teams", "GET /user/blocks", "GET /user/codespaces", "GET /user/codespaces/secrets", "GET /user/emails", "GET /user/followers", "GET /user/following", "GET /user/gpg_keys", "GET /user/installations", "GET /user/installations/{installation_id}/repositories", "GET /user/issues", "GET /user/keys", "GET /user/marketplace_purchases", "GET /user/marketplace_purchases/stubbed", "GET /user/memberships/orgs", "GET /user/migrations", "GET /user/migrations/{migration_id}/repositories", "GET /user/orgs", "GET /user/packages", "GET /user/packages/{package_type}/{package_name}/versions", "GET /user/public_emails", "GET /user/repos", "GET /user/repository_invitations", "GET /user/ssh_signing_keys", "GET /user/starred", "GET /user/subscriptions", "GET /user/teams", "GET /users", "GET /users/{username}/events", "GET /users/{username}/events/orgs/{org}", "GET /users/{username}/events/public", "GET /users/{username}/followers", "GET /users/{username}/following", "GET /users/{username}/gists", "GET /users/{username}/gpg_keys", "GET /users/{username}/keys", "GET /users/{username}/orgs", "GET /users/{username}/packages", "GET /users/{username}/projects", "GET /users/{username}/received_events", "GET /users/{username}/received_events/public", "GET /users/{username}/repos", "GET /users/{username}/ssh_signing_keys", "GET /users/{username}/starred", "GET /users/{username}/subscriptions"]; +// pkg/dist-src/generated/paginating-endpoints.js +var paginatingEndpoints = [ + "GET /app/hook/deliveries", + "GET /app/installation-requests", + "GET /app/installations", + "GET /enterprises/{enterprise}/dependabot/alerts", + "GET /enterprises/{enterprise}/secret-scanning/alerts", + "GET /events", + "GET /gists", + "GET /gists/public", + "GET /gists/starred", + "GET /gists/{gist_id}/comments", + "GET /gists/{gist_id}/commits", + "GET /gists/{gist_id}/forks", + "GET /installation/repositories", + "GET /issues", + "GET /licenses", + "GET /marketplace_listing/plans", + "GET /marketplace_listing/plans/{plan_id}/accounts", + "GET /marketplace_listing/stubbed/plans", + "GET /marketplace_listing/stubbed/plans/{plan_id}/accounts", + "GET /networks/{owner}/{repo}/events", + "GET /notifications", + "GET /organizations", + "GET /organizations/{org}/personal-access-token-requests", + "GET /organizations/{org}/personal-access-token-requests/{pat_request_id}/repositories", + "GET /organizations/{org}/personal-access-tokens", + "GET /organizations/{org}/personal-access-tokens/{pat_id}/repositories", + "GET /orgs/{org}/actions/cache/usage-by-repository", + "GET /orgs/{org}/actions/permissions/repositories", + "GET /orgs/{org}/actions/required_workflows", + "GET /orgs/{org}/actions/runners", + "GET /orgs/{org}/actions/secrets", + "GET /orgs/{org}/actions/secrets/{secret_name}/repositories", + "GET /orgs/{org}/actions/variables", + "GET /orgs/{org}/actions/variables/{name}/repositories", + "GET /orgs/{org}/blocks", + "GET /orgs/{org}/code-scanning/alerts", + "GET /orgs/{org}/codespaces", + "GET /orgs/{org}/codespaces/secrets", + "GET /orgs/{org}/codespaces/secrets/{secret_name}/repositories", + "GET /orgs/{org}/dependabot/alerts", + "GET /orgs/{org}/dependabot/secrets", + "GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories", + "GET /orgs/{org}/events", + "GET /orgs/{org}/failed_invitations", + "GET /orgs/{org}/hooks", + "GET /orgs/{org}/hooks/{hook_id}/deliveries", + "GET /orgs/{org}/installations", + "GET /orgs/{org}/invitations", + "GET /orgs/{org}/invitations/{invitation_id}/teams", + "GET /orgs/{org}/issues", + "GET /orgs/{org}/members", + "GET /orgs/{org}/members/{username}/codespaces", + "GET /orgs/{org}/migrations", + "GET /orgs/{org}/migrations/{migration_id}/repositories", + "GET /orgs/{org}/outside_collaborators", + "GET /orgs/{org}/packages", + "GET /orgs/{org}/packages/{package_type}/{package_name}/versions", + "GET /orgs/{org}/projects", + "GET /orgs/{org}/public_members", + "GET /orgs/{org}/repos", + "GET /orgs/{org}/rulesets", + "GET /orgs/{org}/secret-scanning/alerts", + "GET /orgs/{org}/teams", + "GET /orgs/{org}/teams/{team_slug}/discussions", + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments", + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions", + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions", + "GET /orgs/{org}/teams/{team_slug}/invitations", + "GET /orgs/{org}/teams/{team_slug}/members", + "GET /orgs/{org}/teams/{team_slug}/projects", + "GET /orgs/{org}/teams/{team_slug}/repos", + "GET /orgs/{org}/teams/{team_slug}/teams", + "GET /projects/columns/{column_id}/cards", + "GET /projects/{project_id}/collaborators", + "GET /projects/{project_id}/columns", + "GET /repos/{org}/{repo}/actions/required_workflows", + "GET /repos/{owner}/{repo}/actions/artifacts", + "GET /repos/{owner}/{repo}/actions/caches", + "GET /repos/{owner}/{repo}/actions/organization-secrets", + "GET /repos/{owner}/{repo}/actions/organization-variables", + "GET /repos/{owner}/{repo}/actions/required_workflows/{required_workflow_id_for_repo}/runs", + "GET /repos/{owner}/{repo}/actions/runners", + "GET /repos/{owner}/{repo}/actions/runs", + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts", + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs", + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs", + "GET /repos/{owner}/{repo}/actions/secrets", + "GET /repos/{owner}/{repo}/actions/variables", + "GET /repos/{owner}/{repo}/actions/workflows", + "GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs", + "GET /repos/{owner}/{repo}/assignees", + "GET /repos/{owner}/{repo}/branches", + "GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations", + "GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs", + "GET /repos/{owner}/{repo}/code-scanning/alerts", + "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances", + "GET /repos/{owner}/{repo}/code-scanning/analyses", + "GET /repos/{owner}/{repo}/codespaces", + "GET /repos/{owner}/{repo}/codespaces/devcontainers", + "GET /repos/{owner}/{repo}/codespaces/secrets", + "GET /repos/{owner}/{repo}/collaborators", + "GET /repos/{owner}/{repo}/comments", + "GET /repos/{owner}/{repo}/comments/{comment_id}/reactions", + "GET /repos/{owner}/{repo}/commits", + "GET /repos/{owner}/{repo}/commits/{commit_sha}/comments", + "GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls", + "GET /repos/{owner}/{repo}/commits/{ref}/check-runs", + "GET /repos/{owner}/{repo}/commits/{ref}/check-suites", + "GET /repos/{owner}/{repo}/commits/{ref}/status", + "GET /repos/{owner}/{repo}/commits/{ref}/statuses", + "GET /repos/{owner}/{repo}/contributors", + "GET /repos/{owner}/{repo}/dependabot/alerts", + "GET /repos/{owner}/{repo}/dependabot/secrets", + "GET /repos/{owner}/{repo}/deployments", + "GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses", + "GET /repos/{owner}/{repo}/environments", + "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies", + "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/apps", + "GET /repos/{owner}/{repo}/events", + "GET /repos/{owner}/{repo}/forks", + "GET /repos/{owner}/{repo}/hooks", + "GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries", + "GET /repos/{owner}/{repo}/invitations", + "GET /repos/{owner}/{repo}/issues", + "GET /repos/{owner}/{repo}/issues/comments", + "GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions", + "GET /repos/{owner}/{repo}/issues/events", + "GET /repos/{owner}/{repo}/issues/{issue_number}/comments", + "GET /repos/{owner}/{repo}/issues/{issue_number}/events", + "GET /repos/{owner}/{repo}/issues/{issue_number}/labels", + "GET /repos/{owner}/{repo}/issues/{issue_number}/reactions", + "GET /repos/{owner}/{repo}/issues/{issue_number}/timeline", + "GET /repos/{owner}/{repo}/keys", + "GET /repos/{owner}/{repo}/labels", + "GET /repos/{owner}/{repo}/milestones", + "GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels", + "GET /repos/{owner}/{repo}/notifications", + "GET /repos/{owner}/{repo}/pages/builds", + "GET /repos/{owner}/{repo}/projects", + "GET /repos/{owner}/{repo}/pulls", + "GET /repos/{owner}/{repo}/pulls/comments", + "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions", + "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments", + "GET /repos/{owner}/{repo}/pulls/{pull_number}/commits", + "GET /repos/{owner}/{repo}/pulls/{pull_number}/files", + "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews", + "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments", + "GET /repos/{owner}/{repo}/releases", + "GET /repos/{owner}/{repo}/releases/{release_id}/assets", + "GET /repos/{owner}/{repo}/releases/{release_id}/reactions", + "GET /repos/{owner}/{repo}/rules/branches/{branch}", + "GET /repos/{owner}/{repo}/rulesets", + "GET /repos/{owner}/{repo}/secret-scanning/alerts", + "GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations", + "GET /repos/{owner}/{repo}/security-advisories", + "GET /repos/{owner}/{repo}/stargazers", + "GET /repos/{owner}/{repo}/subscribers", + "GET /repos/{owner}/{repo}/tags", + "GET /repos/{owner}/{repo}/teams", + "GET /repos/{owner}/{repo}/topics", + "GET /repositories", + "GET /repositories/{repository_id}/environments/{environment_name}/secrets", + "GET /repositories/{repository_id}/environments/{environment_name}/variables", + "GET /search/code", + "GET /search/commits", + "GET /search/issues", + "GET /search/labels", + "GET /search/repositories", + "GET /search/topics", + "GET /search/users", + "GET /teams/{team_id}/discussions", + "GET /teams/{team_id}/discussions/{discussion_number}/comments", + "GET /teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions", + "GET /teams/{team_id}/discussions/{discussion_number}/reactions", + "GET /teams/{team_id}/invitations", + "GET /teams/{team_id}/members", + "GET /teams/{team_id}/projects", + "GET /teams/{team_id}/repos", + "GET /teams/{team_id}/teams", + "GET /user/blocks", + "GET /user/codespaces", + "GET /user/codespaces/secrets", + "GET /user/emails", + "GET /user/followers", + "GET /user/following", + "GET /user/gpg_keys", + "GET /user/installations", + "GET /user/installations/{installation_id}/repositories", + "GET /user/issues", + "GET /user/keys", + "GET /user/marketplace_purchases", + "GET /user/marketplace_purchases/stubbed", + "GET /user/memberships/orgs", + "GET /user/migrations", + "GET /user/migrations/{migration_id}/repositories", + "GET /user/orgs", + "GET /user/packages", + "GET /user/packages/{package_type}/{package_name}/versions", + "GET /user/public_emails", + "GET /user/repos", + "GET /user/repository_invitations", + "GET /user/social_accounts", + "GET /user/ssh_signing_keys", + "GET /user/starred", + "GET /user/subscriptions", + "GET /user/teams", + "GET /users", + "GET /users/{username}/events", + "GET /users/{username}/events/orgs/{org}", + "GET /users/{username}/events/public", + "GET /users/{username}/followers", + "GET /users/{username}/following", + "GET /users/{username}/gists", + "GET /users/{username}/gpg_keys", + "GET /users/{username}/keys", + "GET /users/{username}/orgs", + "GET /users/{username}/packages", + "GET /users/{username}/projects", + "GET /users/{username}/received_events", + "GET /users/{username}/received_events/public", + "GET /users/{username}/repos", + "GET /users/{username}/social_accounts", + "GET /users/{username}/ssh_signing_keys", + "GET /users/{username}/starred", + "GET /users/{username}/subscriptions" +]; +// pkg/dist-src/paginating-endpoints.js function isPaginatingEndpoint(arg) { if (typeof arg === "string") { return paginatingEndpoints.includes(arg); @@ -6034,10 +6435,7 @@ function isPaginatingEndpoint(arg) { } } -/** - * @param octokit Octokit instance - * @param options Options passed to Octokit constructor - */ +// pkg/dist-src/index.js function paginateRest(octokit) { return { paginate: Object.assign(paginate.bind(null, octokit), { @@ -6046,178 +6444,416 @@ function paginateRest(octokit) { }; } paginateRest.VERSION = VERSION; - -exports.composePaginateRest = composePaginateRest; -exports.isPaginatingEndpoint = isPaginatingEndpoint; -exports.paginateRest = paginateRest; -exports.paginatingEndpoints = paginatingEndpoints; -//# sourceMappingURL=index.js.map +// Annotate the CommonJS export names for ESM import in node: +0 && (0); /***/ }), /***/ 4923: -/***/ ((__unused_webpack_module, exports) => { +/***/ ((module) => { "use strict"; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// pkg/dist-src/index.js +var dist_src_exports = {}; +__export(dist_src_exports, { + legacyRestEndpointMethods: () => legacyRestEndpointMethods, + restEndpointMethods: () => restEndpointMethods +}); +module.exports = __toCommonJS(dist_src_exports); -Object.defineProperty(exports, "__esModule", ({ value: true })); +// pkg/dist-src/version.js +var VERSION = "7.2.3"; -const Endpoints = { +// pkg/dist-src/generated/endpoints.js +var Endpoints = { actions: { - addCustomLabelsToSelfHostedRunnerForOrg: ["POST /orgs/{org}/actions/runners/{runner_id}/labels"], - addCustomLabelsToSelfHostedRunnerForRepo: ["POST /repos/{owner}/{repo}/actions/runners/{runner_id}/labels"], - addSelectedRepoToOrgSecret: ["PUT /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}"], - addSelectedRepoToOrgVariable: ["PUT /orgs/{org}/actions/variables/{name}/repositories/{repository_id}"], - addSelectedRepoToRequiredWorkflow: ["PUT /orgs/{org}/actions/required_workflows/{required_workflow_id}/repositories/{repository_id}"], - approveWorkflowRun: ["POST /repos/{owner}/{repo}/actions/runs/{run_id}/approve"], - cancelWorkflowRun: ["POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel"], - createEnvironmentVariable: ["POST /repositories/{repository_id}/environments/{environment_name}/variables"], - createOrUpdateEnvironmentSecret: ["PUT /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}"], + addCustomLabelsToSelfHostedRunnerForOrg: [ + "POST /orgs/{org}/actions/runners/{runner_id}/labels" + ], + addCustomLabelsToSelfHostedRunnerForRepo: [ + "POST /repos/{owner}/{repo}/actions/runners/{runner_id}/labels" + ], + addSelectedRepoToOrgSecret: [ + "PUT /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}" + ], + addSelectedRepoToOrgVariable: [ + "PUT /orgs/{org}/actions/variables/{name}/repositories/{repository_id}" + ], + addSelectedRepoToRequiredWorkflow: [ + "PUT /orgs/{org}/actions/required_workflows/{required_workflow_id}/repositories/{repository_id}" + ], + approveWorkflowRun: [ + "POST /repos/{owner}/{repo}/actions/runs/{run_id}/approve" + ], + cancelWorkflowRun: [ + "POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel" + ], + createEnvironmentVariable: [ + "POST /repositories/{repository_id}/environments/{environment_name}/variables" + ], + createOrUpdateEnvironmentSecret: [ + "PUT /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}" + ], createOrUpdateOrgSecret: ["PUT /orgs/{org}/actions/secrets/{secret_name}"], - createOrUpdateRepoSecret: ["PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}"], + createOrUpdateRepoSecret: [ + "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}" + ], createOrgVariable: ["POST /orgs/{org}/actions/variables"], - createRegistrationTokenForOrg: ["POST /orgs/{org}/actions/runners/registration-token"], - createRegistrationTokenForRepo: ["POST /repos/{owner}/{repo}/actions/runners/registration-token"], + createRegistrationTokenForOrg: [ + "POST /orgs/{org}/actions/runners/registration-token" + ], + createRegistrationTokenForRepo: [ + "POST /repos/{owner}/{repo}/actions/runners/registration-token" + ], createRemoveTokenForOrg: ["POST /orgs/{org}/actions/runners/remove-token"], - createRemoveTokenForRepo: ["POST /repos/{owner}/{repo}/actions/runners/remove-token"], + createRemoveTokenForRepo: [ + "POST /repos/{owner}/{repo}/actions/runners/remove-token" + ], createRepoVariable: ["POST /repos/{owner}/{repo}/actions/variables"], createRequiredWorkflow: ["POST /orgs/{org}/actions/required_workflows"], - createWorkflowDispatch: ["POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches"], - deleteActionsCacheById: ["DELETE /repos/{owner}/{repo}/actions/caches/{cache_id}"], - deleteActionsCacheByKey: ["DELETE /repos/{owner}/{repo}/actions/caches{?key,ref}"], - deleteArtifact: ["DELETE /repos/{owner}/{repo}/actions/artifacts/{artifact_id}"], - deleteEnvironmentSecret: ["DELETE /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}"], - deleteEnvironmentVariable: ["DELETE /repositories/{repository_id}/environments/{environment_name}/variables/{name}"], + createWorkflowDispatch: [ + "POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches" + ], + deleteActionsCacheById: [ + "DELETE /repos/{owner}/{repo}/actions/caches/{cache_id}" + ], + deleteActionsCacheByKey: [ + "DELETE /repos/{owner}/{repo}/actions/caches{?key,ref}" + ], + deleteArtifact: [ + "DELETE /repos/{owner}/{repo}/actions/artifacts/{artifact_id}" + ], + deleteEnvironmentSecret: [ + "DELETE /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}" + ], + deleteEnvironmentVariable: [ + "DELETE /repositories/{repository_id}/environments/{environment_name}/variables/{name}" + ], deleteOrgSecret: ["DELETE /orgs/{org}/actions/secrets/{secret_name}"], deleteOrgVariable: ["DELETE /orgs/{org}/actions/variables/{name}"], - deleteRepoSecret: ["DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}"], - deleteRepoVariable: ["DELETE /repos/{owner}/{repo}/actions/variables/{name}"], - deleteRequiredWorkflow: ["DELETE /orgs/{org}/actions/required_workflows/{required_workflow_id}"], - deleteSelfHostedRunnerFromOrg: ["DELETE /orgs/{org}/actions/runners/{runner_id}"], - deleteSelfHostedRunnerFromRepo: ["DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}"], + deleteRepoSecret: [ + "DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}" + ], + deleteRepoVariable: [ + "DELETE /repos/{owner}/{repo}/actions/variables/{name}" + ], + deleteRequiredWorkflow: [ + "DELETE /orgs/{org}/actions/required_workflows/{required_workflow_id}" + ], + deleteSelfHostedRunnerFromOrg: [ + "DELETE /orgs/{org}/actions/runners/{runner_id}" + ], + deleteSelfHostedRunnerFromRepo: [ + "DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}" + ], deleteWorkflowRun: ["DELETE /repos/{owner}/{repo}/actions/runs/{run_id}"], - deleteWorkflowRunLogs: ["DELETE /repos/{owner}/{repo}/actions/runs/{run_id}/logs"], - disableSelectedRepositoryGithubActionsOrganization: ["DELETE /orgs/{org}/actions/permissions/repositories/{repository_id}"], - disableWorkflow: ["PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/disable"], - downloadArtifact: ["GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/{archive_format}"], - downloadJobLogsForWorkflowRun: ["GET /repos/{owner}/{repo}/actions/jobs/{job_id}/logs"], - downloadWorkflowRunAttemptLogs: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/logs"], - downloadWorkflowRunLogs: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/logs"], - enableSelectedRepositoryGithubActionsOrganization: ["PUT /orgs/{org}/actions/permissions/repositories/{repository_id}"], - enableWorkflow: ["PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/enable"], + deleteWorkflowRunLogs: [ + "DELETE /repos/{owner}/{repo}/actions/runs/{run_id}/logs" + ], + disableSelectedRepositoryGithubActionsOrganization: [ + "DELETE /orgs/{org}/actions/permissions/repositories/{repository_id}" + ], + disableWorkflow: [ + "PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/disable" + ], + downloadArtifact: [ + "GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/{archive_format}" + ], + downloadJobLogsForWorkflowRun: [ + "GET /repos/{owner}/{repo}/actions/jobs/{job_id}/logs" + ], + downloadWorkflowRunAttemptLogs: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/logs" + ], + downloadWorkflowRunLogs: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/logs" + ], + enableSelectedRepositoryGithubActionsOrganization: [ + "PUT /orgs/{org}/actions/permissions/repositories/{repository_id}" + ], + enableWorkflow: [ + "PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/enable" + ], + generateRunnerJitconfigForOrg: [ + "POST /orgs/{org}/actions/runners/generate-jitconfig" + ], + generateRunnerJitconfigForRepo: [ + "POST /repos/{owner}/{repo}/actions/runners/generate-jitconfig" + ], getActionsCacheList: ["GET /repos/{owner}/{repo}/actions/caches"], getActionsCacheUsage: ["GET /repos/{owner}/{repo}/actions/cache/usage"], - getActionsCacheUsageByRepoForOrg: ["GET /orgs/{org}/actions/cache/usage-by-repository"], + getActionsCacheUsageByRepoForOrg: [ + "GET /orgs/{org}/actions/cache/usage-by-repository" + ], getActionsCacheUsageForOrg: ["GET /orgs/{org}/actions/cache/usage"], - getAllowedActionsOrganization: ["GET /orgs/{org}/actions/permissions/selected-actions"], - getAllowedActionsRepository: ["GET /repos/{owner}/{repo}/actions/permissions/selected-actions"], + getAllowedActionsOrganization: [ + "GET /orgs/{org}/actions/permissions/selected-actions" + ], + getAllowedActionsRepository: [ + "GET /repos/{owner}/{repo}/actions/permissions/selected-actions" + ], getArtifact: ["GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}"], - getEnvironmentPublicKey: ["GET /repositories/{repository_id}/environments/{environment_name}/secrets/public-key"], - getEnvironmentSecret: ["GET /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}"], - getEnvironmentVariable: ["GET /repositories/{repository_id}/environments/{environment_name}/variables/{name}"], - getGithubActionsDefaultWorkflowPermissionsOrganization: ["GET /orgs/{org}/actions/permissions/workflow"], - getGithubActionsDefaultWorkflowPermissionsRepository: ["GET /repos/{owner}/{repo}/actions/permissions/workflow"], - getGithubActionsPermissionsOrganization: ["GET /orgs/{org}/actions/permissions"], - getGithubActionsPermissionsRepository: ["GET /repos/{owner}/{repo}/actions/permissions"], + getEnvironmentPublicKey: [ + "GET /repositories/{repository_id}/environments/{environment_name}/secrets/public-key" + ], + getEnvironmentSecret: [ + "GET /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}" + ], + getEnvironmentVariable: [ + "GET /repositories/{repository_id}/environments/{environment_name}/variables/{name}" + ], + getGithubActionsDefaultWorkflowPermissionsOrganization: [ + "GET /orgs/{org}/actions/permissions/workflow" + ], + getGithubActionsDefaultWorkflowPermissionsRepository: [ + "GET /repos/{owner}/{repo}/actions/permissions/workflow" + ], + getGithubActionsPermissionsOrganization: [ + "GET /orgs/{org}/actions/permissions" + ], + getGithubActionsPermissionsRepository: [ + "GET /repos/{owner}/{repo}/actions/permissions" + ], getJobForWorkflowRun: ["GET /repos/{owner}/{repo}/actions/jobs/{job_id}"], getOrgPublicKey: ["GET /orgs/{org}/actions/secrets/public-key"], getOrgSecret: ["GET /orgs/{org}/actions/secrets/{secret_name}"], getOrgVariable: ["GET /orgs/{org}/actions/variables/{name}"], - getPendingDeploymentsForRun: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments"], - getRepoPermissions: ["GET /repos/{owner}/{repo}/actions/permissions", {}, { - renamed: ["actions", "getGithubActionsPermissionsRepository"] - }], + getPendingDeploymentsForRun: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments" + ], + getRepoPermissions: [ + "GET /repos/{owner}/{repo}/actions/permissions", + {}, + { renamed: ["actions", "getGithubActionsPermissionsRepository"] } + ], getRepoPublicKey: ["GET /repos/{owner}/{repo}/actions/secrets/public-key"], - getRepoRequiredWorkflow: ["GET /repos/{org}/{repo}/actions/required_workflows/{required_workflow_id_for_repo}"], - getRepoRequiredWorkflowUsage: ["GET /repos/{org}/{repo}/actions/required_workflows/{required_workflow_id_for_repo}/timing"], + getRepoRequiredWorkflow: [ + "GET /repos/{org}/{repo}/actions/required_workflows/{required_workflow_id_for_repo}" + ], + getRepoRequiredWorkflowUsage: [ + "GET /repos/{org}/{repo}/actions/required_workflows/{required_workflow_id_for_repo}/timing" + ], getRepoSecret: ["GET /repos/{owner}/{repo}/actions/secrets/{secret_name}"], getRepoVariable: ["GET /repos/{owner}/{repo}/actions/variables/{name}"], - getRequiredWorkflow: ["GET /orgs/{org}/actions/required_workflows/{required_workflow_id}"], - getReviewsForRun: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/approvals"], + getRequiredWorkflow: [ + "GET /orgs/{org}/actions/required_workflows/{required_workflow_id}" + ], + getReviewsForRun: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/approvals" + ], getSelfHostedRunnerForOrg: ["GET /orgs/{org}/actions/runners/{runner_id}"], - getSelfHostedRunnerForRepo: ["GET /repos/{owner}/{repo}/actions/runners/{runner_id}"], + getSelfHostedRunnerForRepo: [ + "GET /repos/{owner}/{repo}/actions/runners/{runner_id}" + ], getWorkflow: ["GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}"], - getWorkflowAccessToRepository: ["GET /repos/{owner}/{repo}/actions/permissions/access"], + getWorkflowAccessToRepository: [ + "GET /repos/{owner}/{repo}/actions/permissions/access" + ], getWorkflowRun: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}"], - getWorkflowRunAttempt: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}"], - getWorkflowRunUsage: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/timing"], - getWorkflowUsage: ["GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/timing"], + getWorkflowRunAttempt: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}" + ], + getWorkflowRunUsage: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/timing" + ], + getWorkflowUsage: [ + "GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/timing" + ], listArtifactsForRepo: ["GET /repos/{owner}/{repo}/actions/artifacts"], - listEnvironmentSecrets: ["GET /repositories/{repository_id}/environments/{environment_name}/secrets"], - listEnvironmentVariables: ["GET /repositories/{repository_id}/environments/{environment_name}/variables"], - listJobsForWorkflowRun: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs"], - listJobsForWorkflowRunAttempt: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs"], - listLabelsForSelfHostedRunnerForOrg: ["GET /orgs/{org}/actions/runners/{runner_id}/labels"], - listLabelsForSelfHostedRunnerForRepo: ["GET /repos/{owner}/{repo}/actions/runners/{runner_id}/labels"], + listEnvironmentSecrets: [ + "GET /repositories/{repository_id}/environments/{environment_name}/secrets" + ], + listEnvironmentVariables: [ + "GET /repositories/{repository_id}/environments/{environment_name}/variables" + ], + listJobsForWorkflowRun: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs" + ], + listJobsForWorkflowRunAttempt: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs" + ], + listLabelsForSelfHostedRunnerForOrg: [ + "GET /orgs/{org}/actions/runners/{runner_id}/labels" + ], + listLabelsForSelfHostedRunnerForRepo: [ + "GET /repos/{owner}/{repo}/actions/runners/{runner_id}/labels" + ], listOrgSecrets: ["GET /orgs/{org}/actions/secrets"], listOrgVariables: ["GET /orgs/{org}/actions/variables"], - listRepoRequiredWorkflows: ["GET /repos/{org}/{repo}/actions/required_workflows"], + listRepoOrganizationSecrets: [ + "GET /repos/{owner}/{repo}/actions/organization-secrets" + ], + listRepoOrganizationVariables: [ + "GET /repos/{owner}/{repo}/actions/organization-variables" + ], + listRepoRequiredWorkflows: [ + "GET /repos/{org}/{repo}/actions/required_workflows" + ], listRepoSecrets: ["GET /repos/{owner}/{repo}/actions/secrets"], listRepoVariables: ["GET /repos/{owner}/{repo}/actions/variables"], listRepoWorkflows: ["GET /repos/{owner}/{repo}/actions/workflows"], - listRequiredWorkflowRuns: ["GET /repos/{owner}/{repo}/actions/required_workflows/{required_workflow_id_for_repo}/runs"], + listRequiredWorkflowRuns: [ + "GET /repos/{owner}/{repo}/actions/required_workflows/{required_workflow_id_for_repo}/runs" + ], listRequiredWorkflows: ["GET /orgs/{org}/actions/required_workflows"], listRunnerApplicationsForOrg: ["GET /orgs/{org}/actions/runners/downloads"], - listRunnerApplicationsForRepo: ["GET /repos/{owner}/{repo}/actions/runners/downloads"], - listSelectedReposForOrgSecret: ["GET /orgs/{org}/actions/secrets/{secret_name}/repositories"], - listSelectedReposForOrgVariable: ["GET /orgs/{org}/actions/variables/{name}/repositories"], - listSelectedRepositoriesEnabledGithubActionsOrganization: ["GET /orgs/{org}/actions/permissions/repositories"], - listSelectedRepositoriesRequiredWorkflow: ["GET /orgs/{org}/actions/required_workflows/{required_workflow_id}/repositories"], + listRunnerApplicationsForRepo: [ + "GET /repos/{owner}/{repo}/actions/runners/downloads" + ], + listSelectedReposForOrgSecret: [ + "GET /orgs/{org}/actions/secrets/{secret_name}/repositories" + ], + listSelectedReposForOrgVariable: [ + "GET /orgs/{org}/actions/variables/{name}/repositories" + ], + listSelectedRepositoriesEnabledGithubActionsOrganization: [ + "GET /orgs/{org}/actions/permissions/repositories" + ], + listSelectedRepositoriesRequiredWorkflow: [ + "GET /orgs/{org}/actions/required_workflows/{required_workflow_id}/repositories" + ], listSelfHostedRunnersForOrg: ["GET /orgs/{org}/actions/runners"], listSelfHostedRunnersForRepo: ["GET /repos/{owner}/{repo}/actions/runners"], - listWorkflowRunArtifacts: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts"], - listWorkflowRuns: ["GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs"], + listWorkflowRunArtifacts: [ + "GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts" + ], + listWorkflowRuns: [ + "GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs" + ], listWorkflowRunsForRepo: ["GET /repos/{owner}/{repo}/actions/runs"], - reRunJobForWorkflowRun: ["POST /repos/{owner}/{repo}/actions/jobs/{job_id}/rerun"], + reRunJobForWorkflowRun: [ + "POST /repos/{owner}/{repo}/actions/jobs/{job_id}/rerun" + ], reRunWorkflow: ["POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun"], - reRunWorkflowFailedJobs: ["POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun-failed-jobs"], - removeAllCustomLabelsFromSelfHostedRunnerForOrg: ["DELETE /orgs/{org}/actions/runners/{runner_id}/labels"], - removeAllCustomLabelsFromSelfHostedRunnerForRepo: ["DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}/labels"], - removeCustomLabelFromSelfHostedRunnerForOrg: ["DELETE /orgs/{org}/actions/runners/{runner_id}/labels/{name}"], - removeCustomLabelFromSelfHostedRunnerForRepo: ["DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}/labels/{name}"], - removeSelectedRepoFromOrgSecret: ["DELETE /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}"], - removeSelectedRepoFromOrgVariable: ["DELETE /orgs/{org}/actions/variables/{name}/repositories/{repository_id}"], - removeSelectedRepoFromRequiredWorkflow: ["DELETE /orgs/{org}/actions/required_workflows/{required_workflow_id}/repositories/{repository_id}"], - reviewPendingDeploymentsForRun: ["POST /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments"], - setAllowedActionsOrganization: ["PUT /orgs/{org}/actions/permissions/selected-actions"], - setAllowedActionsRepository: ["PUT /repos/{owner}/{repo}/actions/permissions/selected-actions"], - setCustomLabelsForSelfHostedRunnerForOrg: ["PUT /orgs/{org}/actions/runners/{runner_id}/labels"], - setCustomLabelsForSelfHostedRunnerForRepo: ["PUT /repos/{owner}/{repo}/actions/runners/{runner_id}/labels"], - setGithubActionsDefaultWorkflowPermissionsOrganization: ["PUT /orgs/{org}/actions/permissions/workflow"], - setGithubActionsDefaultWorkflowPermissionsRepository: ["PUT /repos/{owner}/{repo}/actions/permissions/workflow"], - setGithubActionsPermissionsOrganization: ["PUT /orgs/{org}/actions/permissions"], - setGithubActionsPermissionsRepository: ["PUT /repos/{owner}/{repo}/actions/permissions"], - setSelectedReposForOrgSecret: ["PUT /orgs/{org}/actions/secrets/{secret_name}/repositories"], - setSelectedReposForOrgVariable: ["PUT /orgs/{org}/actions/variables/{name}/repositories"], - setSelectedReposToRequiredWorkflow: ["PUT /orgs/{org}/actions/required_workflows/{required_workflow_id}/repositories"], - setSelectedRepositoriesEnabledGithubActionsOrganization: ["PUT /orgs/{org}/actions/permissions/repositories"], - setWorkflowAccessToRepository: ["PUT /repos/{owner}/{repo}/actions/permissions/access"], - updateEnvironmentVariable: ["PATCH /repositories/{repository_id}/environments/{environment_name}/variables/{name}"], + reRunWorkflowFailedJobs: [ + "POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun-failed-jobs" + ], + removeAllCustomLabelsFromSelfHostedRunnerForOrg: [ + "DELETE /orgs/{org}/actions/runners/{runner_id}/labels" + ], + removeAllCustomLabelsFromSelfHostedRunnerForRepo: [ + "DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}/labels" + ], + removeCustomLabelFromSelfHostedRunnerForOrg: [ + "DELETE /orgs/{org}/actions/runners/{runner_id}/labels/{name}" + ], + removeCustomLabelFromSelfHostedRunnerForRepo: [ + "DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}/labels/{name}" + ], + removeSelectedRepoFromOrgSecret: [ + "DELETE /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}" + ], + removeSelectedRepoFromOrgVariable: [ + "DELETE /orgs/{org}/actions/variables/{name}/repositories/{repository_id}" + ], + removeSelectedRepoFromRequiredWorkflow: [ + "DELETE /orgs/{org}/actions/required_workflows/{required_workflow_id}/repositories/{repository_id}" + ], + reviewCustomGatesForRun: [ + "POST /repos/{owner}/{repo}/actions/runs/{run_id}/deployment_protection_rule" + ], + reviewPendingDeploymentsForRun: [ + "POST /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments" + ], + setAllowedActionsOrganization: [ + "PUT /orgs/{org}/actions/permissions/selected-actions" + ], + setAllowedActionsRepository: [ + "PUT /repos/{owner}/{repo}/actions/permissions/selected-actions" + ], + setCustomLabelsForSelfHostedRunnerForOrg: [ + "PUT /orgs/{org}/actions/runners/{runner_id}/labels" + ], + setCustomLabelsForSelfHostedRunnerForRepo: [ + "PUT /repos/{owner}/{repo}/actions/runners/{runner_id}/labels" + ], + setGithubActionsDefaultWorkflowPermissionsOrganization: [ + "PUT /orgs/{org}/actions/permissions/workflow" + ], + setGithubActionsDefaultWorkflowPermissionsRepository: [ + "PUT /repos/{owner}/{repo}/actions/permissions/workflow" + ], + setGithubActionsPermissionsOrganization: [ + "PUT /orgs/{org}/actions/permissions" + ], + setGithubActionsPermissionsRepository: [ + "PUT /repos/{owner}/{repo}/actions/permissions" + ], + setSelectedReposForOrgSecret: [ + "PUT /orgs/{org}/actions/secrets/{secret_name}/repositories" + ], + setSelectedReposForOrgVariable: [ + "PUT /orgs/{org}/actions/variables/{name}/repositories" + ], + setSelectedReposToRequiredWorkflow: [ + "PUT /orgs/{org}/actions/required_workflows/{required_workflow_id}/repositories" + ], + setSelectedRepositoriesEnabledGithubActionsOrganization: [ + "PUT /orgs/{org}/actions/permissions/repositories" + ], + setWorkflowAccessToRepository: [ + "PUT /repos/{owner}/{repo}/actions/permissions/access" + ], + updateEnvironmentVariable: [ + "PATCH /repositories/{repository_id}/environments/{environment_name}/variables/{name}" + ], updateOrgVariable: ["PATCH /orgs/{org}/actions/variables/{name}"], - updateRepoVariable: ["PATCH /repos/{owner}/{repo}/actions/variables/{name}"], - updateRequiredWorkflow: ["PATCH /orgs/{org}/actions/required_workflows/{required_workflow_id}"] + updateRepoVariable: [ + "PATCH /repos/{owner}/{repo}/actions/variables/{name}" + ], + updateRequiredWorkflow: [ + "PATCH /orgs/{org}/actions/required_workflows/{required_workflow_id}" + ] }, activity: { checkRepoIsStarredByAuthenticatedUser: ["GET /user/starred/{owner}/{repo}"], deleteRepoSubscription: ["DELETE /repos/{owner}/{repo}/subscription"], - deleteThreadSubscription: ["DELETE /notifications/threads/{thread_id}/subscription"], + deleteThreadSubscription: [ + "DELETE /notifications/threads/{thread_id}/subscription" + ], getFeeds: ["GET /feeds"], getRepoSubscription: ["GET /repos/{owner}/{repo}/subscription"], getThread: ["GET /notifications/threads/{thread_id}"], - getThreadSubscriptionForAuthenticatedUser: ["GET /notifications/threads/{thread_id}/subscription"], + getThreadSubscriptionForAuthenticatedUser: [ + "GET /notifications/threads/{thread_id}/subscription" + ], listEventsForAuthenticatedUser: ["GET /users/{username}/events"], listNotificationsForAuthenticatedUser: ["GET /notifications"], - listOrgEventsForAuthenticatedUser: ["GET /users/{username}/events/orgs/{org}"], + listOrgEventsForAuthenticatedUser: [ + "GET /users/{username}/events/orgs/{org}" + ], listPublicEvents: ["GET /events"], listPublicEventsForRepoNetwork: ["GET /networks/{owner}/{repo}/events"], listPublicEventsForUser: ["GET /users/{username}/events/public"], listPublicOrgEvents: ["GET /orgs/{org}/events"], listReceivedEventsForUser: ["GET /users/{username}/received_events"], - listReceivedPublicEventsForUser: ["GET /users/{username}/received_events/public"], + listReceivedPublicEventsForUser: [ + "GET /users/{username}/received_events/public" + ], listRepoEvents: ["GET /repos/{owner}/{repo}/events"], - listRepoNotificationsForAuthenticatedUser: ["GET /repos/{owner}/{repo}/notifications"], + listRepoNotificationsForAuthenticatedUser: [ + "GET /repos/{owner}/{repo}/notifications" + ], listReposStarredByAuthenticatedUser: ["GET /user/starred"], listReposStarredByUser: ["GET /users/{username}/starred"], listReposWatchedByUser: ["GET /users/{username}/subscriptions"], @@ -6228,18 +6864,26 @@ const Endpoints = { markRepoNotificationsAsRead: ["PUT /repos/{owner}/{repo}/notifications"], markThreadAsRead: ["PATCH /notifications/threads/{thread_id}"], setRepoSubscription: ["PUT /repos/{owner}/{repo}/subscription"], - setThreadSubscription: ["PUT /notifications/threads/{thread_id}/subscription"], + setThreadSubscription: [ + "PUT /notifications/threads/{thread_id}/subscription" + ], starRepoForAuthenticatedUser: ["PUT /user/starred/{owner}/{repo}"], unstarRepoForAuthenticatedUser: ["DELETE /user/starred/{owner}/{repo}"] }, apps: { - addRepoToInstallation: ["PUT /user/installations/{installation_id}/repositories/{repository_id}", {}, { - renamed: ["apps", "addRepoToInstallationForAuthenticatedUser"] - }], - addRepoToInstallationForAuthenticatedUser: ["PUT /user/installations/{installation_id}/repositories/{repository_id}"], + addRepoToInstallation: [ + "PUT /user/installations/{installation_id}/repositories/{repository_id}", + {}, + { renamed: ["apps", "addRepoToInstallationForAuthenticatedUser"] } + ], + addRepoToInstallationForAuthenticatedUser: [ + "PUT /user/installations/{installation_id}/repositories/{repository_id}" + ], checkToken: ["POST /applications/{client_id}/token"], createFromManifest: ["POST /app-manifests/{code}/conversions"], - createInstallationAccessToken: ["POST /app/installations/{installation_id}/access_tokens"], + createInstallationAccessToken: [ + "POST /app/installations/{installation_id}/access_tokens" + ], deleteAuthorization: ["DELETE /applications/{client_id}/grant"], deleteInstallation: ["DELETE /app/installations/{installation_id}"], deleteToken: ["DELETE /applications/{client_id}/token"], @@ -6248,75 +6892,132 @@ const Endpoints = { getInstallation: ["GET /app/installations/{installation_id}"], getOrgInstallation: ["GET /orgs/{org}/installation"], getRepoInstallation: ["GET /repos/{owner}/{repo}/installation"], - getSubscriptionPlanForAccount: ["GET /marketplace_listing/accounts/{account_id}"], - getSubscriptionPlanForAccountStubbed: ["GET /marketplace_listing/stubbed/accounts/{account_id}"], + getSubscriptionPlanForAccount: [ + "GET /marketplace_listing/accounts/{account_id}" + ], + getSubscriptionPlanForAccountStubbed: [ + "GET /marketplace_listing/stubbed/accounts/{account_id}" + ], getUserInstallation: ["GET /users/{username}/installation"], getWebhookConfigForApp: ["GET /app/hook/config"], getWebhookDelivery: ["GET /app/hook/deliveries/{delivery_id}"], listAccountsForPlan: ["GET /marketplace_listing/plans/{plan_id}/accounts"], - listAccountsForPlanStubbed: ["GET /marketplace_listing/stubbed/plans/{plan_id}/accounts"], - listInstallationReposForAuthenticatedUser: ["GET /user/installations/{installation_id}/repositories"], + listAccountsForPlanStubbed: [ + "GET /marketplace_listing/stubbed/plans/{plan_id}/accounts" + ], + listInstallationReposForAuthenticatedUser: [ + "GET /user/installations/{installation_id}/repositories" + ], + listInstallationRequestsForAuthenticatedApp: [ + "GET /app/installation-requests" + ], listInstallations: ["GET /app/installations"], listInstallationsForAuthenticatedUser: ["GET /user/installations"], listPlans: ["GET /marketplace_listing/plans"], listPlansStubbed: ["GET /marketplace_listing/stubbed/plans"], listReposAccessibleToInstallation: ["GET /installation/repositories"], listSubscriptionsForAuthenticatedUser: ["GET /user/marketplace_purchases"], - listSubscriptionsForAuthenticatedUserStubbed: ["GET /user/marketplace_purchases/stubbed"], + listSubscriptionsForAuthenticatedUserStubbed: [ + "GET /user/marketplace_purchases/stubbed" + ], listWebhookDeliveries: ["GET /app/hook/deliveries"], - redeliverWebhookDelivery: ["POST /app/hook/deliveries/{delivery_id}/attempts"], - removeRepoFromInstallation: ["DELETE /user/installations/{installation_id}/repositories/{repository_id}", {}, { - renamed: ["apps", "removeRepoFromInstallationForAuthenticatedUser"] - }], - removeRepoFromInstallationForAuthenticatedUser: ["DELETE /user/installations/{installation_id}/repositories/{repository_id}"], + redeliverWebhookDelivery: [ + "POST /app/hook/deliveries/{delivery_id}/attempts" + ], + removeRepoFromInstallation: [ + "DELETE /user/installations/{installation_id}/repositories/{repository_id}", + {}, + { renamed: ["apps", "removeRepoFromInstallationForAuthenticatedUser"] } + ], + removeRepoFromInstallationForAuthenticatedUser: [ + "DELETE /user/installations/{installation_id}/repositories/{repository_id}" + ], resetToken: ["PATCH /applications/{client_id}/token"], revokeInstallationAccessToken: ["DELETE /installation/token"], scopeToken: ["POST /applications/{client_id}/token/scoped"], suspendInstallation: ["PUT /app/installations/{installation_id}/suspended"], - unsuspendInstallation: ["DELETE /app/installations/{installation_id}/suspended"], + unsuspendInstallation: [ + "DELETE /app/installations/{installation_id}/suspended" + ], updateWebhookConfigForApp: ["PATCH /app/hook/config"] }, billing: { getGithubActionsBillingOrg: ["GET /orgs/{org}/settings/billing/actions"], - getGithubActionsBillingUser: ["GET /users/{username}/settings/billing/actions"], + getGithubActionsBillingUser: [ + "GET /users/{username}/settings/billing/actions" + ], getGithubPackagesBillingOrg: ["GET /orgs/{org}/settings/billing/packages"], - getGithubPackagesBillingUser: ["GET /users/{username}/settings/billing/packages"], - getSharedStorageBillingOrg: ["GET /orgs/{org}/settings/billing/shared-storage"], - getSharedStorageBillingUser: ["GET /users/{username}/settings/billing/shared-storage"] + getGithubPackagesBillingUser: [ + "GET /users/{username}/settings/billing/packages" + ], + getSharedStorageBillingOrg: [ + "GET /orgs/{org}/settings/billing/shared-storage" + ], + getSharedStorageBillingUser: [ + "GET /users/{username}/settings/billing/shared-storage" + ] }, checks: { create: ["POST /repos/{owner}/{repo}/check-runs"], createSuite: ["POST /repos/{owner}/{repo}/check-suites"], get: ["GET /repos/{owner}/{repo}/check-runs/{check_run_id}"], getSuite: ["GET /repos/{owner}/{repo}/check-suites/{check_suite_id}"], - listAnnotations: ["GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations"], + listAnnotations: [ + "GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations" + ], listForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/check-runs"], - listForSuite: ["GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs"], + listForSuite: [ + "GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs" + ], listSuitesForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/check-suites"], - rerequestRun: ["POST /repos/{owner}/{repo}/check-runs/{check_run_id}/rerequest"], - rerequestSuite: ["POST /repos/{owner}/{repo}/check-suites/{check_suite_id}/rerequest"], - setSuitesPreferences: ["PATCH /repos/{owner}/{repo}/check-suites/preferences"], + rerequestRun: [ + "POST /repos/{owner}/{repo}/check-runs/{check_run_id}/rerequest" + ], + rerequestSuite: [ + "POST /repos/{owner}/{repo}/check-suites/{check_suite_id}/rerequest" + ], + setSuitesPreferences: [ + "PATCH /repos/{owner}/{repo}/check-suites/preferences" + ], update: ["PATCH /repos/{owner}/{repo}/check-runs/{check_run_id}"] }, codeScanning: { - deleteAnalysis: ["DELETE /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id}{?confirm_delete}"], - getAlert: ["GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}", {}, { - renamedParameters: { - alert_id: "alert_number" - } - }], - getAnalysis: ["GET /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id}"], - getCodeqlDatabase: ["GET /repos/{owner}/{repo}/code-scanning/codeql/databases/{language}"], + deleteAnalysis: [ + "DELETE /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id}{?confirm_delete}" + ], + getAlert: [ + "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}", + {}, + { renamedParameters: { alert_id: "alert_number" } } + ], + getAnalysis: [ + "GET /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id}" + ], + getCodeqlDatabase: [ + "GET /repos/{owner}/{repo}/code-scanning/codeql/databases/{language}" + ], + getDefaultSetup: ["GET /repos/{owner}/{repo}/code-scanning/default-setup"], getSarif: ["GET /repos/{owner}/{repo}/code-scanning/sarifs/{sarif_id}"], - listAlertInstances: ["GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances"], + listAlertInstances: [ + "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances" + ], listAlertsForOrg: ["GET /orgs/{org}/code-scanning/alerts"], listAlertsForRepo: ["GET /repos/{owner}/{repo}/code-scanning/alerts"], - listAlertsInstances: ["GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances", {}, { - renamed: ["codeScanning", "listAlertInstances"] - }], - listCodeqlDatabases: ["GET /repos/{owner}/{repo}/code-scanning/codeql/databases"], + listAlertsInstances: [ + "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances", + {}, + { renamed: ["codeScanning", "listAlertInstances"] } + ], + listCodeqlDatabases: [ + "GET /repos/{owner}/{repo}/code-scanning/codeql/databases" + ], listRecentAnalyses: ["GET /repos/{owner}/{repo}/code-scanning/analyses"], - updateAlert: ["PATCH /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}"], + updateAlert: [ + "PATCH /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}" + ], + updateDefaultSetup: [ + "PATCH /repos/{owner}/{repo}/code-scanning/default-setup" + ], uploadSarif: ["POST /repos/{owner}/{repo}/code-scanning/sarifs"] }, codesOfConduct: { @@ -6324,89 +7025,175 @@ const Endpoints = { getConductCode: ["GET /codes_of_conduct/{key}"] }, codespaces: { - addRepositoryForSecretForAuthenticatedUser: ["PUT /user/codespaces/secrets/{secret_name}/repositories/{repository_id}"], - addSelectedRepoToOrgSecret: ["PUT /orgs/{org}/codespaces/secrets/{secret_name}/repositories/{repository_id}"], - codespaceMachinesForAuthenticatedUser: ["GET /user/codespaces/{codespace_name}/machines"], + addRepositoryForSecretForAuthenticatedUser: [ + "PUT /user/codespaces/secrets/{secret_name}/repositories/{repository_id}" + ], + addSelectedRepoToOrgSecret: [ + "PUT /orgs/{org}/codespaces/secrets/{secret_name}/repositories/{repository_id}" + ], + codespaceMachinesForAuthenticatedUser: [ + "GET /user/codespaces/{codespace_name}/machines" + ], createForAuthenticatedUser: ["POST /user/codespaces"], - createOrUpdateOrgSecret: ["PUT /orgs/{org}/codespaces/secrets/{secret_name}"], - createOrUpdateRepoSecret: ["PUT /repos/{owner}/{repo}/codespaces/secrets/{secret_name}"], - createOrUpdateSecretForAuthenticatedUser: ["PUT /user/codespaces/secrets/{secret_name}"], - createWithPrForAuthenticatedUser: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/codespaces"], - createWithRepoForAuthenticatedUser: ["POST /repos/{owner}/{repo}/codespaces"], + createOrUpdateOrgSecret: [ + "PUT /orgs/{org}/codespaces/secrets/{secret_name}" + ], + createOrUpdateRepoSecret: [ + "PUT /repos/{owner}/{repo}/codespaces/secrets/{secret_name}" + ], + createOrUpdateSecretForAuthenticatedUser: [ + "PUT /user/codespaces/secrets/{secret_name}" + ], + createWithPrForAuthenticatedUser: [ + "POST /repos/{owner}/{repo}/pulls/{pull_number}/codespaces" + ], + createWithRepoForAuthenticatedUser: [ + "POST /repos/{owner}/{repo}/codespaces" + ], + deleteCodespacesBillingUsers: [ + "DELETE /orgs/{org}/codespaces/billing/selected_users" + ], deleteForAuthenticatedUser: ["DELETE /user/codespaces/{codespace_name}"], - deleteFromOrganization: ["DELETE /orgs/{org}/members/{username}/codespaces/{codespace_name}"], + deleteFromOrganization: [ + "DELETE /orgs/{org}/members/{username}/codespaces/{codespace_name}" + ], deleteOrgSecret: ["DELETE /orgs/{org}/codespaces/secrets/{secret_name}"], - deleteRepoSecret: ["DELETE /repos/{owner}/{repo}/codespaces/secrets/{secret_name}"], - deleteSecretForAuthenticatedUser: ["DELETE /user/codespaces/secrets/{secret_name}"], - exportForAuthenticatedUser: ["POST /user/codespaces/{codespace_name}/exports"], - getCodespacesForUserInOrg: ["GET /orgs/{org}/members/{username}/codespaces"], - getExportDetailsForAuthenticatedUser: ["GET /user/codespaces/{codespace_name}/exports/{export_id}"], + deleteRepoSecret: [ + "DELETE /repos/{owner}/{repo}/codespaces/secrets/{secret_name}" + ], + deleteSecretForAuthenticatedUser: [ + "DELETE /user/codespaces/secrets/{secret_name}" + ], + exportForAuthenticatedUser: [ + "POST /user/codespaces/{codespace_name}/exports" + ], + getCodespacesForUserInOrg: [ + "GET /orgs/{org}/members/{username}/codespaces" + ], + getExportDetailsForAuthenticatedUser: [ + "GET /user/codespaces/{codespace_name}/exports/{export_id}" + ], getForAuthenticatedUser: ["GET /user/codespaces/{codespace_name}"], getOrgPublicKey: ["GET /orgs/{org}/codespaces/secrets/public-key"], getOrgSecret: ["GET /orgs/{org}/codespaces/secrets/{secret_name}"], - getPublicKeyForAuthenticatedUser: ["GET /user/codespaces/secrets/public-key"], - getRepoPublicKey: ["GET /repos/{owner}/{repo}/codespaces/secrets/public-key"], - getRepoSecret: ["GET /repos/{owner}/{repo}/codespaces/secrets/{secret_name}"], - getSecretForAuthenticatedUser: ["GET /user/codespaces/secrets/{secret_name}"], - listDevcontainersInRepositoryForAuthenticatedUser: ["GET /repos/{owner}/{repo}/codespaces/devcontainers"], + getPublicKeyForAuthenticatedUser: [ + "GET /user/codespaces/secrets/public-key" + ], + getRepoPublicKey: [ + "GET /repos/{owner}/{repo}/codespaces/secrets/public-key" + ], + getRepoSecret: [ + "GET /repos/{owner}/{repo}/codespaces/secrets/{secret_name}" + ], + getSecretForAuthenticatedUser: [ + "GET /user/codespaces/secrets/{secret_name}" + ], + listDevcontainersInRepositoryForAuthenticatedUser: [ + "GET /repos/{owner}/{repo}/codespaces/devcontainers" + ], listForAuthenticatedUser: ["GET /user/codespaces"], - listInOrganization: ["GET /orgs/{org}/codespaces", {}, { - renamedParameters: { - org_id: "org" - } - }], - listInRepositoryForAuthenticatedUser: ["GET /repos/{owner}/{repo}/codespaces"], + listInOrganization: [ + "GET /orgs/{org}/codespaces", + {}, + { renamedParameters: { org_id: "org" } } + ], + listInRepositoryForAuthenticatedUser: [ + "GET /repos/{owner}/{repo}/codespaces" + ], listOrgSecrets: ["GET /orgs/{org}/codespaces/secrets"], listRepoSecrets: ["GET /repos/{owner}/{repo}/codespaces/secrets"], - listRepositoriesForSecretForAuthenticatedUser: ["GET /user/codespaces/secrets/{secret_name}/repositories"], + listRepositoriesForSecretForAuthenticatedUser: [ + "GET /user/codespaces/secrets/{secret_name}/repositories" + ], listSecretsForAuthenticatedUser: ["GET /user/codespaces/secrets"], - listSelectedReposForOrgSecret: ["GET /orgs/{org}/codespaces/secrets/{secret_name}/repositories"], - preFlightWithRepoForAuthenticatedUser: ["GET /repos/{owner}/{repo}/codespaces/new"], - publishForAuthenticatedUser: ["POST /user/codespaces/{codespace_name}/publish"], - removeRepositoryForSecretForAuthenticatedUser: ["DELETE /user/codespaces/secrets/{secret_name}/repositories/{repository_id}"], - removeSelectedRepoFromOrgSecret: ["DELETE /orgs/{org}/codespaces/secrets/{secret_name}/repositories/{repository_id}"], - repoMachinesForAuthenticatedUser: ["GET /repos/{owner}/{repo}/codespaces/machines"], + listSelectedReposForOrgSecret: [ + "GET /orgs/{org}/codespaces/secrets/{secret_name}/repositories" + ], + preFlightWithRepoForAuthenticatedUser: [ + "GET /repos/{owner}/{repo}/codespaces/new" + ], + publishForAuthenticatedUser: [ + "POST /user/codespaces/{codespace_name}/publish" + ], + removeRepositoryForSecretForAuthenticatedUser: [ + "DELETE /user/codespaces/secrets/{secret_name}/repositories/{repository_id}" + ], + removeSelectedRepoFromOrgSecret: [ + "DELETE /orgs/{org}/codespaces/secrets/{secret_name}/repositories/{repository_id}" + ], + repoMachinesForAuthenticatedUser: [ + "GET /repos/{owner}/{repo}/codespaces/machines" + ], setCodespacesBilling: ["PUT /orgs/{org}/codespaces/billing"], - setRepositoriesForSecretForAuthenticatedUser: ["PUT /user/codespaces/secrets/{secret_name}/repositories"], - setSelectedReposForOrgSecret: ["PUT /orgs/{org}/codespaces/secrets/{secret_name}/repositories"], + setCodespacesBillingUsers: [ + "POST /orgs/{org}/codespaces/billing/selected_users" + ], + setRepositoriesForSecretForAuthenticatedUser: [ + "PUT /user/codespaces/secrets/{secret_name}/repositories" + ], + setSelectedReposForOrgSecret: [ + "PUT /orgs/{org}/codespaces/secrets/{secret_name}/repositories" + ], startForAuthenticatedUser: ["POST /user/codespaces/{codespace_name}/start"], stopForAuthenticatedUser: ["POST /user/codespaces/{codespace_name}/stop"], - stopInOrganization: ["POST /orgs/{org}/members/{username}/codespaces/{codespace_name}/stop"], + stopInOrganization: [ + "POST /orgs/{org}/members/{username}/codespaces/{codespace_name}/stop" + ], updateForAuthenticatedUser: ["PATCH /user/codespaces/{codespace_name}"] }, dependabot: { - addSelectedRepoToOrgSecret: ["PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id}"], - createOrUpdateOrgSecret: ["PUT /orgs/{org}/dependabot/secrets/{secret_name}"], - createOrUpdateRepoSecret: ["PUT /repos/{owner}/{repo}/dependabot/secrets/{secret_name}"], + addSelectedRepoToOrgSecret: [ + "PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id}" + ], + createOrUpdateOrgSecret: [ + "PUT /orgs/{org}/dependabot/secrets/{secret_name}" + ], + createOrUpdateRepoSecret: [ + "PUT /repos/{owner}/{repo}/dependabot/secrets/{secret_name}" + ], deleteOrgSecret: ["DELETE /orgs/{org}/dependabot/secrets/{secret_name}"], - deleteRepoSecret: ["DELETE /repos/{owner}/{repo}/dependabot/secrets/{secret_name}"], + deleteRepoSecret: [ + "DELETE /repos/{owner}/{repo}/dependabot/secrets/{secret_name}" + ], getAlert: ["GET /repos/{owner}/{repo}/dependabot/alerts/{alert_number}"], getOrgPublicKey: ["GET /orgs/{org}/dependabot/secrets/public-key"], getOrgSecret: ["GET /orgs/{org}/dependabot/secrets/{secret_name}"], - getRepoPublicKey: ["GET /repos/{owner}/{repo}/dependabot/secrets/public-key"], - getRepoSecret: ["GET /repos/{owner}/{repo}/dependabot/secrets/{secret_name}"], - listAlertsForEnterprise: ["GET /enterprises/{enterprise}/dependabot/alerts"], + getRepoPublicKey: [ + "GET /repos/{owner}/{repo}/dependabot/secrets/public-key" + ], + getRepoSecret: [ + "GET /repos/{owner}/{repo}/dependabot/secrets/{secret_name}" + ], + listAlertsForEnterprise: [ + "GET /enterprises/{enterprise}/dependabot/alerts" + ], listAlertsForOrg: ["GET /orgs/{org}/dependabot/alerts"], listAlertsForRepo: ["GET /repos/{owner}/{repo}/dependabot/alerts"], listOrgSecrets: ["GET /orgs/{org}/dependabot/secrets"], listRepoSecrets: ["GET /repos/{owner}/{repo}/dependabot/secrets"], - listSelectedReposForOrgSecret: ["GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories"], - removeSelectedRepoFromOrgSecret: ["DELETE /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id}"], - setSelectedReposForOrgSecret: ["PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories"], - updateAlert: ["PATCH /repos/{owner}/{repo}/dependabot/alerts/{alert_number}"] + listSelectedReposForOrgSecret: [ + "GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories" + ], + removeSelectedRepoFromOrgSecret: [ + "DELETE /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id}" + ], + setSelectedReposForOrgSecret: [ + "PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories" + ], + updateAlert: [ + "PATCH /repos/{owner}/{repo}/dependabot/alerts/{alert_number}" + ] }, dependencyGraph: { - createRepositorySnapshot: ["POST /repos/{owner}/{repo}/dependency-graph/snapshots"], - diffRange: ["GET /repos/{owner}/{repo}/dependency-graph/compare/{basehead}"] - }, - emojis: { - get: ["GET /emojis"] - }, - enterpriseAdmin: { - addCustomLabelsToSelfHostedRunnerForEnterprise: ["POST /enterprises/{enterprise}/actions/runners/{runner_id}/labels"], - enableSelectedOrganizationGithubActionsEnterprise: ["PUT /enterprises/{enterprise}/actions/permissions/organizations/{org_id}"], - listLabelsForSelfHostedRunnerForEnterprise: ["GET /enterprises/{enterprise}/actions/runners/{runner_id}/labels"] + createRepositorySnapshot: [ + "POST /repos/{owner}/{repo}/dependency-graph/snapshots" + ], + diffRange: [ + "GET /repos/{owner}/{repo}/dependency-graph/compare/{basehead}" + ], + exportSbom: ["GET /repos/{owner}/{repo}/dependency-graph/sbom"] }, + emojis: { get: ["GET /emojis"] }, gists: { checkIsStarred: ["GET /gists/{gist_id}/star"], create: ["POST /gists"], @@ -6452,34 +7239,52 @@ const Endpoints = { getRestrictionsForAuthenticatedUser: ["GET /user/interaction-limits"], getRestrictionsForOrg: ["GET /orgs/{org}/interaction-limits"], getRestrictionsForRepo: ["GET /repos/{owner}/{repo}/interaction-limits"], - getRestrictionsForYourPublicRepos: ["GET /user/interaction-limits", {}, { - renamed: ["interactions", "getRestrictionsForAuthenticatedUser"] - }], + getRestrictionsForYourPublicRepos: [ + "GET /user/interaction-limits", + {}, + { renamed: ["interactions", "getRestrictionsForAuthenticatedUser"] } + ], removeRestrictionsForAuthenticatedUser: ["DELETE /user/interaction-limits"], removeRestrictionsForOrg: ["DELETE /orgs/{org}/interaction-limits"], - removeRestrictionsForRepo: ["DELETE /repos/{owner}/{repo}/interaction-limits"], - removeRestrictionsForYourPublicRepos: ["DELETE /user/interaction-limits", {}, { - renamed: ["interactions", "removeRestrictionsForAuthenticatedUser"] - }], + removeRestrictionsForRepo: [ + "DELETE /repos/{owner}/{repo}/interaction-limits" + ], + removeRestrictionsForYourPublicRepos: [ + "DELETE /user/interaction-limits", + {}, + { renamed: ["interactions", "removeRestrictionsForAuthenticatedUser"] } + ], setRestrictionsForAuthenticatedUser: ["PUT /user/interaction-limits"], setRestrictionsForOrg: ["PUT /orgs/{org}/interaction-limits"], setRestrictionsForRepo: ["PUT /repos/{owner}/{repo}/interaction-limits"], - setRestrictionsForYourPublicRepos: ["PUT /user/interaction-limits", {}, { - renamed: ["interactions", "setRestrictionsForAuthenticatedUser"] - }] + setRestrictionsForYourPublicRepos: [ + "PUT /user/interaction-limits", + {}, + { renamed: ["interactions", "setRestrictionsForAuthenticatedUser"] } + ] }, issues: { - addAssignees: ["POST /repos/{owner}/{repo}/issues/{issue_number}/assignees"], + addAssignees: [ + "POST /repos/{owner}/{repo}/issues/{issue_number}/assignees" + ], addLabels: ["POST /repos/{owner}/{repo}/issues/{issue_number}/labels"], checkUserCanBeAssigned: ["GET /repos/{owner}/{repo}/assignees/{assignee}"], - checkUserCanBeAssignedToIssue: ["GET /repos/{owner}/{repo}/issues/{issue_number}/assignees/{assignee}"], + checkUserCanBeAssignedToIssue: [ + "GET /repos/{owner}/{repo}/issues/{issue_number}/assignees/{assignee}" + ], create: ["POST /repos/{owner}/{repo}/issues"], - createComment: ["POST /repos/{owner}/{repo}/issues/{issue_number}/comments"], + createComment: [ + "POST /repos/{owner}/{repo}/issues/{issue_number}/comments" + ], createLabel: ["POST /repos/{owner}/{repo}/labels"], createMilestone: ["POST /repos/{owner}/{repo}/milestones"], - deleteComment: ["DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}"], + deleteComment: [ + "DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}" + ], deleteLabel: ["DELETE /repos/{owner}/{repo}/labels/{name}"], - deleteMilestone: ["DELETE /repos/{owner}/{repo}/milestones/{milestone_number}"], + deleteMilestone: [ + "DELETE /repos/{owner}/{repo}/milestones/{milestone_number}" + ], get: ["GET /repos/{owner}/{repo}/issues/{issue_number}"], getComment: ["GET /repos/{owner}/{repo}/issues/comments/{comment_id}"], getEvent: ["GET /repos/{owner}/{repo}/issues/events/{event_id}"], @@ -6491,24 +7296,38 @@ const Endpoints = { listCommentsForRepo: ["GET /repos/{owner}/{repo}/issues/comments"], listEvents: ["GET /repos/{owner}/{repo}/issues/{issue_number}/events"], listEventsForRepo: ["GET /repos/{owner}/{repo}/issues/events"], - listEventsForTimeline: ["GET /repos/{owner}/{repo}/issues/{issue_number}/timeline"], + listEventsForTimeline: [ + "GET /repos/{owner}/{repo}/issues/{issue_number}/timeline" + ], listForAuthenticatedUser: ["GET /user/issues"], listForOrg: ["GET /orgs/{org}/issues"], listForRepo: ["GET /repos/{owner}/{repo}/issues"], - listLabelsForMilestone: ["GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels"], + listLabelsForMilestone: [ + "GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels" + ], listLabelsForRepo: ["GET /repos/{owner}/{repo}/labels"], - listLabelsOnIssue: ["GET /repos/{owner}/{repo}/issues/{issue_number}/labels"], + listLabelsOnIssue: [ + "GET /repos/{owner}/{repo}/issues/{issue_number}/labels" + ], listMilestones: ["GET /repos/{owner}/{repo}/milestones"], lock: ["PUT /repos/{owner}/{repo}/issues/{issue_number}/lock"], - removeAllLabels: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels"], - removeAssignees: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/assignees"], - removeLabel: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/{name}"], + removeAllLabels: [ + "DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels" + ], + removeAssignees: [ + "DELETE /repos/{owner}/{repo}/issues/{issue_number}/assignees" + ], + removeLabel: [ + "DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/{name}" + ], setLabels: ["PUT /repos/{owner}/{repo}/issues/{issue_number}/labels"], unlock: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/lock"], update: ["PATCH /repos/{owner}/{repo}/issues/{issue_number}"], updateComment: ["PATCH /repos/{owner}/{repo}/issues/comments/{comment_id}"], updateLabel: ["PATCH /repos/{owner}/{repo}/labels/{name}"], - updateMilestone: ["PATCH /repos/{owner}/{repo}/milestones/{milestone_number}"] + updateMilestone: [ + "PATCH /repos/{owner}/{repo}/milestones/{milestone_number}" + ] }, licenses: { get: ["GET /licenses/{license}"], @@ -6517,11 +7336,10 @@ const Endpoints = { }, markdown: { render: ["POST /markdown"], - renderRaw: ["POST /markdown/raw", { - headers: { - "content-type": "text/plain; charset=utf-8" - } - }] + renderRaw: [ + "POST /markdown/raw", + { headers: { "content-type": "text/plain; charset=utf-8" } } + ] }, meta: { get: ["GET /meta"], @@ -6532,10 +7350,18 @@ const Endpoints = { }, migrations: { cancelImport: ["DELETE /repos/{owner}/{repo}/import"], - deleteArchiveForAuthenticatedUser: ["DELETE /user/migrations/{migration_id}/archive"], - deleteArchiveForOrg: ["DELETE /orgs/{org}/migrations/{migration_id}/archive"], - downloadArchiveForOrg: ["GET /orgs/{org}/migrations/{migration_id}/archive"], - getArchiveForAuthenticatedUser: ["GET /user/migrations/{migration_id}/archive"], + deleteArchiveForAuthenticatedUser: [ + "DELETE /user/migrations/{migration_id}/archive" + ], + deleteArchiveForOrg: [ + "DELETE /orgs/{org}/migrations/{migration_id}/archive" + ], + downloadArchiveForOrg: [ + "GET /orgs/{org}/migrations/{migration_id}/archive" + ], + getArchiveForAuthenticatedUser: [ + "GET /user/migrations/{migration_id}/archive" + ], getCommitAuthors: ["GET /repos/{owner}/{repo}/import/authors"], getImportStatus: ["GET /repos/{owner}/{repo}/import"], getLargeFiles: ["GET /repos/{owner}/{repo}/import/large_files"], @@ -6543,38 +7369,55 @@ const Endpoints = { getStatusForOrg: ["GET /orgs/{org}/migrations/{migration_id}"], listForAuthenticatedUser: ["GET /user/migrations"], listForOrg: ["GET /orgs/{org}/migrations"], - listReposForAuthenticatedUser: ["GET /user/migrations/{migration_id}/repositories"], + listReposForAuthenticatedUser: [ + "GET /user/migrations/{migration_id}/repositories" + ], listReposForOrg: ["GET /orgs/{org}/migrations/{migration_id}/repositories"], - listReposForUser: ["GET /user/migrations/{migration_id}/repositories", {}, { - renamed: ["migrations", "listReposForAuthenticatedUser"] - }], + listReposForUser: [ + "GET /user/migrations/{migration_id}/repositories", + {}, + { renamed: ["migrations", "listReposForAuthenticatedUser"] } + ], mapCommitAuthor: ["PATCH /repos/{owner}/{repo}/import/authors/{author_id}"], setLfsPreference: ["PATCH /repos/{owner}/{repo}/import/lfs"], startForAuthenticatedUser: ["POST /user/migrations"], startForOrg: ["POST /orgs/{org}/migrations"], startImport: ["PUT /repos/{owner}/{repo}/import"], - unlockRepoForAuthenticatedUser: ["DELETE /user/migrations/{migration_id}/repos/{repo_name}/lock"], - unlockRepoForOrg: ["DELETE /orgs/{org}/migrations/{migration_id}/repos/{repo_name}/lock"], + unlockRepoForAuthenticatedUser: [ + "DELETE /user/migrations/{migration_id}/repos/{repo_name}/lock" + ], + unlockRepoForOrg: [ + "DELETE /orgs/{org}/migrations/{migration_id}/repos/{repo_name}/lock" + ], updateImport: ["PATCH /repos/{owner}/{repo}/import"] }, orgs: { - addSecurityManagerTeam: ["PUT /orgs/{org}/security-managers/teams/{team_slug}"], + addSecurityManagerTeam: [ + "PUT /orgs/{org}/security-managers/teams/{team_slug}" + ], blockUser: ["PUT /orgs/{org}/blocks/{username}"], cancelInvitation: ["DELETE /orgs/{org}/invitations/{invitation_id}"], checkBlockedUser: ["GET /orgs/{org}/blocks/{username}"], checkMembershipForUser: ["GET /orgs/{org}/members/{username}"], checkPublicMembershipForUser: ["GET /orgs/{org}/public_members/{username}"], - convertMemberToOutsideCollaborator: ["PUT /orgs/{org}/outside_collaborators/{username}"], + convertMemberToOutsideCollaborator: [ + "PUT /orgs/{org}/outside_collaborators/{username}" + ], createInvitation: ["POST /orgs/{org}/invitations"], createWebhook: ["POST /orgs/{org}/hooks"], + delete: ["DELETE /orgs/{org}"], deleteWebhook: ["DELETE /orgs/{org}/hooks/{hook_id}"], - enableOrDisableSecurityProductOnAllOrgRepos: ["POST /orgs/{org}/{security_product}/{enablement}"], + enableOrDisableSecurityProductOnAllOrgRepos: [ + "POST /orgs/{org}/{security_product}/{enablement}" + ], get: ["GET /orgs/{org}"], getMembershipForAuthenticatedUser: ["GET /user/memberships/orgs/{org}"], getMembershipForUser: ["GET /orgs/{org}/memberships/{username}"], getWebhook: ["GET /orgs/{org}/hooks/{hook_id}"], getWebhookConfigForOrg: ["GET /orgs/{org}/hooks/{hook_id}/config"], - getWebhookDelivery: ["GET /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}"], + getWebhookDelivery: [ + "GET /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}" + ], list: ["GET /organizations"], listAppInstallations: ["GET /orgs/{org}/installations"], listBlockedUsers: ["GET /orgs/{org}/blocks"], @@ -6585,57 +7428,149 @@ const Endpoints = { listMembers: ["GET /orgs/{org}/members"], listMembershipsForAuthenticatedUser: ["GET /user/memberships/orgs"], listOutsideCollaborators: ["GET /orgs/{org}/outside_collaborators"], + listPatGrantRepositories: [ + "GET /organizations/{org}/personal-access-tokens/{pat_id}/repositories" + ], + listPatGrantRequestRepositories: [ + "GET /organizations/{org}/personal-access-token-requests/{pat_request_id}/repositories" + ], + listPatGrantRequests: [ + "GET /organizations/{org}/personal-access-token-requests" + ], + listPatGrants: ["GET /organizations/{org}/personal-access-tokens"], listPendingInvitations: ["GET /orgs/{org}/invitations"], listPublicMembers: ["GET /orgs/{org}/public_members"], listSecurityManagerTeams: ["GET /orgs/{org}/security-managers"], listWebhookDeliveries: ["GET /orgs/{org}/hooks/{hook_id}/deliveries"], listWebhooks: ["GET /orgs/{org}/hooks"], pingWebhook: ["POST /orgs/{org}/hooks/{hook_id}/pings"], - redeliverWebhookDelivery: ["POST /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}/attempts"], + redeliverWebhookDelivery: [ + "POST /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}/attempts" + ], removeMember: ["DELETE /orgs/{org}/members/{username}"], removeMembershipForUser: ["DELETE /orgs/{org}/memberships/{username}"], - removeOutsideCollaborator: ["DELETE /orgs/{org}/outside_collaborators/{username}"], - removePublicMembershipForAuthenticatedUser: ["DELETE /orgs/{org}/public_members/{username}"], - removeSecurityManagerTeam: ["DELETE /orgs/{org}/security-managers/teams/{team_slug}"], + removeOutsideCollaborator: [ + "DELETE /orgs/{org}/outside_collaborators/{username}" + ], + removePublicMembershipForAuthenticatedUser: [ + "DELETE /orgs/{org}/public_members/{username}" + ], + removeSecurityManagerTeam: [ + "DELETE /orgs/{org}/security-managers/teams/{team_slug}" + ], + reviewPatGrantRequest: [ + "POST /organizations/{org}/personal-access-token-requests/{pat_request_id}" + ], + reviewPatGrantRequestsInBulk: [ + "POST /organizations/{org}/personal-access-token-requests" + ], setMembershipForUser: ["PUT /orgs/{org}/memberships/{username}"], - setPublicMembershipForAuthenticatedUser: ["PUT /orgs/{org}/public_members/{username}"], + setPublicMembershipForAuthenticatedUser: [ + "PUT /orgs/{org}/public_members/{username}" + ], unblockUser: ["DELETE /orgs/{org}/blocks/{username}"], update: ["PATCH /orgs/{org}"], - updateMembershipForAuthenticatedUser: ["PATCH /user/memberships/orgs/{org}"], + updateMembershipForAuthenticatedUser: [ + "PATCH /user/memberships/orgs/{org}" + ], + updatePatAccess: [ + "POST /organizations/{org}/personal-access-tokens/{pat_id}" + ], + updatePatAccesses: ["POST /organizations/{org}/personal-access-tokens"], updateWebhook: ["PATCH /orgs/{org}/hooks/{hook_id}"], updateWebhookConfigForOrg: ["PATCH /orgs/{org}/hooks/{hook_id}/config"] }, packages: { - deletePackageForAuthenticatedUser: ["DELETE /user/packages/{package_type}/{package_name}"], - deletePackageForOrg: ["DELETE /orgs/{org}/packages/{package_type}/{package_name}"], - deletePackageForUser: ["DELETE /users/{username}/packages/{package_type}/{package_name}"], - deletePackageVersionForAuthenticatedUser: ["DELETE /user/packages/{package_type}/{package_name}/versions/{package_version_id}"], - deletePackageVersionForOrg: ["DELETE /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}"], - deletePackageVersionForUser: ["DELETE /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}"], - getAllPackageVersionsForAPackageOwnedByAnOrg: ["GET /orgs/{org}/packages/{package_type}/{package_name}/versions", {}, { - renamed: ["packages", "getAllPackageVersionsForPackageOwnedByOrg"] - }], - getAllPackageVersionsForAPackageOwnedByTheAuthenticatedUser: ["GET /user/packages/{package_type}/{package_name}/versions", {}, { - renamed: ["packages", "getAllPackageVersionsForPackageOwnedByAuthenticatedUser"] - }], - getAllPackageVersionsForPackageOwnedByAuthenticatedUser: ["GET /user/packages/{package_type}/{package_name}/versions"], - getAllPackageVersionsForPackageOwnedByOrg: ["GET /orgs/{org}/packages/{package_type}/{package_name}/versions"], - getAllPackageVersionsForPackageOwnedByUser: ["GET /users/{username}/packages/{package_type}/{package_name}/versions"], - getPackageForAuthenticatedUser: ["GET /user/packages/{package_type}/{package_name}"], - getPackageForOrganization: ["GET /orgs/{org}/packages/{package_type}/{package_name}"], - getPackageForUser: ["GET /users/{username}/packages/{package_type}/{package_name}"], - getPackageVersionForAuthenticatedUser: ["GET /user/packages/{package_type}/{package_name}/versions/{package_version_id}"], - getPackageVersionForOrganization: ["GET /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}"], - getPackageVersionForUser: ["GET /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}"], + deletePackageForAuthenticatedUser: [ + "DELETE /user/packages/{package_type}/{package_name}" + ], + deletePackageForOrg: [ + "DELETE /orgs/{org}/packages/{package_type}/{package_name}" + ], + deletePackageForUser: [ + "DELETE /users/{username}/packages/{package_type}/{package_name}" + ], + deletePackageVersionForAuthenticatedUser: [ + "DELETE /user/packages/{package_type}/{package_name}/versions/{package_version_id}" + ], + deletePackageVersionForOrg: [ + "DELETE /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}" + ], + deletePackageVersionForUser: [ + "DELETE /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}" + ], + getAllPackageVersionsForAPackageOwnedByAnOrg: [ + "GET /orgs/{org}/packages/{package_type}/{package_name}/versions", + {}, + { renamed: ["packages", "getAllPackageVersionsForPackageOwnedByOrg"] } + ], + getAllPackageVersionsForAPackageOwnedByTheAuthenticatedUser: [ + "GET /user/packages/{package_type}/{package_name}/versions", + {}, + { + renamed: [ + "packages", + "getAllPackageVersionsForPackageOwnedByAuthenticatedUser" + ] + } + ], + getAllPackageVersionsForPackageOwnedByAuthenticatedUser: [ + "GET /user/packages/{package_type}/{package_name}/versions" + ], + getAllPackageVersionsForPackageOwnedByOrg: [ + "GET /orgs/{org}/packages/{package_type}/{package_name}/versions" + ], + getAllPackageVersionsForPackageOwnedByUser: [ + "GET /users/{username}/packages/{package_type}/{package_name}/versions" + ], + getPackageForAuthenticatedUser: [ + "GET /user/packages/{package_type}/{package_name}" + ], + getPackageForOrganization: [ + "GET /orgs/{org}/packages/{package_type}/{package_name}" + ], + getPackageForUser: [ + "GET /users/{username}/packages/{package_type}/{package_name}" + ], + getPackageVersionForAuthenticatedUser: [ + "GET /user/packages/{package_type}/{package_name}/versions/{package_version_id}" + ], + getPackageVersionForOrganization: [ + "GET /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}" + ], + getPackageVersionForUser: [ + "GET /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}" + ], + listDockerMigrationConflictingPackagesForAuthenticatedUser: [ + "GET /user/docker/conflicts" + ], + listDockerMigrationConflictingPackagesForOrganization: [ + "GET /orgs/{org}/docker/conflicts" + ], + listDockerMigrationConflictingPackagesForUser: [ + "GET /users/{username}/docker/conflicts" + ], listPackagesForAuthenticatedUser: ["GET /user/packages"], listPackagesForOrganization: ["GET /orgs/{org}/packages"], listPackagesForUser: ["GET /users/{username}/packages"], - restorePackageForAuthenticatedUser: ["POST /user/packages/{package_type}/{package_name}/restore{?token}"], - restorePackageForOrg: ["POST /orgs/{org}/packages/{package_type}/{package_name}/restore{?token}"], - restorePackageForUser: ["POST /users/{username}/packages/{package_type}/{package_name}/restore{?token}"], - restorePackageVersionForAuthenticatedUser: ["POST /user/packages/{package_type}/{package_name}/versions/{package_version_id}/restore"], - restorePackageVersionForOrg: ["POST /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore"], - restorePackageVersionForUser: ["POST /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore"] + restorePackageForAuthenticatedUser: [ + "POST /user/packages/{package_type}/{package_name}/restore{?token}" + ], + restorePackageForOrg: [ + "POST /orgs/{org}/packages/{package_type}/{package_name}/restore{?token}" + ], + restorePackageForUser: [ + "POST /users/{username}/packages/{package_type}/{package_name}/restore{?token}" + ], + restorePackageVersionForAuthenticatedUser: [ + "POST /user/packages/{package_type}/{package_name}/versions/{package_version_id}/restore" + ], + restorePackageVersionForOrg: [ + "POST /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore" + ], + restorePackageVersionForUser: [ + "POST /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore" + ] }, projects: { addCollaborator: ["PUT /projects/{project_id}/collaborators/{username}"], @@ -6650,7 +7585,9 @@ const Endpoints = { get: ["GET /projects/{project_id}"], getCard: ["GET /projects/columns/cards/{card_id}"], getColumn: ["GET /projects/columns/{column_id}"], - getPermissionForUser: ["GET /projects/{project_id}/collaborators/{username}/permission"], + getPermissionForUser: [ + "GET /projects/{project_id}/collaborators/{username}/permission" + ], listCards: ["GET /projects/columns/{column_id}/cards"], listCollaborators: ["GET /projects/{project_id}/collaborators"], listColumns: ["GET /projects/{project_id}/columns"], @@ -6659,7 +7596,9 @@ const Endpoints = { listForUser: ["GET /users/{username}/projects"], moveCard: ["POST /projects/columns/cards/{card_id}/moves"], moveColumn: ["POST /projects/columns/{column_id}/moves"], - removeCollaborator: ["DELETE /projects/{project_id}/collaborators/{username}"], + removeCollaborator: [ + "DELETE /projects/{project_id}/collaborators/{username}" + ], update: ["PATCH /projects/{project_id}"], updateCard: ["PATCH /projects/columns/cards/{card_id}"], updateColumn: ["PATCH /projects/columns/{column_id}"] @@ -6667,196 +7606,396 @@ const Endpoints = { pulls: { checkIfMerged: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/merge"], create: ["POST /repos/{owner}/{repo}/pulls"], - createReplyForReviewComment: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies"], + createReplyForReviewComment: [ + "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies" + ], createReview: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews"], - createReviewComment: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/comments"], - deletePendingReview: ["DELETE /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}"], - deleteReviewComment: ["DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}"], - dismissReview: ["PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/dismissals"], + createReviewComment: [ + "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments" + ], + deletePendingReview: [ + "DELETE /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}" + ], + deleteReviewComment: [ + "DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}" + ], + dismissReview: [ + "PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/dismissals" + ], get: ["GET /repos/{owner}/{repo}/pulls/{pull_number}"], - getReview: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}"], + getReview: [ + "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}" + ], getReviewComment: ["GET /repos/{owner}/{repo}/pulls/comments/{comment_id}"], list: ["GET /repos/{owner}/{repo}/pulls"], - listCommentsForReview: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments"], + listCommentsForReview: [ + "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments" + ], listCommits: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/commits"], listFiles: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/files"], - listRequestedReviewers: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers"], - listReviewComments: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/comments"], + listRequestedReviewers: [ + "GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers" + ], + listReviewComments: [ + "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments" + ], listReviewCommentsForRepo: ["GET /repos/{owner}/{repo}/pulls/comments"], listReviews: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews"], merge: ["PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge"], - removeRequestedReviewers: ["DELETE /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers"], - requestReviewers: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers"], - submitReview: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/events"], + removeRequestedReviewers: [ + "DELETE /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers" + ], + requestReviewers: [ + "POST /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers" + ], + submitReview: [ + "POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/events" + ], update: ["PATCH /repos/{owner}/{repo}/pulls/{pull_number}"], - updateBranch: ["PUT /repos/{owner}/{repo}/pulls/{pull_number}/update-branch"], - updateReview: ["PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}"], - updateReviewComment: ["PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}"] - }, - rateLimit: { - get: ["GET /rate_limit"] + updateBranch: [ + "PUT /repos/{owner}/{repo}/pulls/{pull_number}/update-branch" + ], + updateReview: [ + "PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}" + ], + updateReviewComment: [ + "PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}" + ] }, + rateLimit: { get: ["GET /rate_limit"] }, reactions: { - createForCommitComment: ["POST /repos/{owner}/{repo}/comments/{comment_id}/reactions"], - createForIssue: ["POST /repos/{owner}/{repo}/issues/{issue_number}/reactions"], - createForIssueComment: ["POST /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions"], - createForPullRequestReviewComment: ["POST /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions"], - createForRelease: ["POST /repos/{owner}/{repo}/releases/{release_id}/reactions"], - createForTeamDiscussionCommentInOrg: ["POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions"], - createForTeamDiscussionInOrg: ["POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions"], - deleteForCommitComment: ["DELETE /repos/{owner}/{repo}/comments/{comment_id}/reactions/{reaction_id}"], - deleteForIssue: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/reactions/{reaction_id}"], - deleteForIssueComment: ["DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions/{reaction_id}"], - deleteForPullRequestComment: ["DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions/{reaction_id}"], - deleteForRelease: ["DELETE /repos/{owner}/{repo}/releases/{release_id}/reactions/{reaction_id}"], - deleteForTeamDiscussion: ["DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions/{reaction_id}"], - deleteForTeamDiscussionComment: ["DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions/{reaction_id}"], - listForCommitComment: ["GET /repos/{owner}/{repo}/comments/{comment_id}/reactions"], + createForCommitComment: [ + "POST /repos/{owner}/{repo}/comments/{comment_id}/reactions" + ], + createForIssue: [ + "POST /repos/{owner}/{repo}/issues/{issue_number}/reactions" + ], + createForIssueComment: [ + "POST /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions" + ], + createForPullRequestReviewComment: [ + "POST /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions" + ], + createForRelease: [ + "POST /repos/{owner}/{repo}/releases/{release_id}/reactions" + ], + createForTeamDiscussionCommentInOrg: [ + "POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions" + ], + createForTeamDiscussionInOrg: [ + "POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions" + ], + deleteForCommitComment: [ + "DELETE /repos/{owner}/{repo}/comments/{comment_id}/reactions/{reaction_id}" + ], + deleteForIssue: [ + "DELETE /repos/{owner}/{repo}/issues/{issue_number}/reactions/{reaction_id}" + ], + deleteForIssueComment: [ + "DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions/{reaction_id}" + ], + deleteForPullRequestComment: [ + "DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions/{reaction_id}" + ], + deleteForRelease: [ + "DELETE /repos/{owner}/{repo}/releases/{release_id}/reactions/{reaction_id}" + ], + deleteForTeamDiscussion: [ + "DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions/{reaction_id}" + ], + deleteForTeamDiscussionComment: [ + "DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions/{reaction_id}" + ], + listForCommitComment: [ + "GET /repos/{owner}/{repo}/comments/{comment_id}/reactions" + ], listForIssue: ["GET /repos/{owner}/{repo}/issues/{issue_number}/reactions"], - listForIssueComment: ["GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions"], - listForPullRequestReviewComment: ["GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions"], - listForRelease: ["GET /repos/{owner}/{repo}/releases/{release_id}/reactions"], - listForTeamDiscussionCommentInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions"], - listForTeamDiscussionInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions"] + listForIssueComment: [ + "GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions" + ], + listForPullRequestReviewComment: [ + "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions" + ], + listForRelease: [ + "GET /repos/{owner}/{repo}/releases/{release_id}/reactions" + ], + listForTeamDiscussionCommentInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions" + ], + listForTeamDiscussionInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions" + ] }, repos: { - acceptInvitation: ["PATCH /user/repository_invitations/{invitation_id}", {}, { - renamed: ["repos", "acceptInvitationForAuthenticatedUser"] - }], - acceptInvitationForAuthenticatedUser: ["PATCH /user/repository_invitations/{invitation_id}"], - addAppAccessRestrictions: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", {}, { - mapToData: "apps" - }], + acceptInvitation: [ + "PATCH /user/repository_invitations/{invitation_id}", + {}, + { renamed: ["repos", "acceptInvitationForAuthenticatedUser"] } + ], + acceptInvitationForAuthenticatedUser: [ + "PATCH /user/repository_invitations/{invitation_id}" + ], + addAppAccessRestrictions: [ + "POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", + {}, + { mapToData: "apps" } + ], addCollaborator: ["PUT /repos/{owner}/{repo}/collaborators/{username}"], - addStatusCheckContexts: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", {}, { - mapToData: "contexts" - }], - addTeamAccessRestrictions: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", {}, { - mapToData: "teams" - }], - addUserAccessRestrictions: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", {}, { - mapToData: "users" - }], + addStatusCheckContexts: [ + "POST /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", + {}, + { mapToData: "contexts" } + ], + addTeamAccessRestrictions: [ + "POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", + {}, + { mapToData: "teams" } + ], + addUserAccessRestrictions: [ + "POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", + {}, + { mapToData: "users" } + ], checkCollaborator: ["GET /repos/{owner}/{repo}/collaborators/{username}"], - checkVulnerabilityAlerts: ["GET /repos/{owner}/{repo}/vulnerability-alerts"], + checkVulnerabilityAlerts: [ + "GET /repos/{owner}/{repo}/vulnerability-alerts" + ], codeownersErrors: ["GET /repos/{owner}/{repo}/codeowners/errors"], compareCommits: ["GET /repos/{owner}/{repo}/compare/{base}...{head}"], - compareCommitsWithBasehead: ["GET /repos/{owner}/{repo}/compare/{basehead}"], + compareCommitsWithBasehead: [ + "GET /repos/{owner}/{repo}/compare/{basehead}" + ], createAutolink: ["POST /repos/{owner}/{repo}/autolinks"], - createCommitComment: ["POST /repos/{owner}/{repo}/commits/{commit_sha}/comments"], - createCommitSignatureProtection: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures"], + createCommitComment: [ + "POST /repos/{owner}/{repo}/commits/{commit_sha}/comments" + ], + createCommitSignatureProtection: [ + "POST /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures" + ], createCommitStatus: ["POST /repos/{owner}/{repo}/statuses/{sha}"], createDeployKey: ["POST /repos/{owner}/{repo}/keys"], createDeployment: ["POST /repos/{owner}/{repo}/deployments"], - createDeploymentBranchPolicy: ["POST /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies"], - createDeploymentStatus: ["POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses"], + createDeploymentBranchPolicy: [ + "POST /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies" + ], + createDeploymentProtectionRule: [ + "POST /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules" + ], + createDeploymentStatus: [ + "POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses" + ], createDispatchEvent: ["POST /repos/{owner}/{repo}/dispatches"], createForAuthenticatedUser: ["POST /user/repos"], createFork: ["POST /repos/{owner}/{repo}/forks"], createInOrg: ["POST /orgs/{org}/repos"], - createOrUpdateEnvironment: ["PUT /repos/{owner}/{repo}/environments/{environment_name}"], + createOrUpdateEnvironment: [ + "PUT /repos/{owner}/{repo}/environments/{environment_name}" + ], createOrUpdateFileContents: ["PUT /repos/{owner}/{repo}/contents/{path}"], + createOrgRuleset: ["POST /orgs/{org}/rulesets"], createPagesDeployment: ["POST /repos/{owner}/{repo}/pages/deployment"], createPagesSite: ["POST /repos/{owner}/{repo}/pages"], createRelease: ["POST /repos/{owner}/{repo}/releases"], + createRepoRuleset: ["POST /repos/{owner}/{repo}/rulesets"], createTagProtection: ["POST /repos/{owner}/{repo}/tags/protection"], - createUsingTemplate: ["POST /repos/{template_owner}/{template_repo}/generate"], + createUsingTemplate: [ + "POST /repos/{template_owner}/{template_repo}/generate" + ], createWebhook: ["POST /repos/{owner}/{repo}/hooks"], - declineInvitation: ["DELETE /user/repository_invitations/{invitation_id}", {}, { - renamed: ["repos", "declineInvitationForAuthenticatedUser"] - }], - declineInvitationForAuthenticatedUser: ["DELETE /user/repository_invitations/{invitation_id}"], + declineInvitation: [ + "DELETE /user/repository_invitations/{invitation_id}", + {}, + { renamed: ["repos", "declineInvitationForAuthenticatedUser"] } + ], + declineInvitationForAuthenticatedUser: [ + "DELETE /user/repository_invitations/{invitation_id}" + ], delete: ["DELETE /repos/{owner}/{repo}"], - deleteAccessRestrictions: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions"], - deleteAdminBranchProtection: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins"], - deleteAnEnvironment: ["DELETE /repos/{owner}/{repo}/environments/{environment_name}"], + deleteAccessRestrictions: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions" + ], + deleteAdminBranchProtection: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins" + ], + deleteAnEnvironment: [ + "DELETE /repos/{owner}/{repo}/environments/{environment_name}" + ], deleteAutolink: ["DELETE /repos/{owner}/{repo}/autolinks/{autolink_id}"], - deleteBranchProtection: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection"], + deleteBranchProtection: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection" + ], deleteCommitComment: ["DELETE /repos/{owner}/{repo}/comments/{comment_id}"], - deleteCommitSignatureProtection: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures"], + deleteCommitSignatureProtection: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures" + ], deleteDeployKey: ["DELETE /repos/{owner}/{repo}/keys/{key_id}"], - deleteDeployment: ["DELETE /repos/{owner}/{repo}/deployments/{deployment_id}"], - deleteDeploymentBranchPolicy: ["DELETE /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}"], + deleteDeployment: [ + "DELETE /repos/{owner}/{repo}/deployments/{deployment_id}" + ], + deleteDeploymentBranchPolicy: [ + "DELETE /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}" + ], deleteFile: ["DELETE /repos/{owner}/{repo}/contents/{path}"], - deleteInvitation: ["DELETE /repos/{owner}/{repo}/invitations/{invitation_id}"], + deleteInvitation: [ + "DELETE /repos/{owner}/{repo}/invitations/{invitation_id}" + ], + deleteOrgRuleset: ["DELETE /orgs/{org}/rulesets/{ruleset_id}"], deletePagesSite: ["DELETE /repos/{owner}/{repo}/pages"], - deletePullRequestReviewProtection: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews"], + deletePullRequestReviewProtection: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews" + ], deleteRelease: ["DELETE /repos/{owner}/{repo}/releases/{release_id}"], - deleteReleaseAsset: ["DELETE /repos/{owner}/{repo}/releases/assets/{asset_id}"], - deleteTagProtection: ["DELETE /repos/{owner}/{repo}/tags/protection/{tag_protection_id}"], + deleteReleaseAsset: [ + "DELETE /repos/{owner}/{repo}/releases/assets/{asset_id}" + ], + deleteRepoRuleset: ["DELETE /repos/{owner}/{repo}/rulesets/{ruleset_id}"], + deleteTagProtection: [ + "DELETE /repos/{owner}/{repo}/tags/protection/{tag_protection_id}" + ], deleteWebhook: ["DELETE /repos/{owner}/{repo}/hooks/{hook_id}"], - disableAutomatedSecurityFixes: ["DELETE /repos/{owner}/{repo}/automated-security-fixes"], + disableAutomatedSecurityFixes: [ + "DELETE /repos/{owner}/{repo}/automated-security-fixes" + ], + disableDeploymentProtectionRule: [ + "DELETE /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/{protection_rule_id}" + ], disableLfsForRepo: ["DELETE /repos/{owner}/{repo}/lfs"], - disableVulnerabilityAlerts: ["DELETE /repos/{owner}/{repo}/vulnerability-alerts"], - downloadArchive: ["GET /repos/{owner}/{repo}/zipball/{ref}", {}, { - renamed: ["repos", "downloadZipballArchive"] - }], + disableVulnerabilityAlerts: [ + "DELETE /repos/{owner}/{repo}/vulnerability-alerts" + ], + downloadArchive: [ + "GET /repos/{owner}/{repo}/zipball/{ref}", + {}, + { renamed: ["repos", "downloadZipballArchive"] } + ], downloadTarballArchive: ["GET /repos/{owner}/{repo}/tarball/{ref}"], downloadZipballArchive: ["GET /repos/{owner}/{repo}/zipball/{ref}"], - enableAutomatedSecurityFixes: ["PUT /repos/{owner}/{repo}/automated-security-fixes"], + enableAutomatedSecurityFixes: [ + "PUT /repos/{owner}/{repo}/automated-security-fixes" + ], enableLfsForRepo: ["PUT /repos/{owner}/{repo}/lfs"], - enableVulnerabilityAlerts: ["PUT /repos/{owner}/{repo}/vulnerability-alerts"], - generateReleaseNotes: ["POST /repos/{owner}/{repo}/releases/generate-notes"], + enableVulnerabilityAlerts: [ + "PUT /repos/{owner}/{repo}/vulnerability-alerts" + ], + generateReleaseNotes: [ + "POST /repos/{owner}/{repo}/releases/generate-notes" + ], get: ["GET /repos/{owner}/{repo}"], - getAccessRestrictions: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions"], - getAdminBranchProtection: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins"], + getAccessRestrictions: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions" + ], + getAdminBranchProtection: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins" + ], + getAllDeploymentProtectionRules: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules" + ], getAllEnvironments: ["GET /repos/{owner}/{repo}/environments"], - getAllStatusCheckContexts: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts"], + getAllStatusCheckContexts: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts" + ], getAllTopics: ["GET /repos/{owner}/{repo}/topics"], - getAppsWithAccessToProtectedBranch: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps"], + getAppsWithAccessToProtectedBranch: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps" + ], getAutolink: ["GET /repos/{owner}/{repo}/autolinks/{autolink_id}"], getBranch: ["GET /repos/{owner}/{repo}/branches/{branch}"], - getBranchProtection: ["GET /repos/{owner}/{repo}/branches/{branch}/protection"], + getBranchProtection: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection" + ], + getBranchRules: ["GET /repos/{owner}/{repo}/rules/branches/{branch}"], getClones: ["GET /repos/{owner}/{repo}/traffic/clones"], getCodeFrequencyStats: ["GET /repos/{owner}/{repo}/stats/code_frequency"], - getCollaboratorPermissionLevel: ["GET /repos/{owner}/{repo}/collaborators/{username}/permission"], + getCollaboratorPermissionLevel: [ + "GET /repos/{owner}/{repo}/collaborators/{username}/permission" + ], getCombinedStatusForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/status"], getCommit: ["GET /repos/{owner}/{repo}/commits/{ref}"], getCommitActivityStats: ["GET /repos/{owner}/{repo}/stats/commit_activity"], getCommitComment: ["GET /repos/{owner}/{repo}/comments/{comment_id}"], - getCommitSignatureProtection: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures"], + getCommitSignatureProtection: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures" + ], getCommunityProfileMetrics: ["GET /repos/{owner}/{repo}/community/profile"], getContent: ["GET /repos/{owner}/{repo}/contents/{path}"], getContributorsStats: ["GET /repos/{owner}/{repo}/stats/contributors"], + getCustomDeploymentProtectionRule: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/{protection_rule_id}" + ], getDeployKey: ["GET /repos/{owner}/{repo}/keys/{key_id}"], getDeployment: ["GET /repos/{owner}/{repo}/deployments/{deployment_id}"], - getDeploymentBranchPolicy: ["GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}"], - getDeploymentStatus: ["GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses/{status_id}"], - getEnvironment: ["GET /repos/{owner}/{repo}/environments/{environment_name}"], + getDeploymentBranchPolicy: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}" + ], + getDeploymentStatus: [ + "GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses/{status_id}" + ], + getEnvironment: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}" + ], getLatestPagesBuild: ["GET /repos/{owner}/{repo}/pages/builds/latest"], getLatestRelease: ["GET /repos/{owner}/{repo}/releases/latest"], + getOrgRuleset: ["GET /orgs/{org}/rulesets/{ruleset_id}"], + getOrgRulesets: ["GET /orgs/{org}/rulesets"], getPages: ["GET /repos/{owner}/{repo}/pages"], getPagesBuild: ["GET /repos/{owner}/{repo}/pages/builds/{build_id}"], getPagesHealthCheck: ["GET /repos/{owner}/{repo}/pages/health"], getParticipationStats: ["GET /repos/{owner}/{repo}/stats/participation"], - getPullRequestReviewProtection: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews"], + getPullRequestReviewProtection: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews" + ], getPunchCardStats: ["GET /repos/{owner}/{repo}/stats/punch_card"], getReadme: ["GET /repos/{owner}/{repo}/readme"], getReadmeInDirectory: ["GET /repos/{owner}/{repo}/readme/{dir}"], getRelease: ["GET /repos/{owner}/{repo}/releases/{release_id}"], getReleaseAsset: ["GET /repos/{owner}/{repo}/releases/assets/{asset_id}"], getReleaseByTag: ["GET /repos/{owner}/{repo}/releases/tags/{tag}"], - getStatusChecksProtection: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks"], - getTeamsWithAccessToProtectedBranch: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams"], + getRepoRuleset: ["GET /repos/{owner}/{repo}/rulesets/{ruleset_id}"], + getRepoRulesets: ["GET /repos/{owner}/{repo}/rulesets"], + getStatusChecksProtection: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks" + ], + getTeamsWithAccessToProtectedBranch: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams" + ], getTopPaths: ["GET /repos/{owner}/{repo}/traffic/popular/paths"], getTopReferrers: ["GET /repos/{owner}/{repo}/traffic/popular/referrers"], - getUsersWithAccessToProtectedBranch: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users"], + getUsersWithAccessToProtectedBranch: [ + "GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users" + ], getViews: ["GET /repos/{owner}/{repo}/traffic/views"], getWebhook: ["GET /repos/{owner}/{repo}/hooks/{hook_id}"], - getWebhookConfigForRepo: ["GET /repos/{owner}/{repo}/hooks/{hook_id}/config"], - getWebhookDelivery: ["GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}"], + getWebhookConfigForRepo: [ + "GET /repos/{owner}/{repo}/hooks/{hook_id}/config" + ], + getWebhookDelivery: [ + "GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}" + ], listAutolinks: ["GET /repos/{owner}/{repo}/autolinks"], listBranches: ["GET /repos/{owner}/{repo}/branches"], - listBranchesForHeadCommit: ["GET /repos/{owner}/{repo}/commits/{commit_sha}/branches-where-head"], + listBranchesForHeadCommit: [ + "GET /repos/{owner}/{repo}/commits/{commit_sha}/branches-where-head" + ], listCollaborators: ["GET /repos/{owner}/{repo}/collaborators"], - listCommentsForCommit: ["GET /repos/{owner}/{repo}/commits/{commit_sha}/comments"], + listCommentsForCommit: [ + "GET /repos/{owner}/{repo}/commits/{commit_sha}/comments" + ], listCommitCommentsForRepo: ["GET /repos/{owner}/{repo}/comments"], - listCommitStatusesForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/statuses"], + listCommitStatusesForRef: [ + "GET /repos/{owner}/{repo}/commits/{ref}/statuses" + ], listCommits: ["GET /repos/{owner}/{repo}/commits"], listContributors: ["GET /repos/{owner}/{repo}/contributors"], + listCustomDeploymentRuleIntegrations: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/apps" + ], listDeployKeys: ["GET /repos/{owner}/{repo}/keys"], - listDeploymentBranchPolicies: ["GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies"], - listDeploymentStatuses: ["GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses"], + listDeploymentBranchPolicies: [ + "GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies" + ], + listDeploymentStatuses: [ + "GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses" + ], listDeployments: ["GET /repos/{owner}/{repo}/deployments"], listForAuthenticatedUser: ["GET /user/repos"], listForOrg: ["GET /orgs/{org}/repos"], @@ -6867,68 +8006,117 @@ const Endpoints = { listLanguages: ["GET /repos/{owner}/{repo}/languages"], listPagesBuilds: ["GET /repos/{owner}/{repo}/pages/builds"], listPublic: ["GET /repositories"], - listPullRequestsAssociatedWithCommit: ["GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls"], - listReleaseAssets: ["GET /repos/{owner}/{repo}/releases/{release_id}/assets"], + listPullRequestsAssociatedWithCommit: [ + "GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls" + ], + listReleaseAssets: [ + "GET /repos/{owner}/{repo}/releases/{release_id}/assets" + ], listReleases: ["GET /repos/{owner}/{repo}/releases"], listTagProtection: ["GET /repos/{owner}/{repo}/tags/protection"], listTags: ["GET /repos/{owner}/{repo}/tags"], listTeams: ["GET /repos/{owner}/{repo}/teams"], - listWebhookDeliveries: ["GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries"], + listWebhookDeliveries: [ + "GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries" + ], listWebhooks: ["GET /repos/{owner}/{repo}/hooks"], merge: ["POST /repos/{owner}/{repo}/merges"], mergeUpstream: ["POST /repos/{owner}/{repo}/merge-upstream"], pingWebhook: ["POST /repos/{owner}/{repo}/hooks/{hook_id}/pings"], - redeliverWebhookDelivery: ["POST /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}/attempts"], - removeAppAccessRestrictions: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", {}, { - mapToData: "apps" - }], - removeCollaborator: ["DELETE /repos/{owner}/{repo}/collaborators/{username}"], - removeStatusCheckContexts: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", {}, { - mapToData: "contexts" - }], - removeStatusCheckProtection: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks"], - removeTeamAccessRestrictions: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", {}, { - mapToData: "teams" - }], - removeUserAccessRestrictions: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", {}, { - mapToData: "users" - }], + redeliverWebhookDelivery: [ + "POST /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}/attempts" + ], + removeAppAccessRestrictions: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", + {}, + { mapToData: "apps" } + ], + removeCollaborator: [ + "DELETE /repos/{owner}/{repo}/collaborators/{username}" + ], + removeStatusCheckContexts: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", + {}, + { mapToData: "contexts" } + ], + removeStatusCheckProtection: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks" + ], + removeTeamAccessRestrictions: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", + {}, + { mapToData: "teams" } + ], + removeUserAccessRestrictions: [ + "DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", + {}, + { mapToData: "users" } + ], renameBranch: ["POST /repos/{owner}/{repo}/branches/{branch}/rename"], replaceAllTopics: ["PUT /repos/{owner}/{repo}/topics"], requestPagesBuild: ["POST /repos/{owner}/{repo}/pages/builds"], - setAdminBranchProtection: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins"], - setAppAccessRestrictions: ["PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", {}, { - mapToData: "apps" - }], - setStatusCheckContexts: ["PUT /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", {}, { - mapToData: "contexts" - }], - setTeamAccessRestrictions: ["PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", {}, { - mapToData: "teams" - }], - setUserAccessRestrictions: ["PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", {}, { - mapToData: "users" - }], + setAdminBranchProtection: [ + "POST /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins" + ], + setAppAccessRestrictions: [ + "PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", + {}, + { mapToData: "apps" } + ], + setStatusCheckContexts: [ + "PUT /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", + {}, + { mapToData: "contexts" } + ], + setTeamAccessRestrictions: [ + "PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", + {}, + { mapToData: "teams" } + ], + setUserAccessRestrictions: [ + "PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", + {}, + { mapToData: "users" } + ], testPushWebhook: ["POST /repos/{owner}/{repo}/hooks/{hook_id}/tests"], transfer: ["POST /repos/{owner}/{repo}/transfer"], update: ["PATCH /repos/{owner}/{repo}"], - updateBranchProtection: ["PUT /repos/{owner}/{repo}/branches/{branch}/protection"], + updateBranchProtection: [ + "PUT /repos/{owner}/{repo}/branches/{branch}/protection" + ], updateCommitComment: ["PATCH /repos/{owner}/{repo}/comments/{comment_id}"], - updateDeploymentBranchPolicy: ["PUT /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}"], + updateDeploymentBranchPolicy: [ + "PUT /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}" + ], updateInformationAboutPagesSite: ["PUT /repos/{owner}/{repo}/pages"], - updateInvitation: ["PATCH /repos/{owner}/{repo}/invitations/{invitation_id}"], - updatePullRequestReviewProtection: ["PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews"], + updateInvitation: [ + "PATCH /repos/{owner}/{repo}/invitations/{invitation_id}" + ], + updateOrgRuleset: ["PUT /orgs/{org}/rulesets/{ruleset_id}"], + updatePullRequestReviewProtection: [ + "PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews" + ], updateRelease: ["PATCH /repos/{owner}/{repo}/releases/{release_id}"], - updateReleaseAsset: ["PATCH /repos/{owner}/{repo}/releases/assets/{asset_id}"], - updateStatusCheckPotection: ["PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks", {}, { - renamed: ["repos", "updateStatusCheckProtection"] - }], - updateStatusCheckProtection: ["PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks"], + updateReleaseAsset: [ + "PATCH /repos/{owner}/{repo}/releases/assets/{asset_id}" + ], + updateRepoRuleset: ["PUT /repos/{owner}/{repo}/rulesets/{ruleset_id}"], + updateStatusCheckPotection: [ + "PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks", + {}, + { renamed: ["repos", "updateStatusCheckProtection"] } + ], + updateStatusCheckProtection: [ + "PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks" + ], updateWebhook: ["PATCH /repos/{owner}/{repo}/hooks/{hook_id}"], - updateWebhookConfigForRepo: ["PATCH /repos/{owner}/{repo}/hooks/{hook_id}/config"], - uploadReleaseAsset: ["POST /repos/{owner}/{repo}/releases/{release_id}/assets{?name,label}", { - baseUrl: "https://uploads.github.com" - }] + updateWebhookConfigForRepo: [ + "PATCH /repos/{owner}/{repo}/hooks/{hook_id}/config" + ], + uploadReleaseAsset: [ + "POST /repos/{owner}/{repo}/releases/{release_id}/assets{?name,label}", + { baseUrl: "https://uploads.github.com" } + ] }, search: { code: ["GET /search/code"], @@ -6940,246 +8128,392 @@ const Endpoints = { users: ["GET /search/users"] }, secretScanning: { - getAlert: ["GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}"], - getSecurityAnalysisSettingsForEnterprise: ["GET /enterprises/{enterprise}/code_security_and_analysis"], - listAlertsForEnterprise: ["GET /enterprises/{enterprise}/secret-scanning/alerts"], + getAlert: [ + "GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}" + ], + listAlertsForEnterprise: [ + "GET /enterprises/{enterprise}/secret-scanning/alerts" + ], listAlertsForOrg: ["GET /orgs/{org}/secret-scanning/alerts"], listAlertsForRepo: ["GET /repos/{owner}/{repo}/secret-scanning/alerts"], - listLocationsForAlert: ["GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations"], - patchSecurityAnalysisSettingsForEnterprise: ["PATCH /enterprises/{enterprise}/code_security_and_analysis"], - postSecurityProductEnablementForEnterprise: ["POST /enterprises/{enterprise}/{security_product}/{enablement}"], - updateAlert: ["PATCH /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}"] + listLocationsForAlert: [ + "GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations" + ], + updateAlert: [ + "PATCH /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}" + ] + }, + securityAdvisories: { + createPrivateVulnerabilityReport: [ + "POST /repos/{owner}/{repo}/security-advisories/reports" + ], + createRepositoryAdvisory: [ + "POST /repos/{owner}/{repo}/security-advisories" + ], + getRepositoryAdvisory: [ + "GET /repos/{owner}/{repo}/security-advisories/{ghsa_id}" + ], + listRepositoryAdvisories: ["GET /repos/{owner}/{repo}/security-advisories"], + updateRepositoryAdvisory: [ + "PATCH /repos/{owner}/{repo}/security-advisories/{ghsa_id}" + ] }, teams: { - addOrUpdateMembershipForUserInOrg: ["PUT /orgs/{org}/teams/{team_slug}/memberships/{username}"], - addOrUpdateProjectPermissionsInOrg: ["PUT /orgs/{org}/teams/{team_slug}/projects/{project_id}"], - addOrUpdateRepoPermissionsInOrg: ["PUT /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}"], - checkPermissionsForProjectInOrg: ["GET /orgs/{org}/teams/{team_slug}/projects/{project_id}"], - checkPermissionsForRepoInOrg: ["GET /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}"], + addOrUpdateMembershipForUserInOrg: [ + "PUT /orgs/{org}/teams/{team_slug}/memberships/{username}" + ], + addOrUpdateProjectPermissionsInOrg: [ + "PUT /orgs/{org}/teams/{team_slug}/projects/{project_id}" + ], + addOrUpdateRepoPermissionsInOrg: [ + "PUT /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}" + ], + checkPermissionsForProjectInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/projects/{project_id}" + ], + checkPermissionsForRepoInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}" + ], create: ["POST /orgs/{org}/teams"], - createDiscussionCommentInOrg: ["POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments"], + createDiscussionCommentInOrg: [ + "POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments" + ], createDiscussionInOrg: ["POST /orgs/{org}/teams/{team_slug}/discussions"], - deleteDiscussionCommentInOrg: ["DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}"], - deleteDiscussionInOrg: ["DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}"], + deleteDiscussionCommentInOrg: [ + "DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}" + ], + deleteDiscussionInOrg: [ + "DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}" + ], deleteInOrg: ["DELETE /orgs/{org}/teams/{team_slug}"], getByName: ["GET /orgs/{org}/teams/{team_slug}"], - getDiscussionCommentInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}"], - getDiscussionInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}"], - getMembershipForUserInOrg: ["GET /orgs/{org}/teams/{team_slug}/memberships/{username}"], + getDiscussionCommentInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}" + ], + getDiscussionInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}" + ], + getMembershipForUserInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/memberships/{username}" + ], list: ["GET /orgs/{org}/teams"], listChildInOrg: ["GET /orgs/{org}/teams/{team_slug}/teams"], - listDiscussionCommentsInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments"], + listDiscussionCommentsInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments" + ], listDiscussionsInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions"], listForAuthenticatedUser: ["GET /user/teams"], listMembersInOrg: ["GET /orgs/{org}/teams/{team_slug}/members"], - listPendingInvitationsInOrg: ["GET /orgs/{org}/teams/{team_slug}/invitations"], + listPendingInvitationsInOrg: [ + "GET /orgs/{org}/teams/{team_slug}/invitations" + ], listProjectsInOrg: ["GET /orgs/{org}/teams/{team_slug}/projects"], listReposInOrg: ["GET /orgs/{org}/teams/{team_slug}/repos"], - removeMembershipForUserInOrg: ["DELETE /orgs/{org}/teams/{team_slug}/memberships/{username}"], - removeProjectInOrg: ["DELETE /orgs/{org}/teams/{team_slug}/projects/{project_id}"], - removeRepoInOrg: ["DELETE /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}"], - updateDiscussionCommentInOrg: ["PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}"], - updateDiscussionInOrg: ["PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}"], + removeMembershipForUserInOrg: [ + "DELETE /orgs/{org}/teams/{team_slug}/memberships/{username}" + ], + removeProjectInOrg: [ + "DELETE /orgs/{org}/teams/{team_slug}/projects/{project_id}" + ], + removeRepoInOrg: [ + "DELETE /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}" + ], + updateDiscussionCommentInOrg: [ + "PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}" + ], + updateDiscussionInOrg: [ + "PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}" + ], updateInOrg: ["PATCH /orgs/{org}/teams/{team_slug}"] }, users: { - addEmailForAuthenticated: ["POST /user/emails", {}, { - renamed: ["users", "addEmailForAuthenticatedUser"] - }], + addEmailForAuthenticated: [ + "POST /user/emails", + {}, + { renamed: ["users", "addEmailForAuthenticatedUser"] } + ], addEmailForAuthenticatedUser: ["POST /user/emails"], + addSocialAccountForAuthenticatedUser: ["POST /user/social_accounts"], block: ["PUT /user/blocks/{username}"], checkBlocked: ["GET /user/blocks/{username}"], checkFollowingForUser: ["GET /users/{username}/following/{target_user}"], checkPersonIsFollowedByAuthenticated: ["GET /user/following/{username}"], - createGpgKeyForAuthenticated: ["POST /user/gpg_keys", {}, { - renamed: ["users", "createGpgKeyForAuthenticatedUser"] - }], + createGpgKeyForAuthenticated: [ + "POST /user/gpg_keys", + {}, + { renamed: ["users", "createGpgKeyForAuthenticatedUser"] } + ], createGpgKeyForAuthenticatedUser: ["POST /user/gpg_keys"], - createPublicSshKeyForAuthenticated: ["POST /user/keys", {}, { - renamed: ["users", "createPublicSshKeyForAuthenticatedUser"] - }], + createPublicSshKeyForAuthenticated: [ + "POST /user/keys", + {}, + { renamed: ["users", "createPublicSshKeyForAuthenticatedUser"] } + ], createPublicSshKeyForAuthenticatedUser: ["POST /user/keys"], createSshSigningKeyForAuthenticatedUser: ["POST /user/ssh_signing_keys"], - deleteEmailForAuthenticated: ["DELETE /user/emails", {}, { - renamed: ["users", "deleteEmailForAuthenticatedUser"] - }], + deleteEmailForAuthenticated: [ + "DELETE /user/emails", + {}, + { renamed: ["users", "deleteEmailForAuthenticatedUser"] } + ], deleteEmailForAuthenticatedUser: ["DELETE /user/emails"], - deleteGpgKeyForAuthenticated: ["DELETE /user/gpg_keys/{gpg_key_id}", {}, { - renamed: ["users", "deleteGpgKeyForAuthenticatedUser"] - }], + deleteGpgKeyForAuthenticated: [ + "DELETE /user/gpg_keys/{gpg_key_id}", + {}, + { renamed: ["users", "deleteGpgKeyForAuthenticatedUser"] } + ], deleteGpgKeyForAuthenticatedUser: ["DELETE /user/gpg_keys/{gpg_key_id}"], - deletePublicSshKeyForAuthenticated: ["DELETE /user/keys/{key_id}", {}, { - renamed: ["users", "deletePublicSshKeyForAuthenticatedUser"] - }], + deletePublicSshKeyForAuthenticated: [ + "DELETE /user/keys/{key_id}", + {}, + { renamed: ["users", "deletePublicSshKeyForAuthenticatedUser"] } + ], deletePublicSshKeyForAuthenticatedUser: ["DELETE /user/keys/{key_id}"], - deleteSshSigningKeyForAuthenticatedUser: ["DELETE /user/ssh_signing_keys/{ssh_signing_key_id}"], + deleteSocialAccountForAuthenticatedUser: ["DELETE /user/social_accounts"], + deleteSshSigningKeyForAuthenticatedUser: [ + "DELETE /user/ssh_signing_keys/{ssh_signing_key_id}" + ], follow: ["PUT /user/following/{username}"], getAuthenticated: ["GET /user"], getByUsername: ["GET /users/{username}"], getContextForUser: ["GET /users/{username}/hovercard"], - getGpgKeyForAuthenticated: ["GET /user/gpg_keys/{gpg_key_id}", {}, { - renamed: ["users", "getGpgKeyForAuthenticatedUser"] - }], + getGpgKeyForAuthenticated: [ + "GET /user/gpg_keys/{gpg_key_id}", + {}, + { renamed: ["users", "getGpgKeyForAuthenticatedUser"] } + ], getGpgKeyForAuthenticatedUser: ["GET /user/gpg_keys/{gpg_key_id}"], - getPublicSshKeyForAuthenticated: ["GET /user/keys/{key_id}", {}, { - renamed: ["users", "getPublicSshKeyForAuthenticatedUser"] - }], + getPublicSshKeyForAuthenticated: [ + "GET /user/keys/{key_id}", + {}, + { renamed: ["users", "getPublicSshKeyForAuthenticatedUser"] } + ], getPublicSshKeyForAuthenticatedUser: ["GET /user/keys/{key_id}"], - getSshSigningKeyForAuthenticatedUser: ["GET /user/ssh_signing_keys/{ssh_signing_key_id}"], + getSshSigningKeyForAuthenticatedUser: [ + "GET /user/ssh_signing_keys/{ssh_signing_key_id}" + ], list: ["GET /users"], - listBlockedByAuthenticated: ["GET /user/blocks", {}, { - renamed: ["users", "listBlockedByAuthenticatedUser"] - }], + listBlockedByAuthenticated: [ + "GET /user/blocks", + {}, + { renamed: ["users", "listBlockedByAuthenticatedUser"] } + ], listBlockedByAuthenticatedUser: ["GET /user/blocks"], - listEmailsForAuthenticated: ["GET /user/emails", {}, { - renamed: ["users", "listEmailsForAuthenticatedUser"] - }], + listEmailsForAuthenticated: [ + "GET /user/emails", + {}, + { renamed: ["users", "listEmailsForAuthenticatedUser"] } + ], listEmailsForAuthenticatedUser: ["GET /user/emails"], - listFollowedByAuthenticated: ["GET /user/following", {}, { - renamed: ["users", "listFollowedByAuthenticatedUser"] - }], + listFollowedByAuthenticated: [ + "GET /user/following", + {}, + { renamed: ["users", "listFollowedByAuthenticatedUser"] } + ], listFollowedByAuthenticatedUser: ["GET /user/following"], listFollowersForAuthenticatedUser: ["GET /user/followers"], listFollowersForUser: ["GET /users/{username}/followers"], listFollowingForUser: ["GET /users/{username}/following"], - listGpgKeysForAuthenticated: ["GET /user/gpg_keys", {}, { - renamed: ["users", "listGpgKeysForAuthenticatedUser"] - }], + listGpgKeysForAuthenticated: [ + "GET /user/gpg_keys", + {}, + { renamed: ["users", "listGpgKeysForAuthenticatedUser"] } + ], listGpgKeysForAuthenticatedUser: ["GET /user/gpg_keys"], listGpgKeysForUser: ["GET /users/{username}/gpg_keys"], - listPublicEmailsForAuthenticated: ["GET /user/public_emails", {}, { - renamed: ["users", "listPublicEmailsForAuthenticatedUser"] - }], + listPublicEmailsForAuthenticated: [ + "GET /user/public_emails", + {}, + { renamed: ["users", "listPublicEmailsForAuthenticatedUser"] } + ], listPublicEmailsForAuthenticatedUser: ["GET /user/public_emails"], listPublicKeysForUser: ["GET /users/{username}/keys"], - listPublicSshKeysForAuthenticated: ["GET /user/keys", {}, { - renamed: ["users", "listPublicSshKeysForAuthenticatedUser"] - }], + listPublicSshKeysForAuthenticated: [ + "GET /user/keys", + {}, + { renamed: ["users", "listPublicSshKeysForAuthenticatedUser"] } + ], listPublicSshKeysForAuthenticatedUser: ["GET /user/keys"], + listSocialAccountsForAuthenticatedUser: ["GET /user/social_accounts"], + listSocialAccountsForUser: ["GET /users/{username}/social_accounts"], listSshSigningKeysForAuthenticatedUser: ["GET /user/ssh_signing_keys"], listSshSigningKeysForUser: ["GET /users/{username}/ssh_signing_keys"], - setPrimaryEmailVisibilityForAuthenticated: ["PATCH /user/email/visibility", {}, { - renamed: ["users", "setPrimaryEmailVisibilityForAuthenticatedUser"] - }], - setPrimaryEmailVisibilityForAuthenticatedUser: ["PATCH /user/email/visibility"], + setPrimaryEmailVisibilityForAuthenticated: [ + "PATCH /user/email/visibility", + {}, + { renamed: ["users", "setPrimaryEmailVisibilityForAuthenticatedUser"] } + ], + setPrimaryEmailVisibilityForAuthenticatedUser: [ + "PATCH /user/email/visibility" + ], unblock: ["DELETE /user/blocks/{username}"], unfollow: ["DELETE /user/following/{username}"], updateAuthenticated: ["PATCH /user"] } }; - -const VERSION = "7.0.1"; - -function endpointsToMethods(octokit, endpointsMap) { - const newMethods = {}; - for (const [scope, endpoints] of Object.entries(endpointsMap)) { - for (const [methodName, endpoint] of Object.entries(endpoints)) { - const [route, defaults, decorations] = endpoint; - const [method, url] = route.split(/ /); - const endpointDefaults = Object.assign({ +var endpoints_default = Endpoints; + +// pkg/dist-src/endpoints-to-methods.js +var endpointMethodsMap = /* @__PURE__ */ new Map(); +for (const [scope, endpoints] of Object.entries(endpoints_default)) { + for (const [methodName, endpoint] of Object.entries(endpoints)) { + const [route, defaults, decorations] = endpoint; + const [method, url] = route.split(/ /); + const endpointDefaults = Object.assign( + { method, url - }, defaults); - if (!newMethods[scope]) { - newMethods[scope] = {}; - } - const scopeMethods = newMethods[scope]; - if (decorations) { - scopeMethods[methodName] = decorate(octokit, scope, methodName, endpointDefaults, decorations); - continue; - } - scopeMethods[methodName] = octokit.request.defaults(endpointDefaults); + }, + defaults + ); + if (!endpointMethodsMap.has(scope)) { + endpointMethodsMap.set(scope, /* @__PURE__ */ new Map()); + } + endpointMethodsMap.get(scope).set(methodName, { + scope, + methodName, + endpointDefaults, + decorations + }); + } +} +var handler = { + get({ octokit, scope, cache }, methodName) { + if (cache[methodName]) { + return cache[methodName]; + } + const { decorations, endpointDefaults } = endpointMethodsMap.get(scope).get(methodName); + if (decorations) { + cache[methodName] = decorate( + octokit, + scope, + methodName, + endpointDefaults, + decorations + ); + } else { + cache[methodName] = octokit.request.defaults(endpointDefaults); } + return cache[methodName]; + } +}; +function endpointsToMethods(octokit) { + const newMethods = {}; + for (const scope of endpointMethodsMap.keys()) { + newMethods[scope] = new Proxy({ octokit, scope, cache: {} }, handler); } return newMethods; } function decorate(octokit, scope, methodName, defaults, decorations) { const requestWithDefaults = octokit.request.defaults(defaults); - /* istanbul ignore next */ function withDecorations(...args) { - // @ts-ignore https://github.com/microsoft/TypeScript/issues/25488 let options = requestWithDefaults.endpoint.merge(...args); - // There are currently no other decorations than `.mapToData` if (decorations.mapToData) { options = Object.assign({}, options, { data: options[decorations.mapToData], - [decorations.mapToData]: undefined + [decorations.mapToData]: void 0 }); return requestWithDefaults(options); } if (decorations.renamed) { const [newScope, newMethodName] = decorations.renamed; - octokit.log.warn(`octokit.${scope}.${methodName}() has been renamed to octokit.${newScope}.${newMethodName}()`); + octokit.log.warn( + `octokit.${scope}.${methodName}() has been renamed to octokit.${newScope}.${newMethodName}()` + ); } if (decorations.deprecated) { octokit.log.warn(decorations.deprecated); } if (decorations.renamedParameters) { - // @ts-ignore https://github.com/microsoft/TypeScript/issues/25488 - const options = requestWithDefaults.endpoint.merge(...args); - for (const [name, alias] of Object.entries(decorations.renamedParameters)) { - if (name in options) { - octokit.log.warn(`"${name}" parameter is deprecated for "octokit.${scope}.${methodName}()". Use "${alias}" instead`); - if (!(alias in options)) { - options[alias] = options[name]; + const options2 = requestWithDefaults.endpoint.merge(...args); + for (const [name, alias] of Object.entries( + decorations.renamedParameters + )) { + if (name in options2) { + octokit.log.warn( + `"${name}" parameter is deprecated for "octokit.${scope}.${methodName}()". Use "${alias}" instead` + ); + if (!(alias in options2)) { + options2[alias] = options2[name]; } - delete options[name]; + delete options2[name]; } } - return requestWithDefaults(options); + return requestWithDefaults(options2); } - // @ts-ignore https://github.com/microsoft/TypeScript/issues/25488 return requestWithDefaults(...args); } return Object.assign(withDecorations, requestWithDefaults); } +// pkg/dist-src/index.js function restEndpointMethods(octokit) { - const api = endpointsToMethods(octokit, Endpoints); + const api = endpointsToMethods(octokit); return { rest: api }; } restEndpointMethods.VERSION = VERSION; function legacyRestEndpointMethods(octokit) { - const api = endpointsToMethods(octokit, Endpoints); + const api = endpointsToMethods(octokit); return { ...api, rest: api }; } legacyRestEndpointMethods.VERSION = VERSION; - -exports.legacyRestEndpointMethods = legacyRestEndpointMethods; -exports.restEndpointMethods = restEndpointMethods; -//# sourceMappingURL=index.js.map +// Annotate the CommonJS export names for ESM import in node: +0 && (0); /***/ }), /***/ 6239: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); - -function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } - -var deprecation = __nccwpck_require__(8932); -var once = _interopDefault(__nccwpck_require__(1223)); - -const logOnceCode = once(deprecation => console.warn(deprecation)); -const logOnceHeaders = once(deprecation => console.warn(deprecation)); -/** - * Error with extra properties to help with debugging - */ -class RequestError extends Error { +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// pkg/dist-src/index.js +var dist_src_exports = {}; +__export(dist_src_exports, { + RequestError: () => RequestError +}); +module.exports = __toCommonJS(dist_src_exports); +var import_deprecation = __nccwpck_require__(8932); +var import_once = __toESM(__nccwpck_require__(1223)); +var logOnceCode = (0, import_once.default)((deprecation) => console.warn(deprecation)); +var logOnceHeaders = (0, import_once.default)((deprecation) => console.warn(deprecation)); +var RequestError = class extends Error { constructor(message, statusCode, options) { super(message); - // Maintains proper stack trace (only available on V8) - /* istanbul ignore next */ if (Error.captureStackTrace) { Error.captureStackTrace(this, this.constructor); } @@ -7193,83 +8527,128 @@ class RequestError extends Error { this.response = options.response; headers = options.response.headers; } - // redact request credentials without mutating original request options const requestCopy = Object.assign({}, options.request); if (options.request.headers.authorization) { requestCopy.headers = Object.assign({}, options.request.headers, { - authorization: options.request.headers.authorization.replace(/ .*$/, " [REDACTED]") + authorization: options.request.headers.authorization.replace( + / .*$/, + " [REDACTED]" + ) }); } - requestCopy.url = requestCopy.url - // client_id & client_secret can be passed as URL query parameters to increase rate limit - // see https://developer.github.com/v3/#increasing-the-unauthenticated-rate-limit-for-oauth-applications - .replace(/\bclient_secret=\w+/g, "client_secret=[REDACTED]") - // OAuth tokens can be passed as URL query parameters, although it is not recommended - // see https://developer.github.com/v3/#oauth2-token-sent-in-a-header - .replace(/\baccess_token=\w+/g, "access_token=[REDACTED]"); + requestCopy.url = requestCopy.url.replace(/\bclient_secret=\w+/g, "client_secret=[REDACTED]").replace(/\baccess_token=\w+/g, "access_token=[REDACTED]"); this.request = requestCopy; - // deprecations Object.defineProperty(this, "code", { get() { - logOnceCode(new deprecation.Deprecation("[@octokit/request-error] `error.code` is deprecated, use `error.status`.")); + logOnceCode( + new import_deprecation.Deprecation( + "[@octokit/request-error] `error.code` is deprecated, use `error.status`." + ) + ); return statusCode; } }); Object.defineProperty(this, "headers", { get() { - logOnceHeaders(new deprecation.Deprecation("[@octokit/request-error] `error.headers` is deprecated, use `error.response.headers`.")); + logOnceHeaders( + new import_deprecation.Deprecation( + "[@octokit/request-error] `error.headers` is deprecated, use `error.response.headers`." + ) + ); return headers || {}; } }); } -} - -exports.RequestError = RequestError; -//# sourceMappingURL=index.js.map +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (0); /***/ }), /***/ 6206: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// pkg/dist-src/index.js +var dist_src_exports = {}; +__export(dist_src_exports, { + request: () => request +}); +module.exports = __toCommonJS(dist_src_exports); +var import_endpoint = __nccwpck_require__(6065); +var import_universal_user_agent = __nccwpck_require__(5030); -Object.defineProperty(exports, "__esModule", ({ value: true })); - -function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } - -var endpoint = __nccwpck_require__(6065); -var universalUserAgent = __nccwpck_require__(5030); -var isPlainObject = __nccwpck_require__(3287); -var nodeFetch = _interopDefault(__nccwpck_require__(467)); -var requestError = __nccwpck_require__(6239); +// pkg/dist-src/version.js +var VERSION = "6.2.7"; -const VERSION = "6.2.3"; +// pkg/dist-src/fetch-wrapper.js +var import_is_plain_object = __nccwpck_require__(3287); +var import_node_fetch = __toESM(__nccwpck_require__(467)); +var import_request_error = __nccwpck_require__(6239); +// pkg/dist-src/get-buffer-response.js function getBufferResponse(response) { return response.arrayBuffer(); } +// pkg/dist-src/fetch-wrapper.js function fetchWrapper(requestOptions) { const log = requestOptions.request && requestOptions.request.log ? requestOptions.request.log : console; - if (isPlainObject.isPlainObject(requestOptions.body) || Array.isArray(requestOptions.body)) { + if ((0, import_is_plain_object.isPlainObject)(requestOptions.body) || Array.isArray(requestOptions.body)) { requestOptions.body = JSON.stringify(requestOptions.body); } let headers = {}; let status; let url; - const fetch = requestOptions.request && requestOptions.request.fetch || globalThis.fetch || /* istanbul ignore next */nodeFetch; - return fetch(requestOptions.url, Object.assign({ - method: requestOptions.method, - body: requestOptions.body, - headers: requestOptions.headers, - redirect: requestOptions.redirect - }, - // `requestOptions.request.agent` type is incompatible - // see https://github.com/octokit/types.ts/pull/264 - requestOptions.request)).then(async response => { + const fetch = requestOptions.request && requestOptions.request.fetch || globalThis.fetch || /* istanbul ignore next */ + import_node_fetch.default; + return fetch( + requestOptions.url, + Object.assign( + { + method: requestOptions.method, + body: requestOptions.body, + headers: requestOptions.headers, + redirect: requestOptions.redirect, + // duplex must be set if request.body is ReadableStream or Async Iterables. + // See https://fetch.spec.whatwg.org/#dom-requestinit-duplex. + ...requestOptions.body && { duplex: "half" } + }, + // `requestOptions.request.agent` type is incompatible + // see https://github.com/octokit/types.ts/pull/264 + requestOptions.request + ) + ).then(async (response) => { url = response.url; status = response.status; for (const keyAndValue of response.headers) { @@ -7278,28 +8657,29 @@ function fetchWrapper(requestOptions) { if ("deprecation" in headers) { const matches = headers.link && headers.link.match(/<([^>]+)>; rel="deprecation"/); const deprecationLink = matches && matches.pop(); - log.warn(`[@octokit/request] "${requestOptions.method} ${requestOptions.url}" is deprecated. It is scheduled to be removed on ${headers.sunset}${deprecationLink ? `. See ${deprecationLink}` : ""}`); + log.warn( + `[@octokit/request] "${requestOptions.method} ${requestOptions.url}" is deprecated. It is scheduled to be removed on ${headers.sunset}${deprecationLink ? `. See ${deprecationLink}` : ""}` + ); } if (status === 204 || status === 205) { return; } - // GitHub API returns 200 for HEAD requests if (requestOptions.method === "HEAD") { if (status < 400) { return; } - throw new requestError.RequestError(response.statusText, status, { + throw new import_request_error.RequestError(response.statusText, status, { response: { url, status, headers, - data: undefined + data: void 0 }, request: requestOptions }); } if (status === 304) { - throw new requestError.RequestError("Not modified", status, { + throw new import_request_error.RequestError("Not modified", status, { response: { url, status, @@ -7311,7 +8691,7 @@ function fetchWrapper(requestOptions) { } if (status >= 400) { const data = await getResponseData(response); - const error = new requestError.RequestError(toErrorMessage(data), status, { + const error = new import_request_error.RequestError(toErrorMessage(data), status, { response: { url, status, @@ -7323,16 +8703,19 @@ function fetchWrapper(requestOptions) { throw error; } return getResponseData(response); - }).then(data => { + }).then((data) => { return { status, url, headers, data }; - }).catch(error => { - if (error instanceof requestError.RequestError) throw error;else if (error.name === "AbortError") throw error; - throw new requestError.RequestError(error.message, 500, { + }).catch((error) => { + if (error instanceof import_request_error.RequestError) + throw error; + else if (error.name === "AbortError") + throw error; + throw new import_request_error.RequestError(error.message, 500, { request: requestOptions }); }); @@ -7348,48 +8731,50 @@ async function getResponseData(response) { return getBufferResponse(response); } function toErrorMessage(data) { - if (typeof data === "string") return data; - // istanbul ignore else - just in case + if (typeof data === "string") + return data; if ("message" in data) { if (Array.isArray(data.errors)) { return `${data.message}: ${data.errors.map(JSON.stringify).join(", ")}`; } return data.message; } - // istanbul ignore next - just in case return `Unknown error: ${JSON.stringify(data)}`; } +// pkg/dist-src/with-defaults.js function withDefaults(oldEndpoint, newDefaults) { - const endpoint = oldEndpoint.defaults(newDefaults); - const newApi = function (route, parameters) { - const endpointOptions = endpoint.merge(route, parameters); + const endpoint2 = oldEndpoint.defaults(newDefaults); + const newApi = function(route, parameters) { + const endpointOptions = endpoint2.merge(route, parameters); if (!endpointOptions.request || !endpointOptions.request.hook) { - return fetchWrapper(endpoint.parse(endpointOptions)); + return fetchWrapper(endpoint2.parse(endpointOptions)); } - const request = (route, parameters) => { - return fetchWrapper(endpoint.parse(endpoint.merge(route, parameters))); + const request2 = (route2, parameters2) => { + return fetchWrapper( + endpoint2.parse(endpoint2.merge(route2, parameters2)) + ); }; - Object.assign(request, { - endpoint, - defaults: withDefaults.bind(null, endpoint) + Object.assign(request2, { + endpoint: endpoint2, + defaults: withDefaults.bind(null, endpoint2) }); - return endpointOptions.request.hook(request, endpointOptions); + return endpointOptions.request.hook(request2, endpointOptions); }; return Object.assign(newApi, { - endpoint, - defaults: withDefaults.bind(null, endpoint) + endpoint: endpoint2, + defaults: withDefaults.bind(null, endpoint2) }); } -const request = withDefaults(endpoint.endpoint, { +// pkg/dist-src/index.js +var request = withDefaults(import_endpoint.endpoint, { headers: { - "user-agent": `octokit-request.js/${VERSION} ${universalUserAgent.getUserAgent()}` + "user-agent": `octokit-request.js/${VERSION} ${(0, import_universal_user_agent.getUserAgent)()}` } }); - -exports.request = request; -//# sourceMappingURL=index.js.map +// Annotate the CommonJS export names for ESM import in node: +0 && (0); /***/ }), @@ -29998,41 +31383,53 @@ module.exports = require("zlib"); "use strict"; -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var Scalar = __nccwpck_require__(9338); +var YAMLMap = __nccwpck_require__(6011); +var YAMLSeq = __nccwpck_require__(5161); var resolveBlockMap = __nccwpck_require__(2986); var resolveBlockSeq = __nccwpck_require__(2289); var resolveFlowCollection = __nccwpck_require__(45); -function composeCollection(CN, ctx, token, tagToken, onError) { - let coll; - switch (token.type) { - case 'block-map': { - coll = resolveBlockMap.resolveBlockMap(CN, ctx, token, onError); - break; - } - case 'block-seq': { - coll = resolveBlockSeq.resolveBlockSeq(CN, ctx, token, onError); - break; - } - case 'flow-collection': { - coll = resolveFlowCollection.resolveFlowCollection(CN, ctx, token, onError); - break; - } - } - if (!tagToken) - return coll; - const tagName = ctx.directives.tagName(tagToken.source, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg)); - if (!tagName) - return coll; - // Cast needed due to: https://github.com/Microsoft/TypeScript/issues/3841 +function resolveCollection(CN, ctx, token, onError, tagName, tag) { + const coll = token.type === 'block-map' + ? resolveBlockMap.resolveBlockMap(CN, ctx, token, onError, tag) + : token.type === 'block-seq' + ? resolveBlockSeq.resolveBlockSeq(CN, ctx, token, onError, tag) + : resolveFlowCollection.resolveFlowCollection(CN, ctx, token, onError, tag); const Coll = coll.constructor; + // If we got a tagName matching the class, or the tag name is '!', + // then use the tagName from the node class used to create it. if (tagName === '!' || tagName === Coll.tagName) { coll.tag = Coll.tagName; return coll; } - const expType = Node.isMap(coll) ? 'map' : 'seq'; - let tag = ctx.schema.tags.find(t => t.collection === expType && t.tag === tagName); + if (tagName) + coll.tag = tagName; + return coll; +} +function composeCollection(CN, ctx, token, tagToken, onError) { + const tagName = !tagToken + ? null + : ctx.directives.tagName(tagToken.source, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg)); + const expType = token.type === 'block-map' + ? 'map' + : token.type === 'block-seq' + ? 'seq' + : token.start.source === '{' + ? 'map' + : 'seq'; + // shortcut: check if it's a generic YAMLMap or YAMLSeq + // before jumping into the custom tag logic. + if (!tagToken || + !tagName || + tagName === '!' || + (tagName === YAMLMap.YAMLMap.tagName && expType === 'map') || + (tagName === YAMLSeq.YAMLSeq.tagName && expType === 'seq') || + !expType) { + return resolveCollection(CN, ctx, token, onError, tagName); + } + let tag = ctx.schema.tags.find(t => t.tag === tagName && t.collection === expType); if (!tag) { const kt = ctx.schema.knownTags[tagName]; if (kt && kt.collection === expType) { @@ -30040,13 +31437,18 @@ function composeCollection(CN, ctx, token, tagToken, onError) { tag = kt; } else { - onError(tagToken, 'TAG_RESOLVE_FAILED', `Unresolved tag: ${tagName}`, true); - coll.tag = tagName; - return coll; + if (kt?.collection) { + onError(tagToken, 'BAD_COLLECTION_TYPE', `${kt.tag} used for ${expType} collection, but expects ${kt.collection}`, true); + } + else { + onError(tagToken, 'TAG_RESOLVE_FAILED', `Unresolved tag: ${tagName}`, true); + } + return resolveCollection(CN, ctx, token, onError, tagName); } } - const res = tag.resolve(coll, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg), ctx.options); - const node = Node.isNode(res) + const coll = resolveCollection(CN, ctx, token, onError, tagName, tag); + const res = tag.resolve?.(coll, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg), ctx.options) ?? coll; + const node = identity.isNode(res) ? res : new Scalar.Scalar(res); node.range = coll.range; @@ -30095,6 +31497,7 @@ function composeDoc(options, directives, { offset, start, value, end }, onError) !props.hasNewline) onError(props.end, 'MISSING_CHAR', 'Block collection cannot start on same line with directives-end marker'); } + // @ts-expect-error If Contents is set, let's trust the user doc.contents = value ? composeNode.composeNode(ctx, value, props, onError) : composeNode.composeEmptyNode(ctx, props.end, start, null, props, onError); @@ -30220,7 +31623,7 @@ exports.composeNode = composeNode; "use strict"; -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var Scalar = __nccwpck_require__(9338); var resolveBlockScalar = __nccwpck_require__(9485); var resolveFlowScalar = __nccwpck_require__(7578); @@ -30236,11 +31639,11 @@ function composeScalar(ctx, token, tagToken, onError) { ? findScalarTagByName(ctx.schema, value, tagName, tagToken, onError) : token.type === 'scalar' ? findScalarTagByTest(ctx, value, token, onError) - : ctx.schema[Node.SCALAR]; + : ctx.schema[identity.SCALAR]; let scalar; try { const res = tag.resolve(value, msg => onError(tagToken ?? token, 'TAG_RESOLVE_FAILED', msg), ctx.options); - scalar = Node.isScalar(res) ? res : new Scalar.Scalar(res); + scalar = identity.isScalar(res) ? res : new Scalar.Scalar(res); } catch (error) { const msg = error instanceof Error ? error.message : String(error); @@ -30261,7 +31664,7 @@ function composeScalar(ctx, token, tagToken, onError) { } function findScalarTagByName(schema, value, tagName, tagToken, onError) { if (tagName === '!') - return schema[Node.SCALAR]; // non-specific tag + return schema[identity.SCALAR]; // non-specific tag const matchWithTest = []; for (const tag of schema.tags) { if (!tag.collection && tag.tag === tagName) { @@ -30282,13 +31685,13 @@ function findScalarTagByName(schema, value, tagName, tagToken, onError) { return kt; } onError(tagToken, 'TAG_RESOLVE_FAILED', `Unresolved tag: ${tagName}`, tagName !== 'tag:yaml.org,2002:str'); - return schema[Node.SCALAR]; + return schema[identity.SCALAR]; } function findScalarTagByTest({ directives, schema }, value, token, onError) { - const tag = schema.tags.find(tag => tag.default && tag.test?.test(value)) || schema[Node.SCALAR]; + const tag = schema.tags.find(tag => tag.default && tag.test?.test(value)) || schema[identity.SCALAR]; if (schema.compat) { const compat = schema.compat.find(tag => tag.default && tag.test?.test(value)) ?? - schema[Node.SCALAR]; + schema[identity.SCALAR]; if (tag.tag !== compat.tag) { const ts = directives.tagString(tag.tag); const cs = directives.tagString(compat.tag); @@ -30313,7 +31716,7 @@ exports.composeScalar = composeScalar; var directives = __nccwpck_require__(5400); var Document = __nccwpck_require__(42); var errors = __nccwpck_require__(4236); -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var composeDoc = __nccwpck_require__(5050); var resolveEnd = __nccwpck_require__(1250); @@ -30393,9 +31796,9 @@ class Composer { else if (afterEmptyLine || doc.directives.docStart || !dc) { doc.commentBefore = comment; } - else if (Node.isCollection(dc) && !dc.flow && dc.items.length > 0) { + else if (identity.isCollection(dc) && !dc.flow && dc.items.length > 0) { let it = dc.items[0]; - if (Node.isPair(it)) + if (identity.isPair(it)) it = it.key; const cb = it.commentBefore; it.commentBefore = cb ? `${comment}\n${cb}` : comment; @@ -30547,8 +31950,9 @@ var utilFlowIndentCheck = __nccwpck_require__(3669); var utilMapIncludes = __nccwpck_require__(6899); const startColMsg = 'All mapping items must start at the same column'; -function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError) { - const map = new YAMLMap.YAMLMap(ctx.schema); +function resolveBlockMap({ composeNode, composeEmptyNode }, ctx, bm, onError, tag) { + const NodeClass = tag?.nodeClass ?? YAMLMap.YAMLMap; + const map = new NodeClass(ctx.schema); if (ctx.atRoot) ctx.atRoot = false; let offset = bm.offset; @@ -30867,8 +32271,9 @@ var YAMLSeq = __nccwpck_require__(5161); var resolveProps = __nccwpck_require__(6985); var utilFlowIndentCheck = __nccwpck_require__(3669); -function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError) { - const seq = new YAMLSeq.YAMLSeq(ctx.schema); +function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError, tag) { + const NodeClass = tag?.nodeClass ?? YAMLSeq.YAMLSeq; + const seq = new NodeClass(ctx.schema); if (ctx.atRoot) ctx.atRoot = false; let offset = bs.offset; @@ -30965,7 +32370,7 @@ exports.resolveEnd = resolveEnd; "use strict"; -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var Pair = __nccwpck_require__(246); var YAMLMap = __nccwpck_require__(6011); var YAMLSeq = __nccwpck_require__(5161); @@ -30976,12 +32381,11 @@ var utilMapIncludes = __nccwpck_require__(6899); const blockMsg = 'Block collections are not allowed within flow collections'; const isBlock = (token) => token && (token.type === 'block-map' || token.type === 'block-seq'); -function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onError) { +function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onError, tag) { const isMap = fc.start.source === '{'; const fcName = isMap ? 'flow map' : 'flow sequence'; - const coll = isMap - ? new YAMLMap.YAMLMap(ctx.schema) - : new YAMLSeq.YAMLSeq(ctx.schema); + const NodeClass = (tag?.nodeClass ?? (isMap ? YAMLMap.YAMLMap : YAMLSeq.YAMLSeq)); + const coll = new NodeClass(ctx.schema); coll.flow = true; const atRoot = ctx.atRoot; if (atRoot) @@ -31040,7 +32444,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr } if (prevItemComment) { let prev = coll.items[coll.items.length - 1]; - if (Node.isPair(prev)) + if (identity.isPair(prev)) prev = prev.value ?? prev.key; if (prev.comment) prev.comment += '\n' + prevItemComment; @@ -31658,7 +33062,7 @@ exports.flowIndentCheck = flowIndentCheck; "use strict"; -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); function mapIncludes(ctx, items, search) { const { uniqueKeys } = ctx.options; @@ -31667,8 +33071,8 @@ function mapIncludes(ctx, items, search) { const isEqual = typeof uniqueKeys === 'function' ? uniqueKeys : (a, b) => a === b || - (Node.isScalar(a) && - Node.isScalar(b) && + (identity.isScalar(a) && + identity.isScalar(b) && a.value === b.value && !(a.value === '<<' && ctx.schema.merge)); return items.some(pair => isEqual(pair.key, search)); @@ -31687,11 +33091,10 @@ exports.mapIncludes = mapIncludes; var Alias = __nccwpck_require__(5639); var Collection = __nccwpck_require__(3466); -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var Pair = __nccwpck_require__(246); var toJS = __nccwpck_require__(2463); var Schema = __nccwpck_require__(6831); -var stringify = __nccwpck_require__(8409); var stringifyDocument = __nccwpck_require__(5225); var anchors = __nccwpck_require__(8459); var applyReviver = __nccwpck_require__(3412); @@ -31708,7 +33111,7 @@ class Document { this.errors = []; /** Warnings encountered during parsing. */ this.warnings = []; - Object.defineProperty(this, Node.NODE_TYPE, { value: Node.DOC }); + Object.defineProperty(this, identity.NODE_TYPE, { value: identity.DOC }); let _replacer = null; if (typeof replacer === 'function' || Array.isArray(replacer)) { _replacer = replacer; @@ -31736,11 +33139,9 @@ class Document { else this.directives = new directives.Directives({ version }); this.setSchema(version, options); - if (value === undefined) - this.contents = null; - else { - this.contents = this.createNode(value, _replacer, options); - } + // @ts-expect-error We can't really know that this matches Contents. + this.contents = + value === undefined ? null : this.createNode(value, _replacer, options); } /** * Create a deep copy of this Document and its contents. @@ -31749,7 +33150,7 @@ class Document { */ clone() { const copy = Object.create(Document.prototype, { - [Node.NODE_TYPE]: { value: Node.DOC } + [identity.NODE_TYPE]: { value: identity.DOC } }); copy.commentBefore = this.commentBefore; copy.comment = this.comment; @@ -31759,7 +33160,8 @@ class Document { if (this.directives) copy.directives = this.directives.clone(); copy.schema = this.schema.clone(); - copy.contents = Node.isNode(this.contents) + // @ts-expect-error We can't really know that this matches Contents. + copy.contents = identity.isNode(this.contents) ? this.contents.clone(copy.schema) : this.contents; if (this.range) @@ -31825,7 +33227,7 @@ class Document { sourceObjects }; const node = createNode.createNode(value, tag, ctx); - if (flow && Node.isCollection(node)) + if (flow && identity.isCollection(node)) node.flow = true; setAnchors(); return node; @@ -31854,6 +33256,7 @@ class Document { if (Collection.isEmptyPath(path)) { if (this.contents == null) return false; + // @ts-expect-error Presumed impossible if Strict extends false this.contents = null; return true; } @@ -31867,7 +33270,7 @@ class Document { * `true` (collections are always returned intact). */ get(key, keepScalar) { - return Node.isCollection(this.contents) + return identity.isCollection(this.contents) ? this.contents.get(key, keepScalar) : undefined; } @@ -31878,10 +33281,10 @@ class Document { */ getIn(path, keepScalar) { if (Collection.isEmptyPath(path)) - return !keepScalar && Node.isScalar(this.contents) + return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents; - return Node.isCollection(this.contents) + return identity.isCollection(this.contents) ? this.contents.getIn(path, keepScalar) : undefined; } @@ -31889,7 +33292,7 @@ class Document { * Checks if the document includes a value with the key `key`. */ has(key) { - return Node.isCollection(this.contents) ? this.contents.has(key) : false; + return identity.isCollection(this.contents) ? this.contents.has(key) : false; } /** * Checks if the document includes a value at `path`. @@ -31897,7 +33300,7 @@ class Document { hasIn(path) { if (Collection.isEmptyPath(path)) return this.contents !== undefined; - return Node.isCollection(this.contents) ? this.contents.hasIn(path) : false; + return identity.isCollection(this.contents) ? this.contents.hasIn(path) : false; } /** * Sets a value in this document. For `!!set`, `value` needs to be a @@ -31905,6 +33308,7 @@ class Document { */ set(key, value) { if (this.contents == null) { + // @ts-expect-error We can't really know that this matches Contents. this.contents = Collection.collectionFromPath(this.schema, [key], value); } else if (assertCollection(this.contents)) { @@ -31916,9 +33320,12 @@ class Document { * boolean to add/remove the item from the set. */ setIn(path, value) { - if (Collection.isEmptyPath(path)) + if (Collection.isEmptyPath(path)) { + // @ts-expect-error We can't really know that this matches Contents. this.contents = value; + } else if (this.contents == null) { + // @ts-expect-error We can't really know that this matches Contents. this.contents = Collection.collectionFromPath(this.schema, Array.from(path), value); } else if (assertCollection(this.contents)) { @@ -31978,8 +33385,7 @@ class Document { keep: !json, mapAsMap: mapAsMap === true, mapKeyWarned: false, - maxAliasCount: typeof maxAliasCount === 'number' ? maxAliasCount : 100, - stringify: stringify.stringify + maxAliasCount: typeof maxAliasCount === 'number' ? maxAliasCount : 100 }; const res = toJS.toJS(this.contents, jsonArg ?? '', ctx); if (typeof onAnchor === 'function') @@ -32011,7 +33417,7 @@ class Document { } } function assertCollection(contents) { - if (Node.isCollection(contents)) + if (identity.isCollection(contents)) return true; throw new Error('Expected a YAML collection as document contents'); } @@ -32027,7 +33433,7 @@ exports.Document = Document; "use strict"; -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var visit = __nccwpck_require__(6796); /** @@ -32084,7 +33490,7 @@ function createNodeAnchors(doc, prefix) { const ref = sourceObjects.get(source); if (typeof ref === 'object' && ref.anchor && - (Node.isScalar(ref.node) || Node.isCollection(ref.node))) { + (identity.isScalar(ref.node) || identity.isCollection(ref.node))) { ref.node.anchor = ref.anchor; } else { @@ -32177,7 +33583,7 @@ exports.applyReviver = applyReviver; var Alias = __nccwpck_require__(5639); -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var Scalar = __nccwpck_require__(9338); const defaultTagPrefix = 'tag:yaml.org,2002:'; @@ -32192,12 +33598,12 @@ function findTagObject(value, tagName, tags) { return tags.find(t => t.identify?.(value) && !t.format); } function createNode(value, tagName, ctx) { - if (Node.isDocument(value)) + if (identity.isDocument(value)) value = value.contents; - if (Node.isNode(value)) + if (identity.isNode(value)) return value; - if (Node.isPair(value)) { - const map = ctx.schema[Node.MAP].createNode?.(ctx.schema, null, ctx); + if (identity.isPair(value)) { + const map = ctx.schema[identity.MAP].createNode?.(ctx.schema, null, ctx); map.items.push(value); return map; } @@ -32241,10 +33647,10 @@ function createNode(value, tagName, ctx) { } tagObj = value instanceof Map - ? schema[Node.MAP] + ? schema[identity.MAP] : Symbol.iterator in Object(value) - ? schema[Node.SEQ] - : schema[Node.MAP]; + ? schema[identity.SEQ] + : schema[identity.MAP]; } if (onTagObj) { onTagObj(tagObj); @@ -32252,9 +33658,13 @@ function createNode(value, tagName, ctx) { } const node = tagObj?.createNode ? tagObj.createNode(ctx.schema, value, ctx) - : new Scalar.Scalar(value); + : typeof tagObj?.nodeClass?.from === 'function' + ? tagObj.nodeClass.from(ctx.schema, value, ctx) + : new Scalar.Scalar(value); if (tagName) node.tag = tagName; + else if (!tagObj.default) + node.tag = tagObj.tag; if (ref) ref.node = node; return node; @@ -32271,7 +33681,7 @@ exports.createNode = createNode; "use strict"; -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var visit = __nccwpck_require__(6796); const escapeChars = { @@ -32417,10 +33827,10 @@ class Directives { : []; const tagEntries = Object.entries(this.tags); let tagNames; - if (doc && tagEntries.length > 0 && Node.isNode(doc.contents)) { + if (doc && tagEntries.length > 0 && identity.isNode(doc.contents)) { const tags = {}; visit.visit(doc.contents, (_key, node) => { - if (Node.isNode(node) && node.tag) + if (identity.isNode(node) && node.tag) tags[node.tag] = true; }); tagNames = Object.keys(tags); @@ -32499,7 +33909,7 @@ const prettifyError = (src, lc) => (error) => { let count = 1; const end = error.linePos[1]; if (end && end.line === line && end.col > col) { - count = Math.min(end.col - col, 80 - ci); + count = Math.max(1, Math.min(end.col - col, 80 - ci)); } const pointer = ' '.repeat(ci) + '^'.repeat(count); error.message += `:\n\n${lineStr}\n${pointer}\n`; @@ -32525,7 +33935,7 @@ var Document = __nccwpck_require__(42); var Schema = __nccwpck_require__(6831); var errors = __nccwpck_require__(4236); var Alias = __nccwpck_require__(5639); -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var Pair = __nccwpck_require__(246); var Scalar = __nccwpck_require__(9338); var YAMLMap = __nccwpck_require__(6011); @@ -32546,14 +33956,14 @@ exports.YAMLError = errors.YAMLError; exports.YAMLParseError = errors.YAMLParseError; exports.YAMLWarning = errors.YAMLWarning; exports.Alias = Alias.Alias; -exports.isAlias = Node.isAlias; -exports.isCollection = Node.isCollection; -exports.isDocument = Node.isDocument; -exports.isMap = Node.isMap; -exports.isNode = Node.isNode; -exports.isPair = Node.isPair; -exports.isScalar = Node.isScalar; -exports.isSeq = Node.isSeq; +exports.isAlias = identity.isAlias; +exports.isCollection = identity.isCollection; +exports.isDocument = identity.isDocument; +exports.isMap = identity.isMap; +exports.isNode = identity.isNode; +exports.isPair = identity.isPair; +exports.isScalar = identity.isScalar; +exports.isSeq = identity.isSeq; exports.Pair = Pair.Pair; exports.Scalar = Scalar.Scalar; exports.YAMLMap = YAMLMap.YAMLMap; @@ -32605,11 +34015,13 @@ exports.warn = warn; var anchors = __nccwpck_require__(8459); var visit = __nccwpck_require__(6796); +var identity = __nccwpck_require__(5589); var Node = __nccwpck_require__(1399); +var toJS = __nccwpck_require__(2463); class Alias extends Node.NodeBase { constructor(source) { - super(Node.ALIAS); + super(identity.ALIAS); this.source = source; Object.defineProperty(this, 'tag', { set() { @@ -32642,7 +34054,12 @@ class Alias extends Node.NodeBase { const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`; throw new ReferenceError(msg); } - const data = anchors.get(source); + let data = anchors.get(source); + if (!data) { + // Resolve anchors for Node.prototype.toJS() + toJS.toJS(source, null, ctx); + data = anchors.get(source); + } /* istanbul ignore if */ if (!data || data.res === undefined) { const msg = 'This should not happen: Alias anchor was not resolved?'; @@ -32674,12 +34091,12 @@ class Alias extends Node.NodeBase { } } function getAliasCount(doc, node, anchors) { - if (Node.isAlias(node)) { + if (identity.isAlias(node)) { const source = node.resolve(doc); const anchor = anchors && source && anchors.get(source); return anchor ? anchor.count * anchor.aliasCount : 0; } - else if (Node.isCollection(node)) { + else if (identity.isCollection(node)) { let count = 0; for (const item of node.items) { const c = getAliasCount(doc, item, anchors); @@ -32688,7 +34105,7 @@ function getAliasCount(doc, node, anchors) { } return count; } - else if (Node.isPair(node)) { + else if (identity.isPair(node)) { const kc = getAliasCount(doc, node.key, anchors); const vc = getAliasCount(doc, node.value, anchors); return Math.max(kc, vc); @@ -32708,6 +34125,7 @@ exports.Alias = Alias; var createNode = __nccwpck_require__(9652); +var identity = __nccwpck_require__(5589); var Node = __nccwpck_require__(1399); function collectionFromPath(schema, path, value) { @@ -32756,7 +34174,7 @@ class Collection extends Node.NodeBase { const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this)); if (schema) copy.schema = schema; - copy.items = copy.items.map(it => Node.isNode(it) || Node.isPair(it) ? it.clone(schema) : it); + copy.items = copy.items.map(it => identity.isNode(it) || identity.isPair(it) ? it.clone(schema) : it); if (this.range) copy.range = this.range.slice(); return copy; @@ -32772,7 +34190,7 @@ class Collection extends Node.NodeBase { else { const [key, ...rest] = path; const node = this.get(key, true); - if (Node.isCollection(node)) + if (identity.isCollection(node)) node.addIn(rest, value); else if (node === undefined && this.schema) this.set(key, collectionFromPath(this.schema, rest, value)); @@ -32789,7 +34207,7 @@ class Collection extends Node.NodeBase { if (rest.length === 0) return this.delete(key); const node = this.get(key, true); - if (Node.isCollection(node)) + if (identity.isCollection(node)) return node.deleteIn(rest); else throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`); @@ -32803,18 +34221,18 @@ class Collection extends Node.NodeBase { const [key, ...rest] = path; const node = this.get(key, true); if (rest.length === 0) - return !keepScalar && Node.isScalar(node) ? node.value : node; + return !keepScalar && identity.isScalar(node) ? node.value : node; else - return Node.isCollection(node) ? node.getIn(rest, keepScalar) : undefined; + return identity.isCollection(node) ? node.getIn(rest, keepScalar) : undefined; } hasAllNullValues(allowScalar) { return this.items.every(node => { - if (!Node.isPair(node)) + if (!identity.isPair(node)) return false; const n = node.value; return (n == null || (allowScalar && - Node.isScalar(n) && + identity.isScalar(n) && n.value == null && !n.commentBefore && !n.comment && @@ -32829,7 +34247,7 @@ class Collection extends Node.NodeBase { if (rest.length === 0) return this.has(key); const node = this.get(key, true); - return Node.isCollection(node) ? node.hasIn(rest) : false; + return identity.isCollection(node) ? node.hasIn(rest) : false; } /** * Sets a value in this collection. For `!!set`, `value` needs to be a @@ -32842,7 +34260,7 @@ class Collection extends Node.NodeBase { } else { const node = this.get(key, true); - if (Node.isCollection(node)) + if (identity.isCollection(node)) node.setIn(rest, value); else if (node === undefined && this.schema) this.set(key, collectionFromPath(this.schema, rest, value)); @@ -32861,48 +34279,18 @@ exports.isEmptyPath = isEmptyPath; /***/ }), /***/ 1399: -/***/ ((__unused_webpack_module, exports) => { +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; -const ALIAS = Symbol.for('yaml.alias'); -const DOC = Symbol.for('yaml.document'); -const MAP = Symbol.for('yaml.map'); -const PAIR = Symbol.for('yaml.pair'); -const SCALAR = Symbol.for('yaml.scalar'); -const SEQ = Symbol.for('yaml.seq'); -const NODE_TYPE = Symbol.for('yaml.node.type'); -const isAlias = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === ALIAS; -const isDocument = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === DOC; -const isMap = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === MAP; -const isPair = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === PAIR; -const isScalar = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === SCALAR; -const isSeq = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === SEQ; -function isCollection(node) { - if (node && typeof node === 'object') - switch (node[NODE_TYPE]) { - case MAP: - case SEQ: - return true; - } - return false; -} -function isNode(node) { - if (node && typeof node === 'object') - switch (node[NODE_TYPE]) { - case ALIAS: - case MAP: - case SCALAR: - case SEQ: - return true; - } - return false; -} -const hasAnchor = (node) => (isScalar(node) || isCollection(node)) && !!node.anchor; +var applyReviver = __nccwpck_require__(3412); +var identity = __nccwpck_require__(5589); +var toJS = __nccwpck_require__(2463); + class NodeBase { constructor(type) { - Object.defineProperty(this, NODE_TYPE, { value: type }); + Object.defineProperty(this, identity.NODE_TYPE, { value: type }); } /** Create a copy of this node. */ clone() { @@ -32911,25 +34299,29 @@ class NodeBase { copy.range = this.range.slice(); return copy; } + /** A plain JavaScript representation of this node. */ + toJS(doc, { mapAsMap, maxAliasCount, onAnchor, reviver } = {}) { + if (!identity.isDocument(doc)) + throw new TypeError('A document argument is required'); + const ctx = { + anchors: new Map(), + doc, + keep: true, + mapAsMap: mapAsMap === true, + mapKeyWarned: false, + maxAliasCount: typeof maxAliasCount === 'number' ? maxAliasCount : 100 + }; + const res = toJS.toJS(this, '', ctx); + if (typeof onAnchor === 'function') + for (const { count, res } of ctx.anchors.values()) + onAnchor(res, count); + return typeof reviver === 'function' + ? applyReviver.applyReviver(reviver, { '': res }, '', res) + : res; + } } -exports.ALIAS = ALIAS; -exports.DOC = DOC; -exports.MAP = MAP; -exports.NODE_TYPE = NODE_TYPE; exports.NodeBase = NodeBase; -exports.PAIR = PAIR; -exports.SCALAR = SCALAR; -exports.SEQ = SEQ; -exports.hasAnchor = hasAnchor; -exports.isAlias = isAlias; -exports.isCollection = isCollection; -exports.isDocument = isDocument; -exports.isMap = isMap; -exports.isNode = isNode; -exports.isPair = isPair; -exports.isScalar = isScalar; -exports.isSeq = isSeq; /***/ }), @@ -32943,7 +34335,7 @@ exports.isSeq = isSeq; var createNode = __nccwpck_require__(9652); var stringifyPair = __nccwpck_require__(4875); var addPairToJSMap = __nccwpck_require__(4676); -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); function createPair(key, value, ctx) { const k = createNode.createNode(key, undefined, ctx); @@ -32952,15 +34344,15 @@ function createPair(key, value, ctx) { } class Pair { constructor(key, value = null) { - Object.defineProperty(this, Node.NODE_TYPE, { value: Node.PAIR }); + Object.defineProperty(this, identity.NODE_TYPE, { value: identity.PAIR }); this.key = key; this.value = value; } clone(schema) { let { key, value } = this; - if (Node.isNode(key)) + if (identity.isNode(key)) key = key.clone(schema); - if (Node.isNode(value)) + if (identity.isNode(value)) value = value.clone(schema); return new Pair(key, value); } @@ -32987,13 +34379,14 @@ exports.createPair = createPair; "use strict"; +var identity = __nccwpck_require__(5589); var Node = __nccwpck_require__(1399); var toJS = __nccwpck_require__(2463); const isScalarValue = (value) => !value || (typeof value !== 'function' && typeof value !== 'object'); class Scalar extends Node.NodeBase { constructor(value) { - super(Node.SCALAR); + super(identity.SCALAR); this.value = value; } toJSON(arg, ctx) { @@ -33024,17 +34417,17 @@ exports.isScalarValue = isScalarValue; var stringifyCollection = __nccwpck_require__(2466); var addPairToJSMap = __nccwpck_require__(4676); var Collection = __nccwpck_require__(3466); -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var Pair = __nccwpck_require__(246); var Scalar = __nccwpck_require__(9338); function findPair(items, key) { - const k = Node.isScalar(key) ? key.value : key; + const k = identity.isScalar(key) ? key.value : key; for (const it of items) { - if (Node.isPair(it)) { + if (identity.isPair(it)) { if (it.key === key || it.key === k) return it; - if (Node.isScalar(it.key) && it.key.value === k) + if (identity.isScalar(it.key) && it.key.value === k) return it; } } @@ -33045,9 +34438,37 @@ class YAMLMap extends Collection.Collection { return 'tag:yaml.org,2002:map'; } constructor(schema) { - super(Node.MAP, schema); + super(identity.MAP, schema); this.items = []; } + /** + * A generic collection parsing method that can be extended + * to other node classes that inherit from YAMLMap + */ + static from(schema, obj, ctx) { + const { keepUndefined, replacer } = ctx; + const map = new this(schema); + const add = (key, value) => { + if (typeof replacer === 'function') + value = replacer.call(obj, key, value); + else if (Array.isArray(replacer) && !replacer.includes(key)) + return; + if (value !== undefined || keepUndefined) + map.items.push(Pair.createPair(key, value, ctx)); + }; + if (obj instanceof Map) { + for (const [key, value] of obj) + add(key, value); + } + else if (obj && typeof obj === 'object') { + for (const key of Object.keys(obj)) + add(key, obj[key]); + } + if (typeof schema.sortMapEntries === 'function') { + map.items.sort(schema.sortMapEntries); + } + return map; + } /** * Adds a value to the collection. * @@ -33056,7 +34477,7 @@ class YAMLMap extends Collection.Collection { */ add(pair, overwrite) { let _pair; - if (Node.isPair(pair)) + if (identity.isPair(pair)) _pair = pair; else if (!pair || typeof pair !== 'object' || !('key' in pair)) { // In TypeScript, this never happens. @@ -33070,7 +34491,7 @@ class YAMLMap extends Collection.Collection { if (!overwrite) throw new Error(`Key ${_pair.key} already set`); // For scalars, keep the old node & its comments and anchors - if (Node.isScalar(prev.value) && Scalar.isScalarValue(_pair.value)) + if (identity.isScalar(prev.value) && Scalar.isScalarValue(_pair.value)) prev.value.value = _pair.value; else prev.value = _pair.value; @@ -33096,7 +34517,7 @@ class YAMLMap extends Collection.Collection { get(key, keepScalar) { const it = findPair(this.items, key); const node = it?.value; - return (!keepScalar && Node.isScalar(node) ? node.value : node) ?? undefined; + return (!keepScalar && identity.isScalar(node) ? node.value : node) ?? undefined; } has(key) { return !!findPair(this.items, key); @@ -33121,7 +34542,7 @@ class YAMLMap extends Collection.Collection { if (!ctx) return JSON.stringify(this); for (const item of this.items) { - if (!Node.isPair(item)) + if (!identity.isPair(item)) throw new Error(`Map items must all be pairs; found ${JSON.stringify(item)} instead`); } if (!ctx.allNullValues && this.hasAllNullValues(false)) @@ -33148,9 +34569,10 @@ exports.findPair = findPair; "use strict"; +var createNode = __nccwpck_require__(9652); var stringifyCollection = __nccwpck_require__(2466); var Collection = __nccwpck_require__(3466); -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var Scalar = __nccwpck_require__(9338); var toJS = __nccwpck_require__(2463); @@ -33159,7 +34581,7 @@ class YAMLSeq extends Collection.Collection { return 'tag:yaml.org,2002:seq'; } constructor(schema) { - super(Node.SEQ, schema); + super(identity.SEQ, schema); this.items = []; } add(value) { @@ -33185,7 +34607,7 @@ class YAMLSeq extends Collection.Collection { if (typeof idx !== 'number') return undefined; const it = this.items[idx]; - return !keepScalar && Node.isScalar(it) ? it.value : it; + return !keepScalar && identity.isScalar(it) ? it.value : it; } /** * Checks if the collection includes a value with the key `key`. @@ -33209,7 +34631,7 @@ class YAMLSeq extends Collection.Collection { if (typeof idx !== 'number') throw new Error(`Expected a valid index, not ${key}.`); const prev = this.items[idx]; - if (Node.isScalar(prev) && Scalar.isScalarValue(value)) + if (identity.isScalar(prev) && Scalar.isScalarValue(value)) prev.value = value; else this.items[idx] = value; @@ -33234,9 +34656,24 @@ class YAMLSeq extends Collection.Collection { onComment }); } + static from(schema, obj, ctx) { + const { replacer } = ctx; + const seq = new this(schema); + if (obj && Symbol.iterator in Object(obj)) { + let i = 0; + for (let it of obj) { + if (typeof replacer === 'function') { + const key = obj instanceof Set ? it : String(i++); + it = replacer.call(obj, key, it); + } + seq.items.push(createNode.createNode(it, undefined, ctx)); + } + } + return seq; + } } function asItemIndex(key) { - let idx = Node.isScalar(key) ? key.value : key; + let idx = identity.isScalar(key) ? key.value : key; if (idx && typeof idx === 'string') idx = Number(idx); return typeof idx === 'number' && Number.isInteger(idx) && idx >= 0 @@ -33257,15 +34694,15 @@ exports.YAMLSeq = YAMLSeq; var log = __nccwpck_require__(6909); var stringify = __nccwpck_require__(8409); -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var Scalar = __nccwpck_require__(9338); var toJS = __nccwpck_require__(2463); const MERGE_KEY = '<<'; function addPairToJSMap(ctx, map, { key, value }) { if (ctx?.doc.schema.merge && isMergeKey(key)) { - value = Node.isAlias(value) ? value.resolve(ctx.doc) : value; - if (Node.isSeq(value)) + value = identity.isAlias(value) ? value.resolve(ctx.doc) : value; + if (identity.isSeq(value)) for (const it of value.items) mergeToJSMap(ctx, map, it); else if (Array.isArray(value)) @@ -33299,7 +34736,7 @@ function addPairToJSMap(ctx, map, { key, value }) { return map; } const isMergeKey = (key) => key === MERGE_KEY || - (Node.isScalar(key) && + (identity.isScalar(key) && key.value === MERGE_KEY && (!key.type || key.type === Scalar.Scalar.PLAIN)); // If the value associated with a merge key is a single mapping node, each of @@ -33310,8 +34747,8 @@ const isMergeKey = (key) => key === MERGE_KEY || // Keys in mapping nodes earlier in the sequence override keys specified in // later mapping nodes. -- http://yaml.org/type/merge.html function mergeToJSMap(ctx, map, value) { - const source = ctx && Node.isAlias(value) ? value.resolve(ctx.doc) : value; - if (!Node.isMap(source)) + const source = ctx && identity.isAlias(value) ? value.resolve(ctx.doc) : value; + if (!identity.isMap(source)) throw new Error('Merge sources must be maps or map aliases'); const srcMap = source.toJSON(null, ctx, Map); for (const [key, value] of srcMap) { @@ -33338,7 +34775,7 @@ function stringifyKey(key, jsKey, ctx) { return ''; if (typeof jsKey !== 'object') return String(jsKey); - if (Node.isNode(key) && ctx && ctx.doc) { + if (identity.isNode(key) && ctx && ctx.doc) { const strCtx = stringify.createStringifyContext(ctx.doc, {}); strCtx.anchors = new Set(); for (const node of ctx.anchors.keys()) @@ -33361,6 +34798,67 @@ function stringifyKey(key, jsKey, ctx) { exports.addPairToJSMap = addPairToJSMap; +/***/ }), + +/***/ 5589: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +const ALIAS = Symbol.for('yaml.alias'); +const DOC = Symbol.for('yaml.document'); +const MAP = Symbol.for('yaml.map'); +const PAIR = Symbol.for('yaml.pair'); +const SCALAR = Symbol.for('yaml.scalar'); +const SEQ = Symbol.for('yaml.seq'); +const NODE_TYPE = Symbol.for('yaml.node.type'); +const isAlias = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === ALIAS; +const isDocument = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === DOC; +const isMap = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === MAP; +const isPair = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === PAIR; +const isScalar = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === SCALAR; +const isSeq = (node) => !!node && typeof node === 'object' && node[NODE_TYPE] === SEQ; +function isCollection(node) { + if (node && typeof node === 'object') + switch (node[NODE_TYPE]) { + case MAP: + case SEQ: + return true; + } + return false; +} +function isNode(node) { + if (node && typeof node === 'object') + switch (node[NODE_TYPE]) { + case ALIAS: + case MAP: + case SCALAR: + case SEQ: + return true; + } + return false; +} +const hasAnchor = (node) => (isScalar(node) || isCollection(node)) && !!node.anchor; + +exports.ALIAS = ALIAS; +exports.DOC = DOC; +exports.MAP = MAP; +exports.NODE_TYPE = NODE_TYPE; +exports.PAIR = PAIR; +exports.SCALAR = SCALAR; +exports.SEQ = SEQ; +exports.hasAnchor = hasAnchor; +exports.isAlias = isAlias; +exports.isCollection = isCollection; +exports.isDocument = isDocument; +exports.isMap = isMap; +exports.isNode = isNode; +exports.isPair = isPair; +exports.isScalar = isScalar; +exports.isSeq = isSeq; + + /***/ }), /***/ 2463: @@ -33369,7 +34867,7 @@ exports.addPairToJSMap = addPairToJSMap; "use strict"; -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); /** * Recursively convert any node or its contents to native JavaScript @@ -33387,7 +34885,7 @@ function toJS(value, arg, ctx) { return value.map((v, i) => toJS(v, String(i), ctx)); if (value && typeof value.toJSON === 'function') { // eslint-disable-next-line @typescript-eslint/no-unsafe-call - if (!ctx || !Node.hasAnchor(value)) + if (!ctx || !identity.hasAnchor(value)) return value.toJSON(arg, ctx); const data = { aliasCount: 0, count: 1, res: undefined }; ctx.anchors.set(value, data); @@ -35774,7 +37272,7 @@ exports.stringify = stringify; "use strict"; -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var map = __nccwpck_require__(83); var seq = __nccwpck_require__(1693); var string = __nccwpck_require__(2201); @@ -35793,9 +37291,9 @@ class Schema { this.knownTags = resolveKnownTags ? tags.coreKnownTags : {}; this.tags = tags.getTags(customTags, this.name); this.toStringOptions = toStringDefaults ?? null; - Object.defineProperty(this, Node.MAP, { value: map.map }); - Object.defineProperty(this, Node.SCALAR, { value: string.string }); - Object.defineProperty(this, Node.SEQ, { value: seq.seq }); + Object.defineProperty(this, identity.MAP, { value: map.map }); + Object.defineProperty(this, identity.SCALAR, { value: string.string }); + Object.defineProperty(this, identity.SEQ, { value: seq.seq }); // Used by createMap() this.sortMapEntries = typeof sortMapEntries === 'function' @@ -35822,45 +37320,20 @@ exports.Schema = Schema; "use strict"; -var Node = __nccwpck_require__(1399); -var Pair = __nccwpck_require__(246); +var identity = __nccwpck_require__(5589); var YAMLMap = __nccwpck_require__(6011); -function createMap(schema, obj, ctx) { - const { keepUndefined, replacer } = ctx; - const map = new YAMLMap.YAMLMap(schema); - const add = (key, value) => { - if (typeof replacer === 'function') - value = replacer.call(obj, key, value); - else if (Array.isArray(replacer) && !replacer.includes(key)) - return; - if (value !== undefined || keepUndefined) - map.items.push(Pair.createPair(key, value, ctx)); - }; - if (obj instanceof Map) { - for (const [key, value] of obj) - add(key, value); - } - else if (obj && typeof obj === 'object') { - for (const key of Object.keys(obj)) - add(key, obj[key]); - } - if (typeof schema.sortMapEntries === 'function') { - map.items.sort(schema.sortMapEntries); - } - return map; -} const map = { collection: 'map', - createNode: createMap, default: true, nodeClass: YAMLMap.YAMLMap, tag: 'tag:yaml.org,2002:map', resolve(map, onError) { - if (!Node.isMap(map)) + if (!identity.isMap(map)) onError('Expected a mapping for this tag'); return map; - } + }, + createNode: (schema, obj, ctx) => YAMLMap.YAMLMap.from(schema, obj, ctx) }; exports.map = map; @@ -35899,36 +37372,20 @@ exports.nullTag = nullTag; "use strict"; -var createNode = __nccwpck_require__(9652); -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var YAMLSeq = __nccwpck_require__(5161); -function createSeq(schema, obj, ctx) { - const { replacer } = ctx; - const seq = new YAMLSeq.YAMLSeq(schema); - if (obj && Symbol.iterator in Object(obj)) { - let i = 0; - for (let it of obj) { - if (typeof replacer === 'function') { - const key = obj instanceof Set ? it : String(i++); - it = replacer.call(obj, key, it); - } - seq.items.push(createNode.createNode(it, undefined, ctx)); - } - } - return seq; -} const seq = { collection: 'seq', - createNode: createSeq, default: true, nodeClass: YAMLSeq.YAMLSeq, tag: 'tag:yaml.org,2002:seq', resolve(seq, onError) { - if (!Node.isSeq(seq)) + if (!identity.isSeq(seq)) onError('Expected a sequence for this tag'); return seq; - } + }, + createNode: (schema, obj, ctx) => YAMLSeq.YAMLSeq.from(schema, obj, ctx) }; exports.seq = seq; @@ -36554,10 +38011,10 @@ exports.intOct = intOct; "use strict"; -var YAMLSeq = __nccwpck_require__(5161); +var identity = __nccwpck_require__(5589); var toJS = __nccwpck_require__(2463); -var Node = __nccwpck_require__(1399); var YAMLMap = __nccwpck_require__(6011); +var YAMLSeq = __nccwpck_require__(5161); var pairs = __nccwpck_require__(9841); class YAMLOMap extends YAMLSeq.YAMLSeq { @@ -36582,7 +38039,7 @@ class YAMLOMap extends YAMLSeq.YAMLSeq { ctx.onCreate(map); for (const pair of this.items) { let key, value; - if (Node.isPair(pair)) { + if (identity.isPair(pair)) { key = toJS.toJS(pair.key, '', ctx); value = toJS.toJS(pair.value, key, ctx); } @@ -36595,6 +38052,12 @@ class YAMLOMap extends YAMLSeq.YAMLSeq { } return map; } + static from(schema, iterable, ctx) { + const pairs$1 = pairs.createPairs(schema, iterable, ctx); + const omap = new this(); + omap.items = pairs$1.items; + return omap; + } } YAMLOMap.tag = 'tag:yaml.org,2002:omap'; const omap = { @@ -36607,7 +38070,7 @@ const omap = { const pairs$1 = pairs.resolvePairs(seq, onError); const seenKeys = []; for (const { key } of pairs$1.items) { - if (Node.isScalar(key)) { + if (identity.isScalar(key)) { if (seenKeys.includes(key.value)) { onError(`Ordered maps must not include duplicate keys: ${key.value}`); } @@ -36618,12 +38081,7 @@ const omap = { } return Object.assign(new YAMLOMap(), pairs$1); }, - createNode(schema, iterable, ctx) { - const pairs$1 = pairs.createPairs(schema, iterable, ctx); - const omap = new YAMLOMap(); - omap.items = pairs$1.items; - return omap; - } + createNode: (schema, iterable, ctx) => YAMLOMap.from(schema, iterable, ctx) }; exports.YAMLOMap = YAMLOMap; @@ -36638,18 +38096,18 @@ exports.omap = omap; "use strict"; -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var Pair = __nccwpck_require__(246); var Scalar = __nccwpck_require__(9338); var YAMLSeq = __nccwpck_require__(5161); function resolvePairs(seq, onError) { - if (Node.isSeq(seq)) { + if (identity.isSeq(seq)) { for (let i = 0; i < seq.items.length; ++i) { let item = seq.items[i]; - if (Node.isPair(item)) + if (identity.isPair(item)) continue; - else if (Node.isMap(item)) { + else if (identity.isMap(item)) { if (item.items.length > 1) onError('Each pair must have its own sequence indicator'); const pair = item.items[0] || new Pair.Pair(new Scalar.Scalar(null)); @@ -36665,7 +38123,7 @@ function resolvePairs(seq, onError) { } item = pair; } - seq.items[i] = Node.isPair(item) ? item : new Pair.Pair(item); + seq.items[i] = identity.isPair(item) ? item : new Pair.Pair(item); } } else @@ -36774,7 +38232,7 @@ exports.schema = schema; "use strict"; -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var Pair = __nccwpck_require__(246); var YAMLMap = __nccwpck_require__(6011); @@ -36785,7 +38243,7 @@ class YAMLSet extends YAMLMap.YAMLMap { } add(key) { let pair; - if (Node.isPair(key)) + if (identity.isPair(key)) pair = key; else if (key && typeof key === 'object' && @@ -36805,8 +38263,8 @@ class YAMLSet extends YAMLMap.YAMLMap { */ get(key, keepPair) { const pair = YAMLMap.findPair(this.items, key); - return !keepPair && Node.isPair(pair) - ? Node.isScalar(pair.key) + return !keepPair && identity.isPair(pair) + ? identity.isScalar(pair.key) ? pair.key.value : pair.key : pair; @@ -36833,6 +38291,17 @@ class YAMLSet extends YAMLMap.YAMLMap { else throw new Error('Set items must all have null values'); } + static from(schema, iterable, ctx) { + const { replacer } = ctx; + const set = new this(schema); + if (iterable && Symbol.iterator in Object(iterable)) + for (let value of iterable) { + if (typeof replacer === 'function') + value = replacer.call(iterable, value, value); + set.items.push(Pair.createPair(value, null, ctx)); + } + return set; + } } YAMLSet.tag = 'tag:yaml.org,2002:set'; const set = { @@ -36841,8 +38310,9 @@ const set = { nodeClass: YAMLSet, default: false, tag: 'tag:yaml.org,2002:set', + createNode: (schema, iterable, ctx) => YAMLSet.from(schema, iterable, ctx), resolve(map, onError) { - if (Node.isMap(map)) { + if (identity.isMap(map)) { if (map.hasAllNullValues(true)) return Object.assign(new YAMLSet(), map); else @@ -36851,17 +38321,6 @@ const set = { else onError('Expected a mapping for this tag'); return map; - }, - createNode(schema, iterable, ctx) { - const { replacer } = ctx; - const set = new YAMLSet(schema); - if (iterable && Symbol.iterator in Object(iterable)) - for (let value of iterable) { - if (typeof replacer === 'function') - value = replacer.call(iterable, value, value); - set.items.push(Pair.createPair(value, null, ctx)); - } - return set; } }; @@ -36922,7 +38381,7 @@ function stringifySexagesimal(node) { } return (sign + parts - .map(n => (n < 10 ? '0' + String(n) : String(n))) + .map(n => String(n).padStart(2, '0')) .join(':') .replace(/000000\d*$/, '') // % 60 may introduce error ); @@ -37139,7 +38598,7 @@ exports.foldFlowLines = foldFlowLines; var anchors = __nccwpck_require__(8459); -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var stringifyComment = __nccwpck_require__(5182); var stringifyString = __nccwpck_require__(6226); @@ -37192,7 +38651,7 @@ function getTagObject(tags, item) { } let tagObj = undefined; let obj; - if (Node.isScalar(item)) { + if (identity.isScalar(item)) { obj = item.value; const match = tags.filter(t => t.identify?.(obj)); tagObj = @@ -37213,7 +38672,7 @@ function stringifyProps(node, tagObj, { anchors: anchors$1, doc }) { if (!doc.directives) return ''; const props = []; - const anchor = (Node.isScalar(node) || Node.isCollection(node)) && node.anchor; + const anchor = (identity.isScalar(node) || identity.isCollection(node)) && node.anchor; if (anchor && anchors.anchorIsValid(anchor)) { anchors$1.add(anchor); props.push(`&${anchor}`); @@ -37224,9 +38683,9 @@ function stringifyProps(node, tagObj, { anchors: anchors$1, doc }) { return props.join(' '); } function stringify(item, ctx, onComment, onChompKeep) { - if (Node.isPair(item)) + if (identity.isPair(item)) return item.toString(ctx, onComment, onChompKeep); - if (Node.isAlias(item)) { + if (identity.isAlias(item)) { if (ctx.doc.directives) return item.toString(ctx); if (ctx.resolvedAliases?.has(item)) { @@ -37241,7 +38700,7 @@ function stringify(item, ctx, onComment, onChompKeep) { } } let tagObj = undefined; - const node = Node.isNode(item) + const node = identity.isNode(item) ? item : ctx.doc.createNode(item, { onTagObj: o => (tagObj = o) }); if (!tagObj) @@ -37251,12 +38710,12 @@ function stringify(item, ctx, onComment, onChompKeep) { ctx.indentAtStart = (ctx.indentAtStart ?? 0) + props.length + 1; const str = typeof tagObj.stringify === 'function' ? tagObj.stringify(node, ctx, onComment, onChompKeep) - : Node.isScalar(node) + : identity.isScalar(node) ? stringifyString.stringifyString(node, ctx, onComment, onChompKeep) : node.toString(ctx, onComment, onChompKeep); if (!props) return str; - return Node.isScalar(node) || str[0] === '{' || str[0] === '[' + return identity.isScalar(node) || str[0] === '{' || str[0] === '[' ? `${props} ${str}` : `${props}\n${ctx.indent}${str}`; } @@ -37274,7 +38733,7 @@ exports.stringify = stringify; var Collection = __nccwpck_require__(3466); -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var stringify = __nccwpck_require__(8409); var stringifyComment = __nccwpck_require__(5182); @@ -37291,15 +38750,15 @@ function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, fl for (let i = 0; i < items.length; ++i) { const item = items[i]; let comment = null; - if (Node.isNode(item)) { + if (identity.isNode(item)) { if (!chompKeep && item.spaceBefore) lines.push(''); addCommentBefore(ctx, lines, item.commentBefore, chompKeep); if (item.comment) comment = item.comment; } - else if (Node.isPair(item)) { - const ik = Node.isNode(item.key) ? item.key : null; + else if (identity.isPair(item)) { + const ik = identity.isNode(item.key) ? item.key : null; if (ik) { if (!chompKeep && ik.spaceBefore) lines.push(''); @@ -37348,15 +38807,15 @@ function stringifyFlowCollection({ comment, items }, ctx, { flowChars, itemInden for (let i = 0; i < items.length; ++i) { const item = items[i]; let comment = null; - if (Node.isNode(item)) { + if (identity.isNode(item)) { if (item.spaceBefore) lines.push(''); addCommentBefore(ctx, lines, item.commentBefore, false); if (item.comment) comment = item.comment; } - else if (Node.isPair(item)) { - const ik = Node.isNode(item.key) ? item.key : null; + else if (identity.isPair(item)) { + const ik = identity.isNode(item.key) ? item.key : null; if (ik) { if (ik.spaceBefore) lines.push(''); @@ -37364,7 +38823,7 @@ function stringifyFlowCollection({ comment, items }, ctx, { flowChars, itemInden if (ik.comment) reqNewline = true; } - const iv = Node.isNode(item.value) ? item.value : null; + const iv = identity.isNode(item.value) ? item.value : null; if (iv) { if (iv.comment) comment = iv.comment; @@ -37408,7 +38867,7 @@ function stringifyFlowCollection({ comment, items }, ctx, { flowChars, itemInden } } if (comment) { - str += stringifyComment.lineComment(str, commentString(comment), indent); + str += stringifyComment.lineComment(str, indent, commentString(comment)); if (onComment) onComment(); } @@ -37466,7 +38925,7 @@ exports.stringifyComment = stringifyComment; "use strict"; -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var stringify = __nccwpck_require__(8409); var stringifyComment = __nccwpck_require__(5182); @@ -37495,7 +38954,7 @@ function stringifyDocument(doc, options) { let chompKeep = false; let contentComment = null; if (doc.contents) { - if (Node.isNode(doc.contents)) { + if (identity.isNode(doc.contents)) { if (doc.contents.spaceBefore && hasDirectives) lines.push(''); if (doc.contents.commentBefore) { @@ -37595,19 +39054,19 @@ exports.stringifyNumber = stringifyNumber; "use strict"; -var Node = __nccwpck_require__(1399); +var identity = __nccwpck_require__(5589); var Scalar = __nccwpck_require__(9338); var stringify = __nccwpck_require__(8409); var stringifyComment = __nccwpck_require__(5182); function stringifyPair({ key, value }, ctx, onComment, onChompKeep) { const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx; - let keyComment = (Node.isNode(key) && key.comment) || null; + let keyComment = (identity.isNode(key) && key.comment) || null; if (simpleKeys) { if (keyComment) { throw new Error('With simple keys, key nodes cannot have comments'); } - if (Node.isCollection(key)) { + if (identity.isCollection(key)) { const msg = 'With simple keys, collection cannot be used as a key value'; throw new Error(msg); } @@ -37615,8 +39074,8 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) { let explicitKey = !simpleKeys && (!key || (keyComment && value == null && !ctx.inFlow) || - Node.isCollection(key) || - (Node.isScalar(key) + identity.isCollection(key) || + (identity.isScalar(key) ? key.type === Scalar.Scalar.BLOCK_FOLDED || key.type === Scalar.Scalar.BLOCK_LITERAL : typeof key === 'object')); ctx = Object.assign({}, ctx, { @@ -37661,7 +39120,7 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) { str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment)); } let vsb, vcb, valueComment; - if (Node.isNode(value)) { + if (identity.isNode(value)) { vsb = !!value.spaceBefore; vcb = value.commentBefore; valueComment = value.comment; @@ -37674,14 +39133,14 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) { value = doc.createNode(value); } ctx.implicitKey = false; - if (!explicitKey && !keyComment && Node.isScalar(value)) + if (!explicitKey && !keyComment && identity.isScalar(value)) ctx.indentAtStart = str.length + 1; chompKeep = false; if (!indentSeq && indentStep.length >= 2 && !ctx.inFlow && !explicitKey && - Node.isSeq(value) && + identity.isSeq(value) && !value.flow && !value.tag && !value.anchor) { @@ -37705,7 +39164,7 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) { ws += `\n${ctx.indent}`; } } - else if (!explicitKey && Node.isCollection(value)) { + else if (!explicitKey && identity.isCollection(value)) { const vs0 = valueStr[0]; const nl0 = valueStr.indexOf('\n'); const hasNewline = nl0 !== -1; @@ -37758,8 +39217,8 @@ exports.stringifyPair = stringifyPair; var Scalar = __nccwpck_require__(9338); var foldFlowLines = __nccwpck_require__(2889); -const getFoldOptions = (ctx) => ({ - indentAtStart: ctx.indentAtStart, +const getFoldOptions = (ctx, isBlock) => ({ + indentAtStart: isBlock ? ctx.indent.length : ctx.indentAtStart, lineWidth: ctx.options.lineWidth, minContentWidth: ctx.options.minContentWidth }); @@ -37872,7 +39331,7 @@ function doubleQuotedString(value, ctx) { str = start ? str + json.slice(start) : json; return implicitKey ? str - : foldFlowLines.foldFlowLines(str, indent, foldFlowLines.FOLD_QUOTED, getFoldOptions(ctx)); + : foldFlowLines.foldFlowLines(str, indent, foldFlowLines.FOLD_QUOTED, getFoldOptions(ctx, false)); } function singleQuotedString(value, ctx) { if (ctx.options.singleQuote === false || @@ -37884,7 +39343,7 @@ function singleQuotedString(value, ctx) { const res = "'" + value.replace(/'/g, "''").replace(/\n+/g, `$&\n${indent}`) + "'"; return ctx.implicitKey ? res - : foldFlowLines.foldFlowLines(res, indent, foldFlowLines.FOLD_FLOW, getFoldOptions(ctx)); + : foldFlowLines.foldFlowLines(res, indent, foldFlowLines.FOLD_FLOW, getFoldOptions(ctx, false)); } function quotedString(value, ctx) { const { singleQuote } = ctx.options; @@ -37903,6 +39362,15 @@ function quotedString(value, ctx) { } return qs(value, ctx); } +// The negative lookbehind avoids a polynomial search, +// but isn't supported yet on Safari: https://caniuse.com/js-regexp-lookbehind +let blockEndNewlines; +try { + blockEndNewlines = new RegExp('(^|(? + **/ + +const core = require('@actions/core') +const _ = require('lodash') +const { + expandObjectInputs, + forceArray, + forceObject, +} = require('./input-expander') + +/** + * This lets us use the same mapping function for multiple versions. + * @param {string[]} versions - The versions to use. + * @param {function} mapper - The mapping function. + * @returns {object} - The mapping object. + * @private + * @function + **/ +const useSharedMappings = (versions, mapper) => + Object.assign(...versions.map((x) => ({ [x]: mapper }))) + +/** + * This function takes an input name and a mapper function and returns a function which maps the input value to the registry document value. + * @param {string} input - The input name. + * @param {function} func - The mapping function. + * @returns {function} - The mapping function. + * @private + * @function + **/ +const mapToUsing = (input, func) => (value) => func(input, value) + +/** + * This function takes an input and a value and returns an object with the input as the key and the value as the value. + * @param {string} input - The input name. + * @param {any} value - The value. + * @returns {object} - The mapped object. + * @private + * @function + **/ +const passThru = (input, value) => ({ [input]: value }) + +/** + * This function takes an input and a YAML string and returns an object with the input as the key and the expanded YAML as the value. + * @param {string} input - The input name. + * @param {string} str - The YAML string. + * @returns {object} - The mapped object. + * @private + * @function + * @see expandObjectInputs + **/ +const simpleYamlParse = (input, str) => ({ [input]: expandObjectInputs(str) }) + +/** + * This function takes an input and a YAML string and returns an object with the input as the key and the expanded YAML as the value. The value of the object returned will _always_ be an array. + * @param {string} input - The input name. + * @param {string} str - The YAML string. + * @returns {object} - The mapped object. + * @private + * @function + * @see expandObjectInputs + * @see forceArray + **/ +const arrayYamlParse = (input, str) => ({ + [input]: forceArray(expandObjectInputs(str)), +}) + +const objectYamlParse = (input, str) => ({ + [input]: forceObject(expandObjectInputs(str)), +}) + +const versionCompatibilityError = + (field, chosenVersion, validVersions) => (_input) => + core.setFailed( + `Sorry, but the «${field}» field is not avaiable in version ${chosenVersion} of the Datadog Service Catalog schema; this field is only available in version(s): ${validVersions.join( + ',', + )}`, + ) + +/** + * This is the list of mappings which tracks which fields map to different versions in different ways. + * - Keyed by the GitHub Actions input name (action.yml) + * - Values are objects keyed with version tags + * - Values of those objects are the function which maps the input value to the registry document value. + * TODO: Add warnings for when folks try to use the wrong schema versions. + **/ +const mappings = { + 'schema-version': useSharedMappings( + ['v2', 'v2.1'], + mapToUsing('schema-version', (input, value) => ({ + 'schema-version': value ?? 'v2', + })), + ), + + 'service-name': useSharedMappings( + ['v2', 'v2.1'], + mapToUsing('dd-service', passThru), + ), + + team: useSharedMappings(['v2', 'v2.1'], mapToUsing('team', passThru)), + + contacts: useSharedMappings( + ['v2', 'v2.1'], + mapToUsing('contacts', arrayYamlParse), + ), + + // This tags setup is a little hairy, but the biggest thing + // to keep in mind is that we want a list of strings, made up + // of colon-separated values. Mercifully, this is the same + // for both v2 and v2.1. + tags: useSharedMappings(['v2', 'v2.1'], (input) => ({ + tags: forceArray(expandObjectInputs(input)).map((entry) => + _.isPlainObject(entry) + ? _.join( + _.head(_.toPairs(entry)).map((x) => + // This check is so that we trim strings, but don't break + // numbers or boolean values. + typeof x === 'string' ? x.trim() : x, + ), + ':', + ) + : entry, + ), + })), + + links: { + v2: (input) => ({ + links: forceArray(expandObjectInputs(input)).map((x) => + // v2 doesn't have a provider field + _.omit(x, ['provider']), + ), + }), + 'v2.1': (input) => ({ links: forceArray(expandObjectInputs(input)) }), + }, + + integrations: useSharedMappings( + ['v2', 'v2.1'], + mapToUsing('integrations', objectYamlParse), + ), + + docs: { + v2: mapToUsing('docs', arrayYamlParse), + 'v2.1': versionCompatibilityError('docs', 'v2.1', ['v2']), + }, + + repos: { + v2: mapToUsing('repos', arrayYamlParse), + 'v2.1': versionCompatibilityError('repos', 'v2.1', ['v2']), + }, + + application: { + v2: versionCompatibilityError('application', 'v2', ['v2.1']), + 'v2.1': mapToUsing('application', passThru), + }, + + description: { + v2: versionCompatibilityError('description', 'v2', ['v2.1']), + 'v2.1': mapToUsing('description', passThru), + }, + + tier: { + v2: versionCompatibilityError('tier', 'v2', ['v2.1']), + 'v2.1': mapToUsing('tier', passThru), + }, + + lifecycle: { + v2: versionCompatibilityError('lifecycle', 'v2', ['v2.1']), + 'v2.1': mapToUsing('lifecycle', passThru), + }, +} +Object.freeze(mappings) + +/** + * This is the list of fields which are part of the Datadog schema, in one version or another. + * @type {string[]} + **/ +const schemaFields = _.keys(mappings) +Object.freeze(schemaFields) + +const incorporateConvenienceMapping = (inputObj, doc, targetList) => { + const docCopy = !!doc ? _.cloneDeep(doc) : {} + docCopy?.[targetList] + ? docCopy[targetList].push(inputObj) + : (docCopy[targetList] = [inputObj]) + return docCopy +} + +const incorporateConvenienceMappingToObject = (inputObj, doc, targetObject) => { + const docCopy = !!doc ? _.cloneDeep(doc) : {} + docCopy?.[targetObject] + ? (docCopy[targetObject] = _.merge(docCopy[targetObject], inputObj)) + : (docCopy[targetObject] = { ...inputObj }) + return docCopy +} + +/** + * This is the list of fields which are convenience fields, which are mapped to other fields in the registry document. + * A key difference between this and `mappings` is that the mappers here take two arguments: the input value, as well as the document currently being produced. The function then returns a fresh copy of that document, mutated with the output of the mapper. This is a pure function, and does not mutate the document passed in. + * @type {Object} + **/ +const convenienceMappings = { + // These fields map into `contacts` in the registry document. + email: useSharedMappings(['v2', 'v2.1'], (input, doc) => + incorporateConvenienceMapping( + { contact: input, type: 'email' }, + doc, + 'contacts', + ), + ), + + slack: useSharedMappings(['v2', 'v2.1'], (input, doc) => + incorporateConvenienceMapping( + { contact: input, type: 'slack' }, + doc, + 'contacts', + ), + ), + + // These fields map into `repos` list in the registry document for v2, and into the `links` list in the registry document for v2.1. + repo: { + v2: (input, doc) => + incorporateConvenienceMapping({ name: 'Repo', url: input }, doc, 'repos'), + 'v2.1': (input, doc) => + incorporateConvenienceMapping( + { name: 'Repo', type: 'repo', url: input }, + doc, + 'links', + ), + }, + + // These fields map into `integrations` in the registry document. + opsgenie: useSharedMappings(['v2', 'v2.1'], (input, doc) => + incorporateConvenienceMappingToObject( + { opsgenie: { 'service-url': input } }, + doc, + 'integrations', + ), + ), + pagerduty: { + v2: (input, doc) => + incorporateConvenienceMappingToObject( + { pagerduty: input }, + doc, + 'integrations', + ), + 'v2.1': (input, doc) => + incorporateConvenienceMappingToObject( + { pagerduty: { 'service-url': input } }, + doc, + 'integrations', + ), + }, +} +convenienceMappings['slack-support-channel'] = convenienceMappings.slack +Object.freeze(convenienceMappings) + +/** + * This is the list of fields which are convenience fields, which are mapped to other fields in the registry document. + * @type {string[]} + **/ +const convenienceFields = _.keys(convenienceMappings) +Object.freeze(convenienceFields) + +/** + * This is a convenience function which takes a field name and a version tag and returns a function which maps the input value to the registry document value. + * @param {string} field - The name of the field to map. + * @param {string} version - The version tag to map the field to. + * @returns {function} - A function which maps the input value to the registry document value. + * @example + * const mapField = require('./lib/fieldMappings') + * const mappedValue = mapField('team', 'v2.1')('my-team') + * `// mappedValue = { team: 'my-team' }` + * @public + * @function + **/ +const mapField = + (field, version) => + (input, doc = undefined) => + ( + mappings?.[field]?.[version] ?? + convenienceMappings?.[field]?.[version] ?? + ((_) => core.setFailed(`Unknown field: ${field}`)) + )(input, doc) + +module.exports = { + mappings, + convenienceFields, + schemaFields, + mapField, +} diff --git a/lib/input-expander.js b/lib/input-expander.js index 289655f..4a26d44 100644 --- a/lib/input-expander.js +++ b/lib/input-expander.js @@ -1,9 +1,21 @@ +/** + * input-expander.js + * DDSCMP + * @file This module contains all of the functions which expand scalar + * input from GitHub Actions into hydrated structures for the DD API. + * + * @author Mike Stemle + */ + const core = require('@actions/core') const YAML = require('yaml') -/* +/** * As part of our recursive implementation, we need * to engage in a little bit of type inference. + * @private + * @param {string} x - The input value. + * @returns {Object|Symbol} The parsed YAML object, or a Symbol. */ const parseSafely = (x) => { try { @@ -12,11 +24,38 @@ const parseSafely = (x) => { return Symbol('This will never match.') } } + +/** + * As part of our recursive implementation, we need to be able to break down different types. This tells us if it's an Array. + * @returns {boolean} Whether or not the input is an array. + * @private + **/ const isArray = Array.isArray + +/** + * As part of our recursive implementation, we need to be able to break down different types. This tells us if it's an Object. + * @param {Object} x - The input value. + * @returns {boolean} Whether or not the input is an object. + * @private + **/ const isObject = (x) => x?.constructor === Object // this is because `YAML.parse(1)` returns `null`. + +/** + * As part of our recursive implementation, we need to be able to break down different types. This tells us if it's a scalar or scalar equivalent. + * @param {any} x - The input value. + * @returns {boolean} Whether or not the input is a scalar or scalar equivalent. + * @private + **/ const isYamlScalarEquivalent = (x) => !x || ['string', 'number', 'boolean'].includes(typeof x) + +/** + * As part of our recursive implementation, we need to be able to break down different types. This tells us if it's a scalar. + * @param {any} x - The input value. + * @returns {boolean} Whether or not the input is a scalar. + * @private + **/ const isJustAScalar = (x) => !x || x[0] === '@' || x === parseSafely(`${x}`) /** @@ -61,6 +100,27 @@ const expandObjectInputs = (str) => { } } +/** + * This function takes an input and forces it to be an array. + * @param {any} input - The input to force into an array. + * @returns {array} - The input as an array. + * @public + * @function + */ +const forceArray = (input) => + Array.isArray(input) ? input : !!input ? [input] : [] + +/** + * This function takes an input and forces it to be an object. + * @param {any} input - The input to force into an object. + * @returns {object} - The input as an object. + * @public + * @function + */ +const forceObject = (input) => (typeof input === 'object' ? input : {}) + module.exports = { expandObjectInputs, + forceArray, + forceObject, } diff --git a/lib/input-to-registry-document.js b/lib/input-to-registry-document.js index d51bc93..fbee363 100644 --- a/lib/input-to-registry-document.js +++ b/lib/input-to-registry-document.js @@ -1,27 +1,39 @@ +/** + * This module contains the logic for converting the Action inputs into a registry document for Datadog. + * @module lib/input-to-registry-document + * @requires fs + * @requires path + * @requires @actions/core + * @requires lodash + * @author Mike Stemle + **/ + const fs = require('fs') const path = require('path') const core = require('@actions/core') const _ = require('lodash') -const { expandObjectInputs } = require('./input-expander') +const { expandObjectInputs, forceArray, forceObject } = require('./input-expander') -/** - * This function takes an input and forces it to be an array. - * @param {any} input - The input to force into an array. - * @returns {array} - The input as an array. - * @private - * @function - */ -const forceArray = (input) => - Array.isArray(input) ? input : input && input.length > 0 ? [input] : [] +const { mapField, convenienceFields, schemaFields } = require('./fieldMappings') /** - * This function takes an input and forces it to be an object. - * @param {any} input - The input to force into an object. - * @returns {object} - The input as an object. - * @private - * @function - */ -const forceObject = (input) => (typeof input === 'object' ? input : {}) + * This function takes the inputs from the Action and performs a preliminary mapping for them. + * @param {object} core - The core module from @actions/core. + * @param {string} version - The version of the schema to use. + * @returns {object} - The mapped inputs, with `schema` mapped to schema fields, and `convenience` mapped to convenience fields. + **/ +// const collectInputs = (core, version) => { +// const doc = Object.assign( +// {}, +// ...schemaFields.map((fieldName) => +// mapField(fieldName, version)(core.getInput(fieldName)), +// ) + +// return Object.assign( +// ...convenienceFields.map((fieldName) => +// mapField(fieldName, version)(core.getInput(fieldName)), +// ), +// ) /** * This function takes the inputs from the Action and converts them into a registry document for Datadog. @@ -31,79 +43,33 @@ const forceObject = (input) => (typeof input === 'object' ? input : {}) */ const inputsToRegistryDocument = async () => { // This does the initial fetch of configs from the Action inputs. - const configs = [ - 'team', - 'contacts', - 'repos', - 'tags', - 'links', - 'docs', - 'integrations', - ].reduce((agg, inputName) => { - const inputValue = core.getInput(inputName) - return Object.assign(agg, { [inputName]: expandObjectInputs(inputValue) }) - }, {}) + // const configs = collectInputs(core, core.getInput('schema-version') ?? 'v2') - // Prep the team email contact - const teamContactEmail = { - name: 'Team Email', - type: 'email', - contact: core.getInput('email'), - } - const teamContactSlack = core.getInput('slack-support-channel') - ? [ - { - name: 'Support Slack Channel', - type: 'slack', - contact: core.getInput('slack-support-channel'), - }, - ] - : [] - configs.contacts = Array.isArray(configs.contacts) - ? [teamContactEmail, ...teamContactSlack, ...configs.contacts] - : [teamContactEmail, ...teamContactSlack] + const version = core.getInput('schema-version') ?? 'v2' + let configs = { 'schema-version': version } - if (core.getInput('repo')) { - const serviceRepo = { - name: 'Service Repository', - provider: 'Github', - url: core.getInput('repo'), - } - configs.repos = Array.isArray(configs.repos) - ? [serviceRepo, ...configs.repos] - : [serviceRepo] - } else { - configs.repos = forceArray(configs.repos) + _.merge( + configs, + ...schemaFields + .filter((fieldName) => !!core.getInput(fieldName)) + .map((fieldName) => + mapField(fieldName, version)(core.getInput(fieldName)), + ), + ) + /* + for (const fieldName of schemaFields) { + const input = core.getInput(fieldName) + if (input === undefined) continue + Object.assign(configs, mapField(fieldName, version)(input)) } + */ - // Make sure we have at least one repository. - if (configs.repos?.length === 0) { - return core.setFailed('No repos provided. At least one repo is required.') + for (const fieldName of convenienceFields) { + const input = core.getInput(fieldName) + if (input === undefined) continue + configs = mapField(fieldName, version)(input, configs) } - // Rename `service-name` to `dd-service` - configs['dd-service'] = core.getInput('service-name') - // The schema version - configs['schema-version'] = 'v2' - - // Tags _need_ to be an array of strings, but we can accept an array of strings or an array of objects which we then flatten to an array of strings. - configs.tags = forceArray(configs.tags).map((entry) => - _.isPlainObject(entry) - ? _.join( - _.head(_.toPairs(entry)).map((x) => - typeof x === 'string' ? x.trim() : x, - ), - ':', - ) - : entry, - ) - // These items don't have any convenience items, but they _must_ be arrays. - configs.docs = forceArray(configs.docs) - configs.links = forceArray(configs.links) - // Except for this one which must be an Object - configs.integrations = forceObject(configs.integrations) - - // Return the configs. return configs } diff --git a/lib/input-validation.js b/lib/input-validation.js index 8cea224..0baf53f 100644 --- a/lib/input-validation.js +++ b/lib/input-validation.js @@ -1,3 +1,10 @@ +/** + * @file This file contains the input validation functions. + * @module lib/input-validation + * @see lib/input-expander + * @author Mike Stemle + **/ + /** * Validates the Datadog host. * @param {string} ddHost - The Datadog host. @@ -8,7 +15,10 @@ */ const validateDatadogHostname = (ddHost) => { // Verify the host. - if (!ddHost || !ddHost.match(/^[a-z0-9.-]+\.(datadoghq\.(com|eu|us)|ddog-gov\.com)$/)) { + if ( + !ddHost || + !ddHost.match(/^[a-z0-9.-]+\.(datadoghq\.(com|eu|us)|ddog-gov\.com)$/) + ) { throw new Error( `Invalid DataDog host: ${ddHost}. See here for more details: https://docs.datadoghq.com/getting_started/site/`, ) diff --git a/lib/org-rules.js b/lib/org-rules.js index 68fc154..a6258b7 100644 --- a/lib/org-rules.js +++ b/lib/org-rules.js @@ -1,3 +1,9 @@ +/** + * @file This file contains the functions which apply the organization rules to service catalog entries. + * @module lib/org-rules + * @author Mike Stemle + **/ + const YAML = require('yaml') const core = require('@actions/core') const github = require('@actions/github') @@ -182,28 +188,33 @@ const selectionForTags = (tags, serviceDefinition) => { return true } -/** - * Check selection criteria for a team. - * @param {string} teamName - The team name to check. - * @param {object} serviceDefinition - The service definition to use when checking. - * @returns {boolean} - True if the team name matches, false otherwise. - * @private - * @function - */ -const selectionForTeam = (teamName, serviceDefinition) => - teamName.toLocaleLowerCase() === serviceDefinition?.team?.toLocaleLowerCase() +const caseSensitiveFieldListMatch = + (fieldName) => (value, serviceDefinition) => { + if (value.toLocaleLowerCase() === 'all') { + !!_.get(serviceDefinition, fieldName, undefined) + } + if (!Array.isArray(value)) { + core.warning( + `Invalid value for ${fieldName}: ${value}; this should be either 'all' or an array of acceptable values.`, + ) + } + + return ( + value.filter((v) => _.get(serviceDefinition, fieldName, []).includes(v)) + .length > 0 + ) + } /** - * Check selection criteria for a service name. - * @param {string} serviceName - The service name to check. - * @param {object} serviceDefinition - The service definition to use when checking. - * @returns {boolean} - True if the service name matches, false otherwise. + * Make a function which checks for a field name in a service definition. + * @param {string} fieldName - The field name to check. + * @returns {function} - A function which checks for the field name in a service definition. * @private * @function - */ -const selectionForServiceName = (serviceName, serviceDefinition) => - serviceName.toLocaleLowerCase() === - serviceDefinition['dd-service'].toLocaleLowerCase() + **/ +const caseInsensitiveFieldMatch = (fieldName) => (value, serviceDefinition) => + value.toLocaleLowerCase() === + serviceDefinition?.[fieldName]?.toLocaleLowerCase() /** * Determine if the rule applies to the service description. Since a single rule can have @@ -220,8 +231,12 @@ const determineApplicabilityOfRule = (rule, serviceDescription) => { const selectionCriteria = rule?.selection || undefined const selectionCheckers = { tags: selectionForTags, - 'service-name': selectionForServiceName, - team: selectionForTeam, + 'service-name': caseInsensitiveFieldMatch('dd-service'), + 'schema-version': caseInsensitiveFieldMatch('schema-version'), + team: caseInsensitiveFieldMatch('team'), + application: caseSensitiveFieldListMatch('application'), + tier: caseSensitiveFieldListMatch('tier'), + lifecycle: caseSensitiveFieldListMatch('lifecycle'), } const selectableFields = Object.keys(selectionCheckers) @@ -328,6 +343,32 @@ const makeComplianceCheck_valueMatchAndCount = ( } } +/** + * Create a compliance check function which checks that a field in the service definition using a value check, with support for `any`. + * @param {string} fieldName - The name of the field to check. + * @returns {function} - A compliance check function. + * @private + * @function + **/ +const makeSimpleStringFieldComplianceChecker = + (fieldName) => (requirement, serviceDefinition) => { + if (!requirement || _.isEmpty(requirement)) return true + if (!serviceDefinition || _.isEmpty(serviceDefinition)) return false + + // Support `any` + if ( + !Array.isArray(requirement) && + requirement.toLocaleLowerCase() === 'any' + ) { + return !!_.get(serviceDefinition, fieldName, undefined) + } + + const req_list = Array.isArray(requirement) ? requirement : [requirement] + const sd_value = _.get(serviceDefinition, fieldName, undefined) + + return req_list.includes(sd_value) + } + /** * Check if the service description complies with the tags rule. * @param {object} requirement - The requirement to check. @@ -437,6 +478,11 @@ const determineRuleCompliance = (rule, serviceDescription) => { tags: checkTagsCompliance, integrations: checkIntegrationsCompliance, + application: makeSimpleStringFieldComplianceChecker('application'), + description: makeSimpleStringFieldComplianceChecker('description'), + lifecycle: makeSimpleStringFieldComplianceChecker('lifecycle'), + tier: makeSimpleStringFieldComplianceChecker('tier'), + // Everything else can use these higher-order functions. links: makeComplianceCheck_valueMatchAndCount( 'type', diff --git a/package-lock.json b/package-lock.json index 8fab966..8128831 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,12 +12,12 @@ "@actions/core": "^1.10.0", "@actions/github": "^5.1.1", "@actions/http-client": "^2.1.0", - "@octokit/rest": "^19.0.7", + "@octokit/rest": "^19.0.12", "lodash": "^4.17.21", - "yaml": "^2.2.2" + "yaml": "^2.3.1" }, "devDependencies": { - "@types/jest": "^29.5.1", + "@types/jest": "^29.5.2", "@vercel/ncc": "^0.36.1", "ajv": "^8.12.0", "jest": "^29.5.0", @@ -1090,40 +1090,37 @@ } }, "node_modules/@octokit/rest": { - "version": "19.0.7", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.7.tgz", - "integrity": "sha512-HRtSfjrWmWVNp2uAkEpQnuGMJsu/+dBr47dRc5QVgsCbnIc1+GFEaoKBWkYG+zjrsHpSqcAElMio+n10c0b5JA==", + "version": "19.0.12", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.12.tgz", + "integrity": "sha512-oOeaUb9mmtLej6r0hjyT0KGN0NaT3BOMKLaloRrETWGeiLBWQaxaf8Z5dh7bduxxntxZoXSW5Sb5oyl0JKKAxg==", "dependencies": { - "@octokit/core": "^4.1.0", - "@octokit/plugin-paginate-rest": "^6.0.0", + "@octokit/core": "^4.2.1", + "@octokit/plugin-paginate-rest": "^7.0.0", "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.0.0" + "@octokit/plugin-rest-endpoint-methods": "^7.1.2" }, "engines": { "node": ">= 14" } }, "node_modules/@octokit/rest/node_modules/@octokit/auth-token": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz", - "integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==", - "dependencies": { - "@octokit/types": "^9.0.0" - }, + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.4.tgz", + "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==", "engines": { "node": ">= 14" } }, "node_modules/@octokit/rest/node_modules/@octokit/core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.0.tgz", - "integrity": "sha512-AgvDRUg3COpR82P7PBdGZF/NNqGmtMq2NiPqeSsDIeCfYFOZ9gddqWNQHnFdEUf+YwOj4aZYmJnlPp7OXmDIDg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.3.tgz", + "integrity": "sha512-pFfOAfEvijIMK0rL92cU55z8z2VYznW4a5/fzI4EStWVTASaum/MpWvk5eG9zJZAf+EI7U+sBPbIvk5uswDcZg==", "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": "^9.0.0", + "@octokit/request-error": "^4.0.0", + "@octokit/types": "^10.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" }, @@ -1132,9 +1129,9 @@ } }, "node_modules/@octokit/rest/node_modules/@octokit/endpoint": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.5.tgz", - "integrity": "sha512-LG4o4HMY1Xoaec87IqQ41TQ+glvIeTKqfjkCEmt5AIwDZJwQeVZFIEYXrYY6yLwK+pAScb9Gj4q+Nz2qSw1roA==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.6.tgz", + "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==", "dependencies": { "@octokit/types": "^9.0.0", "is-plain-object": "^5.0.0", @@ -1144,10 +1141,18 @@ "node": ">= 14" } }, + "node_modules/@octokit/rest/node_modules/@octokit/endpoint/node_modules/@octokit/types": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz", + "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", + "dependencies": { + "@octokit/openapi-types": "^18.0.0" + } + }, "node_modules/@octokit/rest/node_modules/@octokit/graphql": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.5.tgz", - "integrity": "sha512-Qwfvh3xdqKtIznjX9lz2D458r7dJPP8l6r4GQkIdWQouZwHQK0mVT88uwiU2bdTU2OtT1uOlKpRciUWldpG0yQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", + "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", "dependencies": { "@octokit/request": "^6.0.0", "@octokit/types": "^9.0.0", @@ -1157,32 +1162,48 @@ "node": ">= 14" } }, + "node_modules/@octokit/rest/node_modules/@octokit/graphql/node_modules/@octokit/types": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz", + "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", + "dependencies": { + "@octokit/openapi-types": "^18.0.0" + } + }, "node_modules/@octokit/rest/node_modules/@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", + "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==" }, "node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz", - "integrity": "sha512-Sq5VU1PfT6/JyuXPyt04KZNVsFOSBaYOAq2QRZUwzVlI10KFvcbUo8lR258AAQL1Et60b0WuVik+zOWKLuDZxw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-7.1.2.tgz", + "integrity": "sha512-Jx8KuKqEAVRsK6fMzZKv3h6UH9/NRDHsDRtUAROqqmZlCptM///Uef7A1ViZ/cbDplekz7VbDWdFLAZ/mpuDww==", "dependencies": { - "@octokit/types": "^9.0.0" + "@octokit/tsconfig": "^2.0.0", + "@octokit/types": "^9.3.2" }, "engines": { - "node": ">= 14" + "node": ">= 18" }, "peerDependencies": { "@octokit/core": ">=4" } }, + "node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz", + "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", + "dependencies": { + "@octokit/openapi-types": "^18.0.0" + } + }, "node_modules/@octokit/rest/node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.0.1.tgz", - "integrity": "sha512-pnCaLwZBudK5xCdrR823xHGNgqOzRnJ/mpC/76YPpNP7DybdsJtP7mdOwh+wYZxK5jqeQuhu59ogMI4NRlBUvA==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz", + "integrity": "sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==", "dependencies": { - "@octokit/types": "^9.0.0", - "deprecation": "^2.3.1" + "@octokit/types": "^10.0.0" }, "engines": { "node": ">= 14" @@ -1192,12 +1213,12 @@ } }, "node_modules/@octokit/rest/node_modules/@octokit/request": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.3.tgz", - "integrity": "sha512-TNAodj5yNzrrZ/VxP+H5HiYaZep0H3GU0O7PaF+fhDrt8FPrnkei9Aal/txsN/1P7V3CPiThG0tIvpPDYUsyAA==", + "version": "6.2.7", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.7.tgz", + "integrity": "sha512-OKTq4unIM7iXn9MzRnI66rcXmh0VF7389Acx33uMjcoZ34o6NzbglcncPdy/P+sCKIvrf73aZRZ9w08GnMluQg==", "dependencies": { "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", + "@octokit/request-error": "^4.0.0", "@octokit/types": "^9.0.0", "is-plain-object": "^5.0.0", "node-fetch": "^2.6.7", @@ -1208,26 +1229,39 @@ } }, "node_modules/@octokit/rest/node_modules/@octokit/request-error": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-4.0.2.tgz", + "integrity": "sha512-uqwUEmZw3x4I9DGYq9fODVAAvcLsPQv97NRycP6syEFu5916M189VnNBW2zANNwqg3OiligNcAey7P0SET843w==", "dependencies": { - "@octokit/types": "^9.0.0", + "@octokit/types": "^10.0.0", "deprecation": "^2.0.0", "once": "^1.4.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/request/node_modules/@octokit/types": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz", + "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", + "dependencies": { + "@octokit/openapi-types": "^18.0.0" } }, "node_modules/@octokit/rest/node_modules/@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-10.0.0.tgz", + "integrity": "sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==", "dependencies": { - "@octokit/openapi-types": "^16.0.0" + "@octokit/openapi-types": "^18.0.0" } }, + "node_modules/@octokit/tsconfig": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-2.0.0.tgz", + "integrity": "sha512-tWnrai3quGt8+gRN2edzo9fmraWekeryXPeXDomMw2oFSpu/lH3VSWGn/q4V+rwjTRMeeXk/ci623/01Zet4VQ==" + }, "node_modules/@octokit/types": { "version": "6.41.0", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", @@ -1335,9 +1369,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.1.tgz", - "integrity": "sha512-tEuVcHrpaixS36w7hpsfLBLpjtMRJUE09/MHXn923LOVojDwyC14cWcfc0rDs0VEfUyYmt/+iX1kxxp+gZMcaQ==", + "version": "29.5.2", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.2.tgz", + "integrity": "sha512-mSoZVJF5YzGVCk+FsDxzDuH7s+SCkzrgKZzf0Z0T2WudhBUPoF6ktoTPC4R0ZoCPCV5xUvuU6ias5NvxcBcMMg==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -3865,9 +3899,9 @@ "dev": true }, "node_modules/yaml": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz", - "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", + "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", "engines": { "node": ">= 14" } diff --git a/package.json b/package.json index bd2c5ac..782a4cd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@arcxp/datadog-service-catalog-metadata-provider", - "version": "1.1.2", + "version": "2.0.0", "description": "This is a package which provides GitHub Actions with a workflow for providing the DataDog Service Catalog Provider with information that will register your service in the Service Catalog.", "main": "index.js", "scripts": { @@ -27,12 +27,12 @@ "@actions/core": "^1.10.0", "@actions/github": "^5.1.1", "@actions/http-client": "^2.1.0", - "@octokit/rest": "^19.0.7", + "@octokit/rest": "^19.0.12", "lodash": "^4.17.21", - "yaml": "^2.2.2" + "yaml": "^2.3.1" }, "devDependencies": { - "@types/jest": "^29.5.1", + "@types/jest": "^29.5.2", "@vercel/ncc": "^0.36.1", "ajv": "^8.12.0", "jest": "^29.5.0",