mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-12 04:15:30 +00:00
Merge branch 'msukkarieh/deprecate_secret_manager' into msukkarieh/auth_provider_config
This commit is contained in:
commit
20ae502618
92 changed files with 584 additions and 5421 deletions
|
|
@ -14,6 +14,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- [ask sb] Fixed issue where reasoning tokens would appear in `text` content for openai compatible models. [#582](https://github.com/sourcebot-dev/sourcebot/pull/582)
|
- [ask sb] Fixed issue where reasoning tokens would appear in `text` content for openai compatible models. [#582](https://github.com/sourcebot-dev/sourcebot/pull/582)
|
||||||
- Fixed issue with GitHub app token tracking and refreshing. [#583](https://github.com/sourcebot-dev/sourcebot/pull/583)
|
- Fixed issue with GitHub app token tracking and refreshing. [#583](https://github.com/sourcebot-dev/sourcebot/pull/583)
|
||||||
- Fixed "The account is already associated with another user" errors with GitLab oauth provider. [#584](https://github.com/sourcebot-dev/sourcebot/pull/584)
|
- Fixed "The account is already associated with another user" errors with GitLab oauth provider. [#584](https://github.com/sourcebot-dev/sourcebot/pull/584)
|
||||||
|
- Fixed error when viewing a generic git connection in `/settings/connections`. [#588](https://github.com/sourcebot-dev/sourcebot/pull/588)
|
||||||
|
|
||||||
|
## Removed
|
||||||
|
- Removed built-in secret manager. [#592](https://github.com/sourcebot-dev/sourcebot/pull/592)
|
||||||
|
|
||||||
## [4.8.1] - 2025-10-29
|
## [4.8.1] - 2025-10-29
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ If you're not familiar with Sourcebot [connections](/docs/connections/overview),
|
||||||
Azure Devops Cloud requires you to provide a PAT in order to index your repositories. To learn how to create PAT, check out the [Azure Devops docs](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows).
|
Azure Devops Cloud requires you to provide a PAT in order to index your repositories. To learn how to create PAT, check out the [Azure Devops docs](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows).
|
||||||
Sourcebot needs the `Read` access for the `Code` scope in order to find and clone your repos.
|
Sourcebot needs the `Read` access for the `Code` scope in order to find and clone your repos.
|
||||||
|
|
||||||
Next, provide the access token via the `token` property, either as an environment variable or a secret:
|
Next, provide the access token via an environment variable which is referenced in the `token` property:
|
||||||
|
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<Tab title="Environment Variable">
|
<Tab title="Environment Variable">
|
||||||
|
|
@ -113,28 +113,6 @@ Next, provide the access token via the `token` property, either as an environmen
|
||||||
ghcr.io/sourcebot-dev/sourcebot:latest
|
ghcr.io/sourcebot-dev/sourcebot:latest
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab title="Secret">
|
|
||||||
<Note>Secrets are only supported when [authentication](/docs/configuration/auth/overview) is enabled.</Note>
|
|
||||||
|
|
||||||
1. Navigate to **Secrets** in settings and create a new secret with your PAT:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
2. Add the `token` property to your connection config:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "azuredevops",
|
|
||||||
"deploymentType": "cloud",
|
|
||||||
"token": {
|
|
||||||
"secret": "mysecret"
|
|
||||||
}
|
|
||||||
// .. rest of config ..
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
## Schema reference
|
## Schema reference
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ If you're not familiar with Sourcebot [connections](/docs/connections/overview),
|
||||||
Azure Devops Server requires you to provide a PAT in order to index your repositories. To learn how to create PAT, check out the [Azure Devops docs](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows).
|
Azure Devops Server requires you to provide a PAT in order to index your repositories. To learn how to create PAT, check out the [Azure Devops docs](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows).
|
||||||
Sourcebot needs the `Read` access for the `Code` scope in order to find and clone your repos.
|
Sourcebot needs the `Read` access for the `Code` scope in order to find and clone your repos.
|
||||||
|
|
||||||
Next, provide the access token via the `token` property, either as an environment variable or a secret:
|
Next, provide the access token via an environment variable which is referenced in the `token` property:
|
||||||
|
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<Tab title="Environment Variable">
|
<Tab title="Environment Variable">
|
||||||
|
|
@ -127,28 +127,6 @@ Next, provide the access token via the `token` property, either as an environmen
|
||||||
ghcr.io/sourcebot-dev/sourcebot:latest
|
ghcr.io/sourcebot-dev/sourcebot:latest
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab title="Secret">
|
|
||||||
<Note>Secrets are only supported when [authentication](/docs/configuration/auth/overview) is enabled.</Note>
|
|
||||||
|
|
||||||
1. Navigate to **Secrets** in settings and create a new secret with your PAT:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
2. Add the `token` property to your connection config:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "azuredevops",
|
|
||||||
"deploymentType": "server",
|
|
||||||
"token": {
|
|
||||||
"secret": "mysecret"
|
|
||||||
}
|
|
||||||
// .. rest of config ..
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
## Schema reference
|
## Schema reference
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ In order to index private repositories, you'll need to generate a Gitea access t
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Next, provide the access token via the `token` property, either as an environment variable or a secret:
|
Next, provide the access token via an environment variable which is referenced in the `token` property:
|
||||||
|
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<Tab title="Environment Variable">
|
<Tab title="Environment Variable">
|
||||||
|
|
@ -107,27 +107,6 @@ Next, provide the access token via the `token` property, either as an environmen
|
||||||
ghcr.io/sourcebot-dev/sourcebot:latest
|
ghcr.io/sourcebot-dev/sourcebot:latest
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab title="Secret">
|
|
||||||
<Note>Secrets are only supported when [authentication](/docs/configuration/auth/overview) is enabled.</Note>
|
|
||||||
|
|
||||||
1. Navigate to **Secrets** in settings and create a new secret with your PAT:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
2. Add the `token` property to your connection config:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "gitea",
|
|
||||||
"token": {
|
|
||||||
"secret": "mysecret"
|
|
||||||
}
|
|
||||||
// .. rest of config ..
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
## Connecting to a custom Gitea
|
## Connecting to a custom Gitea
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ In order to index private repositories, you'll need to generate a access token a
|
||||||
</Accordion>
|
</Accordion>
|
||||||
</AccordionGroup>
|
</AccordionGroup>
|
||||||
|
|
||||||
Next, provide the access token via the `token` property, either as an environment variable or a secret:
|
Next, provide the access token via an environment variable which is referenced in the `token` property:
|
||||||
|
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<Tab title="Environment Variable">
|
<Tab title="Environment Variable">
|
||||||
|
|
@ -154,27 +154,6 @@ Next, provide the access token via the `token` property, either as an environmen
|
||||||
ghcr.io/sourcebot-dev/sourcebot:latest
|
ghcr.io/sourcebot-dev/sourcebot:latest
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab title="Secret">
|
|
||||||
<Note>Secrets are only supported when [authentication](/docs/configuration/auth/overview) is enabled.</Note>
|
|
||||||
|
|
||||||
1. Navigate to **Secrets** in settings and create a new secret with your PAT:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
2. Add the `token` property to your connection config:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"token": {
|
|
||||||
"secret": "mysecret"
|
|
||||||
}
|
|
||||||
// .. rest of config ..
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
## Connecting to a custom GitHub host
|
## Connecting to a custom GitHub host
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ In order to index private projects, you'll need to generate a GitLab Personal Ac
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Next, provide the PAT via the `token` property, either as an environment variable or a secret:
|
Next, provide the PAT via an environment variable which is referenced in the `token` property:
|
||||||
|
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<Tab title="Environment Variable">
|
<Tab title="Environment Variable">
|
||||||
|
|
@ -142,27 +142,6 @@ Next, provide the PAT via the `token` property, either as an environment variabl
|
||||||
ghcr.io/sourcebot-dev/sourcebot:latest
|
ghcr.io/sourcebot-dev/sourcebot:latest
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab title="Secret">
|
|
||||||
<Note>Secrets are only supported when [authentication](/docs/configuration/auth/overview) is enabled.</Note>
|
|
||||||
|
|
||||||
1. Navigate to **Secrets** in settings and create a new secret with your PAT:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
2. Add the `token` property to your connection config:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "gitlab",
|
|
||||||
"token": {
|
|
||||||
"secret": "mysecret"
|
|
||||||
}
|
|
||||||
// .. rest of config ..
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
## Connecting to a custom GitLab host
|
## Connecting to a custom GitLab host
|
||||||
|
|
|
||||||
|
|
@ -24,27 +24,4 @@
|
||||||
ghcr.io/sourcebot-dev/sourcebot:latest
|
ghcr.io/sourcebot-dev/sourcebot:latest
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab title="Secret">
|
|
||||||
<Note>Secrets are only supported when [authentication](/docs/configuration/auth/overview) is enabled.</Note>
|
|
||||||
|
|
||||||
1. Navigate to **Secrets** in settings and create a new secret with your access token:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
2. Add the `token` and `user` (username associated with the app password you created) properties to your connection config:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "bitbucket",
|
|
||||||
"deploymentType": "cloud",
|
|
||||||
"user": "myusername",
|
|
||||||
"token": {
|
|
||||||
"secret": "mysecret"
|
|
||||||
}
|
|
||||||
// .. rest of config ..
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
@ -22,25 +22,4 @@
|
||||||
ghcr.io/sourcebot-dev/sourcebot:latest
|
ghcr.io/sourcebot-dev/sourcebot:latest
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab title="Secret">
|
|
||||||
<Note>Secrets are only supported when [authentication](/docs/configuration/auth/overview) is enabled.</Note>
|
|
||||||
|
|
||||||
1. Navigate to **Secrets** in settings and create a new secret with your PAT:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
2. Add the `token` property to your connection config:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "bitbucket",
|
|
||||||
"token": {
|
|
||||||
"secret": "mysecret"
|
|
||||||
}
|
|
||||||
// .. rest of config ..
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</Tab>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
@ -77,7 +77,6 @@
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -274,7 +273,6 @@
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token.",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -465,7 +463,6 @@
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An access token.",
|
"description": "An access token.",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -779,7 +776,6 @@
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -976,7 +972,6 @@
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token.",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -1167,7 +1162,6 @@
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An access token.",
|
"description": "An access token.",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -1563,7 +1557,6 @@
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -1760,7 +1753,6 @@
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token.",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -1951,7 +1943,6 @@
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An access token.",
|
"description": "An access token.",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,19 +28,6 @@
|
||||||
"privateKey": {
|
"privateKey": {
|
||||||
"description": "The private key of the GitHub App.",
|
"description": "The private key of the GitHub App.",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -90,19 +77,6 @@
|
||||||
"privateKey": {
|
"privateKey": {
|
||||||
"description": "The private key of the GitHub App.",
|
"description": "The private key of the GitHub App.",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -11,25 +11,7 @@
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -15,25 +15,7 @@
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token.",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -15,25 +15,7 @@
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -228,25 +210,7 @@
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token.",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -435,25 +399,7 @@
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -707,25 +653,7 @@
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token.",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -880,25 +808,7 @@
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -11,25 +11,7 @@
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -11,25 +11,7 @@
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
{/* THIS IS A AUTO-GENERATED FILE. DO NOT MODIFY MANUALLY! */}
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"type": "object",
|
|
||||||
"title": "GithubAppConfig",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"const": "githubApp",
|
|
||||||
"description": "GitHub App Configuration"
|
|
||||||
},
|
|
||||||
"deploymentHostname": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "hostname",
|
|
||||||
"default": "github.com",
|
|
||||||
"description": "The hostname of the GitHub App deployment.",
|
|
||||||
"examples": [
|
|
||||||
"github.com",
|
|
||||||
"github.example.com"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"id": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The ID of the GitHub App."
|
|
||||||
},
|
|
||||||
"privateKey": {
|
|
||||||
"description": "The private key of the GitHub App.",
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"env": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the environment variable that contains the token. Only supported in declarative connection configs."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"env"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"required": [
|
|
||||||
"privateKey"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"required": [
|
|
||||||
"privateKeyPath"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
@ -11,25 +11,7 @@
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token.",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -6,19 +6,6 @@
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"Token": {
|
"Token": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -86,19 +73,6 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -130,19 +104,6 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import { AzureDevOpsConnectionConfig } from "@sourcebot/schemas/v3/azuredevops.t
|
||||||
import { createLogger } from "@sourcebot/logger";
|
import { createLogger } from "@sourcebot/logger";
|
||||||
import { measure, fetchWithRetry } from "./utils.js";
|
import { measure, fetchWithRetry } from "./utils.js";
|
||||||
import micromatch from "micromatch";
|
import micromatch from "micromatch";
|
||||||
import { PrismaClient } from "@sourcebot/db";
|
|
||||||
import { BackendException, BackendError } from "@sourcebot/error";
|
import { BackendException, BackendError } from "@sourcebot/error";
|
||||||
import { processPromiseResults, throwIfAnyFailed } from "./connectionUtils.js";
|
import { processPromiseResults, throwIfAnyFailed } from "./connectionUtils.js";
|
||||||
import * as Sentry from "@sentry/node";
|
import * as Sentry from "@sentry/node";
|
||||||
|
|
@ -29,13 +28,11 @@ function createAzureDevOpsConnection(
|
||||||
|
|
||||||
export const getAzureDevOpsReposFromConfig = async (
|
export const getAzureDevOpsReposFromConfig = async (
|
||||||
config: AzureDevOpsConnectionConfig,
|
config: AzureDevOpsConnectionConfig,
|
||||||
orgId: number,
|
|
||||||
db: PrismaClient
|
|
||||||
) => {
|
) => {
|
||||||
const baseUrl = config.url || `https://${AZUREDEVOPS_CLOUD_HOSTNAME}`;
|
const baseUrl = config.url || `https://${AZUREDEVOPS_CLOUD_HOSTNAME}`;
|
||||||
|
|
||||||
const token = config.token ?
|
const token = config.token ?
|
||||||
await getTokenFromConfig(config.token, orgId, db) :
|
await getTokenFromConfig(config.token) :
|
||||||
undefined;
|
undefined;
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import { createBitbucketServerClient } from "@coderabbitai/bitbucket/server";
|
||||||
import { BitbucketConnectionConfig } from "@sourcebot/schemas/v3/bitbucket.type";
|
import { BitbucketConnectionConfig } from "@sourcebot/schemas/v3/bitbucket.type";
|
||||||
import type { ClientOptions, ClientPathsWithMethod } from "openapi-fetch";
|
import type { ClientOptions, ClientPathsWithMethod } from "openapi-fetch";
|
||||||
import { createLogger } from "@sourcebot/logger";
|
import { createLogger } from "@sourcebot/logger";
|
||||||
import { PrismaClient } from "@sourcebot/db";
|
|
||||||
import { measure, fetchWithRetry } from "./utils.js";
|
import { measure, fetchWithRetry } from "./utils.js";
|
||||||
import * as Sentry from "@sentry/node";
|
import * as Sentry from "@sentry/node";
|
||||||
import {
|
import {
|
||||||
|
|
@ -58,9 +57,9 @@ type ServerPaginatedResponse<T> = {
|
||||||
readonly nextPageStart: number;
|
readonly nextPageStart: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getBitbucketReposFromConfig = async (config: BitbucketConnectionConfig, orgId: number, db: PrismaClient) => {
|
export const getBitbucketReposFromConfig = async (config: BitbucketConnectionConfig) => {
|
||||||
const token = config.token ?
|
const token = config.token ?
|
||||||
await getTokenFromConfig(config.token, orgId, db) :
|
await getTokenFromConfig(config.token) :
|
||||||
undefined;
|
undefined;
|
||||||
|
|
||||||
if (config.deploymentType === 'server' && !config.url) {
|
if (config.deploymentType === 'server' && !config.url) {
|
||||||
|
|
|
||||||
|
|
@ -179,25 +179,25 @@ export class ConnectionManager {
|
||||||
const result = await (async () => {
|
const result = await (async () => {
|
||||||
switch (config.type) {
|
switch (config.type) {
|
||||||
case 'github': {
|
case 'github': {
|
||||||
return await compileGithubConfig(config, job.data.connectionId, orgId, this.db, abortController);
|
return await compileGithubConfig(config, job.data.connectionId, abortController);
|
||||||
}
|
}
|
||||||
case 'gitlab': {
|
case 'gitlab': {
|
||||||
return await compileGitlabConfig(config, job.data.connectionId, orgId, this.db);
|
return await compileGitlabConfig(config, job.data.connectionId);
|
||||||
}
|
}
|
||||||
case 'gitea': {
|
case 'gitea': {
|
||||||
return await compileGiteaConfig(config, job.data.connectionId, orgId, this.db);
|
return await compileGiteaConfig(config, job.data.connectionId);
|
||||||
}
|
}
|
||||||
case 'gerrit': {
|
case 'gerrit': {
|
||||||
return await compileGerritConfig(config, job.data.connectionId, orgId);
|
return await compileGerritConfig(config, job.data.connectionId);
|
||||||
}
|
}
|
||||||
case 'bitbucket': {
|
case 'bitbucket': {
|
||||||
return await compileBitbucketConfig(config, job.data.connectionId, orgId, this.db);
|
return await compileBitbucketConfig(config, job.data.connectionId);
|
||||||
}
|
}
|
||||||
case 'azuredevops': {
|
case 'azuredevops': {
|
||||||
return await compileAzureDevOpsConfig(config, job.data.connectionId, orgId, this.db);
|
return await compileAzureDevOpsConfig(config, job.data.connectionId);
|
||||||
}
|
}
|
||||||
case 'git': {
|
case 'git': {
|
||||||
return await compileGenericGitHostConfig(config, job.data.connectionId, orgId);
|
return await compileGenericGitHostConfig(config, job.data.connectionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
|
import { CodeHostType } from "@sourcebot/db";
|
||||||
import { env } from "./env.js";
|
import { env } from "./env.js";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
export const SINGLE_TENANT_ORG_ID = 1;
|
export const SINGLE_TENANT_ORG_ID = 1;
|
||||||
|
|
||||||
export const PERMISSION_SYNC_SUPPORTED_CODE_HOST_TYPES = [
|
export const PERMISSION_SYNC_SUPPORTED_CODE_HOST_TYPES: CodeHostType[] = [
|
||||||
'github',
|
'github',
|
||||||
'gitlab',
|
'gitlab',
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -55,11 +55,7 @@ export class GithubAppManager {
|
||||||
|
|
||||||
for (const app of githubApps) {
|
for (const app of githubApps) {
|
||||||
const deploymentHostname = app.deploymentHostname as string || GITHUB_DEFAULT_DEPLOYMENT_HOSTNAME;
|
const deploymentHostname = app.deploymentHostname as string || GITHUB_DEFAULT_DEPLOYMENT_HOSTNAME;
|
||||||
|
const privateKey = await getTokenFromConfig(app.privateKey);
|
||||||
// @todo: we should move SINGLE_TENANT_ORG_ID to shared package or just remove the need to pass this in
|
|
||||||
// when resolving tokens
|
|
||||||
const SINGLE_TENANT_ORG_ID = 1;
|
|
||||||
const privateKey = await getTokenFromConfig(app.privateKey, SINGLE_TENANT_ORG_ID, this.db);
|
|
||||||
|
|
||||||
const octokitApp = new App({
|
const octokitApp = new App({
|
||||||
appId: Number(app.id),
|
appId: Number(app.id),
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ export class RepoPermissionSyncer {
|
||||||
|
|
||||||
logger.info(`Syncing permissions for repo ${repo.displayName}...`);
|
logger.info(`Syncing permissions for repo ${repo.displayName}...`);
|
||||||
|
|
||||||
const credentials = await getAuthCredentialsForRepo(repo, this.db, logger);
|
const credentials = await getAuthCredentialsForRepo(repo, logger);
|
||||||
if (!credentials) {
|
if (!credentials) {
|
||||||
throw new Error(`No credentials found for repo ${id}`);
|
throw new Error(`No credentials found for repo ${id}`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import { measure } from './utils.js';
|
||||||
import fetch from 'cross-fetch';
|
import fetch from 'cross-fetch';
|
||||||
import { createLogger } from '@sourcebot/logger';
|
import { createLogger } from '@sourcebot/logger';
|
||||||
import micromatch from 'micromatch';
|
import micromatch from 'micromatch';
|
||||||
import { PrismaClient } from '@sourcebot/db';
|
|
||||||
import { processPromiseResults, throwIfAnyFailed } from './connectionUtils.js';
|
import { processPromiseResults, throwIfAnyFailed } from './connectionUtils.js';
|
||||||
import * as Sentry from "@sentry/node";
|
import * as Sentry from "@sentry/node";
|
||||||
import { env } from './env.js';
|
import { env } from './env.js';
|
||||||
|
|
@ -13,13 +12,13 @@ import { getTokenFromConfig } from "@sourcebot/crypto";
|
||||||
const logger = createLogger('gitea');
|
const logger = createLogger('gitea');
|
||||||
const GITEA_CLOUD_HOSTNAME = "gitea.com";
|
const GITEA_CLOUD_HOSTNAME = "gitea.com";
|
||||||
|
|
||||||
export const getGiteaReposFromConfig = async (config: GiteaConnectionConfig, orgId: number, db: PrismaClient) => {
|
export const getGiteaReposFromConfig = async (config: GiteaConnectionConfig) => {
|
||||||
const hostname = config.url ?
|
const hostname = config.url ?
|
||||||
new URL(config.url).hostname :
|
new URL(config.url).hostname :
|
||||||
GITEA_CLOUD_HOSTNAME;
|
GITEA_CLOUD_HOSTNAME;
|
||||||
|
|
||||||
const token = config.token ?
|
const token = config.token ?
|
||||||
await getTokenFromConfig(config.token, orgId, db) :
|
await getTokenFromConfig(config.token) :
|
||||||
hostname === GITEA_CLOUD_HOSTNAME ?
|
hostname === GITEA_CLOUD_HOSTNAME ?
|
||||||
env.FALLBACK_GITEA_CLOUD_TOKEN :
|
env.FALLBACK_GITEA_CLOUD_TOKEN :
|
||||||
undefined;
|
undefined;
|
||||||
|
|
@ -53,7 +52,7 @@ export const getGiteaReposFromConfig = async (config: GiteaConnectionConfig, org
|
||||||
allRepos = allRepos.filter(repo => repo.full_name !== undefined);
|
allRepos = allRepos.filter(repo => repo.full_name !== undefined);
|
||||||
allRepos = allRepos.filter(repo => {
|
allRepos = allRepos.filter(repo => {
|
||||||
if (repo.full_name === undefined) {
|
if (repo.full_name === undefined) {
|
||||||
logger.warn(`Repository with undefined full_name found: orgId=${orgId}, repoId=${repo.id}`);
|
logger.warn(`Repository with undefined full_name found: repoId=${repo.id}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { Octokit } from "@octokit/rest";
|
import { Octokit } from "@octokit/rest";
|
||||||
import * as Sentry from "@sentry/node";
|
import * as Sentry from "@sentry/node";
|
||||||
import { PrismaClient } from "@sourcebot/db";
|
|
||||||
import { createLogger } from "@sourcebot/logger";
|
import { createLogger } from "@sourcebot/logger";
|
||||||
import { GithubConnectionConfig } from "@sourcebot/schemas/v3/github.type";
|
import { GithubConnectionConfig } from "@sourcebot/schemas/v3/github.type";
|
||||||
import { hasEntitlement } from "@sourcebot/shared";
|
import { hasEntitlement } from "@sourcebot/shared";
|
||||||
|
|
@ -92,13 +91,13 @@ const getOctokitWithGithubApp = async (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getGitHubReposFromConfig = async (config: GithubConnectionConfig, orgId: number, db: PrismaClient, signal: AbortSignal): Promise<{ repos: OctokitRepository[], warnings: string[] }> => {
|
export const getGitHubReposFromConfig = async (config: GithubConnectionConfig, signal: AbortSignal): Promise<{ repos: OctokitRepository[], warnings: string[] }> => {
|
||||||
const hostname = config.url ?
|
const hostname = config.url ?
|
||||||
new URL(config.url).hostname :
|
new URL(config.url).hostname :
|
||||||
GITHUB_CLOUD_HOSTNAME;
|
GITHUB_CLOUD_HOSTNAME;
|
||||||
|
|
||||||
const token = config.token ?
|
const token = config.token ?
|
||||||
await getTokenFromConfig(config.token, orgId, db) :
|
await getTokenFromConfig(config.token) :
|
||||||
hostname === GITHUB_CLOUD_HOSTNAME ?
|
hostname === GITHUB_CLOUD_HOSTNAME ?
|
||||||
env.FALLBACK_GITHUB_CLOUD_TOKEN :
|
env.FALLBACK_GITHUB_CLOUD_TOKEN :
|
||||||
undefined;
|
undefined;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import micromatch from "micromatch";
|
||||||
import { createLogger } from "@sourcebot/logger";
|
import { createLogger } from "@sourcebot/logger";
|
||||||
import { GitlabConnectionConfig } from "@sourcebot/schemas/v3/gitlab.type"
|
import { GitlabConnectionConfig } from "@sourcebot/schemas/v3/gitlab.type"
|
||||||
import { measure, fetchWithRetry } from "./utils.js";
|
import { measure, fetchWithRetry } from "./utils.js";
|
||||||
import { PrismaClient } from "@sourcebot/db";
|
|
||||||
import { processPromiseResults, throwIfAnyFailed } from "./connectionUtils.js";
|
import { processPromiseResults, throwIfAnyFailed } from "./connectionUtils.js";
|
||||||
import * as Sentry from "@sentry/node";
|
import * as Sentry from "@sentry/node";
|
||||||
import { env } from "./env.js";
|
import { env } from "./env.js";
|
||||||
|
|
@ -34,13 +33,13 @@ export const createGitLabFromOAuthToken = async ({ oauthToken, url }: { oauthTok
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getGitLabReposFromConfig = async (config: GitlabConnectionConfig, orgId: number, db: PrismaClient) => {
|
export const getGitLabReposFromConfig = async (config: GitlabConnectionConfig) => {
|
||||||
const hostname = config.url ?
|
const hostname = config.url ?
|
||||||
new URL(config.url).hostname :
|
new URL(config.url).hostname :
|
||||||
GITLAB_CLOUD_HOSTNAME;
|
GITLAB_CLOUD_HOSTNAME;
|
||||||
|
|
||||||
const token = config.token ?
|
const token = config.token ?
|
||||||
await getTokenFromConfig(config.token, orgId, db) :
|
await getTokenFromConfig(config.token) :
|
||||||
hostname === GITLAB_CLOUD_HOSTNAME ?
|
hostname === GITLAB_CLOUD_HOSTNAME ?
|
||||||
env.FALLBACK_GITLAB_CLOUD_TOKEN :
|
env.FALLBACK_GITLAB_CLOUD_TOKEN :
|
||||||
undefined;
|
undefined;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import { BitbucketRepository, getBitbucketReposFromConfig } from "./bitbucket.js
|
||||||
import { getAzureDevOpsReposFromConfig } from "./azuredevops.js";
|
import { getAzureDevOpsReposFromConfig } from "./azuredevops.js";
|
||||||
import { SchemaRestRepository as BitbucketServerRepository } from "@coderabbitai/bitbucket/server/openapi";
|
import { SchemaRestRepository as BitbucketServerRepository } from "@coderabbitai/bitbucket/server/openapi";
|
||||||
import { SchemaRepository as BitbucketCloudRepository } from "@coderabbitai/bitbucket/cloud/openapi";
|
import { SchemaRepository as BitbucketCloudRepository } from "@coderabbitai/bitbucket/cloud/openapi";
|
||||||
import { Prisma, PrismaClient } from '@sourcebot/db';
|
import { CodeHostType, Prisma } from '@sourcebot/db';
|
||||||
import { WithRequired } from "./types.js"
|
import { WithRequired } from "./types.js"
|
||||||
import { marshalBool } from "./utils.js";
|
import { marshalBool } from "./utils.js";
|
||||||
import { createLogger } from '@sourcebot/logger';
|
import { createLogger } from '@sourcebot/logger';
|
||||||
|
|
@ -19,6 +19,7 @@ import { getOriginUrl, isPathAValidGitRepoRoot, isUrlAValidGitRepo } from './git
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import GitUrlParse from 'git-url-parse';
|
import GitUrlParse from 'git-url-parse';
|
||||||
import { RepoMetadata } from '@sourcebot/shared';
|
import { RepoMetadata } from '@sourcebot/shared';
|
||||||
|
import { SINGLE_TENANT_ORG_ID } from './constants.js';
|
||||||
|
|
||||||
export type RepoData = WithRequired<Prisma.RepoCreateInput, 'connections'>;
|
export type RepoData = WithRequired<Prisma.RepoCreateInput, 'connections'>;
|
||||||
|
|
||||||
|
|
@ -32,10 +33,8 @@ type CompileResult = {
|
||||||
export const compileGithubConfig = async (
|
export const compileGithubConfig = async (
|
||||||
config: GithubConnectionConfig,
|
config: GithubConnectionConfig,
|
||||||
connectionId: number,
|
connectionId: number,
|
||||||
orgId: number,
|
|
||||||
db: PrismaClient,
|
|
||||||
abortController: AbortController): Promise<CompileResult> => {
|
abortController: AbortController): Promise<CompileResult> => {
|
||||||
const gitHubReposResult = await getGitHubReposFromConfig(config, orgId, db, abortController.signal);
|
const gitHubReposResult = await getGitHubReposFromConfig(config, abortController.signal);
|
||||||
const gitHubRepos = gitHubReposResult.repos;
|
const gitHubRepos = gitHubReposResult.repos;
|
||||||
const warnings = gitHubReposResult.warnings;
|
const warnings = gitHubReposResult.warnings;
|
||||||
|
|
||||||
|
|
@ -66,7 +65,7 @@ export const compileGithubConfig = async (
|
||||||
isPublic: isPublic,
|
isPublic: isPublic,
|
||||||
org: {
|
org: {
|
||||||
connect: {
|
connect: {
|
||||||
id: orgId,
|
id: SINGLE_TENANT_ORG_ID,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
connections: {
|
connections: {
|
||||||
|
|
@ -104,11 +103,9 @@ export const compileGithubConfig = async (
|
||||||
|
|
||||||
export const compileGitlabConfig = async (
|
export const compileGitlabConfig = async (
|
||||||
config: GitlabConnectionConfig,
|
config: GitlabConnectionConfig,
|
||||||
connectionId: number,
|
connectionId: number): Promise<CompileResult> => {
|
||||||
orgId: number,
|
|
||||||
db: PrismaClient): Promise<CompileResult> => {
|
|
||||||
|
|
||||||
const gitlabReposResult = await getGitLabReposFromConfig(config, orgId, db);
|
const gitlabReposResult = await getGitLabReposFromConfig(config);
|
||||||
const gitlabRepos = gitlabReposResult.repos;
|
const gitlabRepos = gitlabReposResult.repos;
|
||||||
const warnings = gitlabReposResult.warnings;
|
const warnings = gitlabReposResult.warnings;
|
||||||
|
|
||||||
|
|
@ -144,7 +141,7 @@ export const compileGitlabConfig = async (
|
||||||
isArchived: !!project.archived,
|
isArchived: !!project.archived,
|
||||||
org: {
|
org: {
|
||||||
connect: {
|
connect: {
|
||||||
id: orgId,
|
id: SINGLE_TENANT_ORG_ID,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
connections: {
|
connections: {
|
||||||
|
|
@ -180,11 +177,9 @@ export const compileGitlabConfig = async (
|
||||||
|
|
||||||
export const compileGiteaConfig = async (
|
export const compileGiteaConfig = async (
|
||||||
config: GiteaConnectionConfig,
|
config: GiteaConnectionConfig,
|
||||||
connectionId: number,
|
connectionId: number): Promise<CompileResult> => {
|
||||||
orgId: number,
|
|
||||||
db: PrismaClient): Promise<CompileResult> => {
|
|
||||||
|
|
||||||
const giteaReposResult = await getGiteaReposFromConfig(config, orgId, db);
|
const giteaReposResult = await getGiteaReposFromConfig(config);
|
||||||
const giteaRepos = giteaReposResult.repos;
|
const giteaRepos = giteaReposResult.repos;
|
||||||
const warnings = giteaReposResult.warnings;
|
const warnings = giteaReposResult.warnings;
|
||||||
|
|
||||||
|
|
@ -217,7 +212,7 @@ export const compileGiteaConfig = async (
|
||||||
isArchived: !!repo.archived,
|
isArchived: !!repo.archived,
|
||||||
org: {
|
org: {
|
||||||
connect: {
|
connect: {
|
||||||
id: orgId,
|
id: SINGLE_TENANT_ORG_ID,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
connections: {
|
connections: {
|
||||||
|
|
@ -251,8 +246,7 @@ export const compileGiteaConfig = async (
|
||||||
|
|
||||||
export const compileGerritConfig = async (
|
export const compileGerritConfig = async (
|
||||||
config: GerritConnectionConfig,
|
config: GerritConnectionConfig,
|
||||||
connectionId: number,
|
connectionId: number): Promise<CompileResult> => {
|
||||||
orgId: number): Promise<CompileResult> => {
|
|
||||||
|
|
||||||
const gerritRepos = await getGerritReposFromConfig(config);
|
const gerritRepos = await getGerritReposFromConfig(config);
|
||||||
const hostUrl = config.url;
|
const hostUrl = config.url;
|
||||||
|
|
@ -298,7 +292,7 @@ export const compileGerritConfig = async (
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
org: {
|
org: {
|
||||||
connect: {
|
connect: {
|
||||||
id: orgId,
|
id: SINGLE_TENANT_ORG_ID,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
connections: {
|
connections: {
|
||||||
|
|
@ -332,11 +326,9 @@ export const compileGerritConfig = async (
|
||||||
|
|
||||||
export const compileBitbucketConfig = async (
|
export const compileBitbucketConfig = async (
|
||||||
config: BitbucketConnectionConfig,
|
config: BitbucketConnectionConfig,
|
||||||
connectionId: number,
|
connectionId: number): Promise<CompileResult> => {
|
||||||
orgId: number,
|
|
||||||
db: PrismaClient): Promise<CompileResult> => {
|
|
||||||
|
|
||||||
const bitbucketReposResult = await getBitbucketReposFromConfig(config, orgId, db);
|
const bitbucketReposResult = await getBitbucketReposFromConfig(config);
|
||||||
const bitbucketRepos = bitbucketReposResult.repos;
|
const bitbucketRepos = bitbucketReposResult.repos;
|
||||||
const warnings = bitbucketReposResult.warnings;
|
const warnings = bitbucketReposResult.warnings;
|
||||||
|
|
||||||
|
|
@ -392,7 +384,7 @@ export const compileBitbucketConfig = async (
|
||||||
|
|
||||||
const repos = bitbucketRepos.map((repo) => {
|
const repos = bitbucketRepos.map((repo) => {
|
||||||
const isServer = config.deploymentType === 'server';
|
const isServer = config.deploymentType === 'server';
|
||||||
const codeHostType = isServer ? 'bitbucket-server' : 'bitbucket-cloud'; // zoekt expects bitbucket-server
|
const codeHostType: CodeHostType = isServer ? 'bitbucketServer' : 'bitbucketCloud';
|
||||||
const displayName = isServer ? (repo as BitbucketServerRepository).name! : (repo as BitbucketCloudRepository).full_name!;
|
const displayName = isServer ? (repo as BitbucketServerRepository).name! : (repo as BitbucketCloudRepository).full_name!;
|
||||||
const externalId = isServer ? (repo as BitbucketServerRepository).id!.toString() : (repo as BitbucketCloudRepository).uuid!;
|
const externalId = isServer ? (repo as BitbucketServerRepository).id!.toString() : (repo as BitbucketCloudRepository).uuid!;
|
||||||
const isPublic = isServer ? (repo as BitbucketServerRepository).public : (repo as BitbucketCloudRepository).is_private === false;
|
const isPublic = isServer ? (repo as BitbucketServerRepository).public : (repo as BitbucketCloudRepository).is_private === false;
|
||||||
|
|
@ -415,7 +407,7 @@ export const compileBitbucketConfig = async (
|
||||||
isArchived: isArchived,
|
isArchived: isArchived,
|
||||||
org: {
|
org: {
|
||||||
connect: {
|
connect: {
|
||||||
id: orgId,
|
id: SINGLE_TENANT_ORG_ID,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
connections: {
|
connections: {
|
||||||
|
|
@ -425,7 +417,8 @@ export const compileBitbucketConfig = async (
|
||||||
},
|
},
|
||||||
metadata: {
|
metadata: {
|
||||||
gitConfig: {
|
gitConfig: {
|
||||||
'zoekt.web-url-type': codeHostType,
|
// zoekt expects bitbucket-server and bitbucket-cloud
|
||||||
|
'zoekt.web-url-type': codeHostType === 'bitbucketServer' ? 'bitbucket-server' : 'bitbucket-cloud',
|
||||||
'zoekt.web-url': webUrl,
|
'zoekt.web-url': webUrl,
|
||||||
'zoekt.name': repoName,
|
'zoekt.name': repoName,
|
||||||
'zoekt.archived': marshalBool(isArchived),
|
'zoekt.archived': marshalBool(isArchived),
|
||||||
|
|
@ -449,15 +442,14 @@ export const compileBitbucketConfig = async (
|
||||||
|
|
||||||
export const compileGenericGitHostConfig = async (
|
export const compileGenericGitHostConfig = async (
|
||||||
config: GenericGitHostConnectionConfig,
|
config: GenericGitHostConnectionConfig,
|
||||||
connectionId: number,
|
connectionId: number
|
||||||
orgId: number,
|
|
||||||
): Promise<CompileResult> => {
|
): Promise<CompileResult> => {
|
||||||
const configUrl = new URL(config.url);
|
const configUrl = new URL(config.url);
|
||||||
if (configUrl.protocol === 'file:') {
|
if (configUrl.protocol === 'file:') {
|
||||||
return compileGenericGitHostConfig_file(config, orgId, connectionId);
|
return compileGenericGitHostConfig_file(config, connectionId);
|
||||||
}
|
}
|
||||||
else if (configUrl.protocol === 'http:' || configUrl.protocol === 'https:') {
|
else if (configUrl.protocol === 'http:' || configUrl.protocol === 'https:') {
|
||||||
return compileGenericGitHostConfig_url(config, orgId, connectionId);
|
return compileGenericGitHostConfig_url(config, connectionId);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Schema should prevent this, but throw an error just in case.
|
// Schema should prevent this, but throw an error just in case.
|
||||||
|
|
@ -467,7 +459,6 @@ export const compileGenericGitHostConfig = async (
|
||||||
|
|
||||||
export const compileGenericGitHostConfig_file = async (
|
export const compileGenericGitHostConfig_file = async (
|
||||||
config: GenericGitHostConnectionConfig,
|
config: GenericGitHostConnectionConfig,
|
||||||
orgId: number,
|
|
||||||
connectionId: number,
|
connectionId: number,
|
||||||
): Promise<CompileResult> => {
|
): Promise<CompileResult> => {
|
||||||
const configUrl = new URL(config.url);
|
const configUrl = new URL(config.url);
|
||||||
|
|
@ -507,7 +498,7 @@ export const compileGenericGitHostConfig_file = async (
|
||||||
const repoName = path.join(remoteUrl.host, remoteUrl.pathname.replace(/\.git$/, ''));
|
const repoName = path.join(remoteUrl.host, remoteUrl.pathname.replace(/\.git$/, ''));
|
||||||
|
|
||||||
const repo: RepoData = {
|
const repo: RepoData = {
|
||||||
external_codeHostType: 'generic-git-host',
|
external_codeHostType: 'genericGitHost',
|
||||||
external_codeHostUrl: remoteUrl.resource,
|
external_codeHostUrl: remoteUrl.resource,
|
||||||
external_id: remoteUrl.toString(),
|
external_id: remoteUrl.toString(),
|
||||||
cloneUrl: `file://${repoPath}`,
|
cloneUrl: `file://${repoPath}`,
|
||||||
|
|
@ -517,7 +508,7 @@ export const compileGenericGitHostConfig_file = async (
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
org: {
|
org: {
|
||||||
connect: {
|
connect: {
|
||||||
id: orgId,
|
id: SINGLE_TENANT_ORG_ID,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
connections: {
|
connections: {
|
||||||
|
|
@ -546,7 +537,6 @@ export const compileGenericGitHostConfig_file = async (
|
||||||
|
|
||||||
export const compileGenericGitHostConfig_url = async (
|
export const compileGenericGitHostConfig_url = async (
|
||||||
config: GenericGitHostConnectionConfig,
|
config: GenericGitHostConnectionConfig,
|
||||||
orgId: number,
|
|
||||||
connectionId: number,
|
connectionId: number,
|
||||||
): Promise<CompileResult> => {
|
): Promise<CompileResult> => {
|
||||||
const remoteUrl = new URL(config.url);
|
const remoteUrl = new URL(config.url);
|
||||||
|
|
@ -571,7 +561,7 @@ export const compileGenericGitHostConfig_url = async (
|
||||||
const repoName = path.join(remoteUrl.host, remoteUrl.pathname.replace(/\.git$/, ''));
|
const repoName = path.join(remoteUrl.host, remoteUrl.pathname.replace(/\.git$/, ''));
|
||||||
|
|
||||||
const repo: RepoData = {
|
const repo: RepoData = {
|
||||||
external_codeHostType: 'generic-git-host',
|
external_codeHostType: 'genericGitHost',
|
||||||
external_codeHostUrl: remoteUrl.origin,
|
external_codeHostUrl: remoteUrl.origin,
|
||||||
external_id: remoteUrl.toString(),
|
external_id: remoteUrl.toString(),
|
||||||
cloneUrl: remoteUrl.toString(),
|
cloneUrl: remoteUrl.toString(),
|
||||||
|
|
@ -581,7 +571,7 @@ export const compileGenericGitHostConfig_url = async (
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
org: {
|
org: {
|
||||||
connect: {
|
connect: {
|
||||||
id: orgId,
|
id: SINGLE_TENANT_ORG_ID,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
connections: {
|
connections: {
|
||||||
|
|
@ -603,11 +593,9 @@ export const compileGenericGitHostConfig_url = async (
|
||||||
|
|
||||||
export const compileAzureDevOpsConfig = async (
|
export const compileAzureDevOpsConfig = async (
|
||||||
config: AzureDevOpsConnectionConfig,
|
config: AzureDevOpsConnectionConfig,
|
||||||
connectionId: number,
|
connectionId: number): Promise<CompileResult> => {
|
||||||
orgId: number,
|
|
||||||
db: PrismaClient): Promise<CompileResult> => {
|
|
||||||
|
|
||||||
const azureDevOpsReposResult = await getAzureDevOpsReposFromConfig(config, orgId, db);
|
const azureDevOpsReposResult = await getAzureDevOpsReposFromConfig(config);
|
||||||
const azureDevOpsRepos = azureDevOpsReposResult.repos;
|
const azureDevOpsRepos = azureDevOpsReposResult.repos;
|
||||||
const warnings = azureDevOpsReposResult.warnings;
|
const warnings = azureDevOpsReposResult.warnings;
|
||||||
|
|
||||||
|
|
@ -651,7 +639,7 @@ export const compileAzureDevOpsConfig = async (
|
||||||
isPublic: isPublic,
|
isPublic: isPublic,
|
||||||
org: {
|
org: {
|
||||||
connect: {
|
connect: {
|
||||||
id: orgId,
|
id: SINGLE_TENANT_ORG_ID,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
connections: {
|
connections: {
|
||||||
|
|
|
||||||
|
|
@ -290,7 +290,7 @@ export class RepoIndexManager {
|
||||||
|
|
||||||
const metadata = repoMetadataSchema.parse(repo.metadata);
|
const metadata = repoMetadataSchema.parse(repo.metadata);
|
||||||
|
|
||||||
const credentials = await getAuthCredentialsForRepo(repo, this.db);
|
const credentials = await getAuthCredentialsForRepo(repo);
|
||||||
const cloneUrlMaybeWithToken = credentials?.cloneUrlWithToken ?? repo.cloneUrl;
|
const cloneUrlMaybeWithToken = credentials?.cloneUrlWithToken ?? repo.cloneUrl;
|
||||||
const authHeader = credentials?.authHeader ?? undefined;
|
const authHeader = credentials?.authHeader ?? undefined;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Logger } from "winston";
|
import { Logger } from "winston";
|
||||||
import { RepoAuthCredentials, RepoWithConnections } from "./types.js";
|
import { RepoAuthCredentials, RepoWithConnections } from "./types.js";
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { PrismaClient, Repo } from "@sourcebot/db";
|
import { Repo } from "@sourcebot/db";
|
||||||
import { getTokenFromConfig } from "@sourcebot/crypto";
|
import { getTokenFromConfig } from "@sourcebot/crypto";
|
||||||
import * as Sentry from "@sentry/node";
|
import * as Sentry from "@sentry/node";
|
||||||
import { GithubConnectionConfig, GitlabConnectionConfig, GiteaConnectionConfig, BitbucketConnectionConfig, AzureDevOpsConnectionConfig } from '@sourcebot/schemas/v3/connection.type';
|
import { GithubConnectionConfig, GitlabConnectionConfig, GiteaConnectionConfig, BitbucketConnectionConfig, AzureDevOpsConnectionConfig } from '@sourcebot/schemas/v3/connection.type';
|
||||||
|
|
@ -59,7 +59,7 @@ export const getRepoPath = (repo: Repo): { path: string, isReadOnly: boolean } =
|
||||||
// If we are dealing with a local repository, then use that as the path.
|
// If we are dealing with a local repository, then use that as the path.
|
||||||
// Mark as read-only since we aren't guaranteed to have write access to the local filesystem.
|
// Mark as read-only since we aren't guaranteed to have write access to the local filesystem.
|
||||||
const cloneUrl = new URL(repo.cloneUrl);
|
const cloneUrl = new URL(repo.cloneUrl);
|
||||||
if (repo.external_codeHostType === 'generic-git-host' && cloneUrl.protocol === 'file:') {
|
if (repo.external_codeHostType === 'genericGitHost' && cloneUrl.protocol === 'file:') {
|
||||||
return {
|
return {
|
||||||
path: cloneUrl.pathname,
|
path: cloneUrl.pathname,
|
||||||
isReadOnly: true,
|
isReadOnly: true,
|
||||||
|
|
@ -110,7 +110,7 @@ export const fetchWithRetry = async <T>(
|
||||||
// fetch the token here using the connections from the repo. Multiple connections could be referencing this repo, and each
|
// fetch the token here using the connections from the repo. Multiple connections could be referencing this repo, and each
|
||||||
// may have their own token. This method will just pick the first connection that has a token (if one exists) and uses that. This
|
// may have their own token. This method will just pick the first connection that has a token (if one exists) and uses that. This
|
||||||
// may technically cause syncing to fail if that connection's token just so happens to not have access to the repo it's referencing.
|
// may technically cause syncing to fail if that connection's token just so happens to not have access to the repo it's referencing.
|
||||||
export const getAuthCredentialsForRepo = async (repo: RepoWithConnections, db: PrismaClient, logger?: Logger): Promise<RepoAuthCredentials | undefined> => {
|
export const getAuthCredentialsForRepo = async (repo: RepoWithConnections, logger?: Logger): Promise<RepoAuthCredentials | undefined> => {
|
||||||
// If we have github apps configured we assume that we must use them for github service auth
|
// If we have github apps configured we assume that we must use them for github service auth
|
||||||
if (repo.external_codeHostType === 'github' && hasEntitlement('github-app') && GithubAppManager.getInstance().appsConfigured()) {
|
if (repo.external_codeHostType === 'github' && hasEntitlement('github-app') && GithubAppManager.getInstance().appsConfigured()) {
|
||||||
logger?.debug(`Using GitHub App for service auth for repo ${repo.displayName} hosted at ${repo.external_codeHostUrl}`);
|
logger?.debug(`Using GitHub App for service auth for repo ${repo.displayName} hosted at ${repo.external_codeHostUrl}`);
|
||||||
|
|
@ -139,7 +139,7 @@ export const getAuthCredentialsForRepo = async (repo: RepoWithConnections, db: P
|
||||||
if (connection.connectionType === 'github') {
|
if (connection.connectionType === 'github') {
|
||||||
const config = connection.config as unknown as GithubConnectionConfig;
|
const config = connection.config as unknown as GithubConnectionConfig;
|
||||||
if (config.token) {
|
if (config.token) {
|
||||||
const token = await getTokenFromConfig(config.token, connection.orgId, db);
|
const token = await getTokenFromConfig(config.token);
|
||||||
return {
|
return {
|
||||||
hostUrl: config.url,
|
hostUrl: config.url,
|
||||||
token,
|
token,
|
||||||
|
|
@ -154,7 +154,7 @@ export const getAuthCredentialsForRepo = async (repo: RepoWithConnections, db: P
|
||||||
} else if (connection.connectionType === 'gitlab') {
|
} else if (connection.connectionType === 'gitlab') {
|
||||||
const config = connection.config as unknown as GitlabConnectionConfig;
|
const config = connection.config as unknown as GitlabConnectionConfig;
|
||||||
if (config.token) {
|
if (config.token) {
|
||||||
const token = await getTokenFromConfig(config.token, connection.orgId, db);
|
const token = await getTokenFromConfig(config.token);
|
||||||
return {
|
return {
|
||||||
hostUrl: config.url,
|
hostUrl: config.url,
|
||||||
token,
|
token,
|
||||||
|
|
@ -170,7 +170,7 @@ export const getAuthCredentialsForRepo = async (repo: RepoWithConnections, db: P
|
||||||
} else if (connection.connectionType === 'gitea') {
|
} else if (connection.connectionType === 'gitea') {
|
||||||
const config = connection.config as unknown as GiteaConnectionConfig;
|
const config = connection.config as unknown as GiteaConnectionConfig;
|
||||||
if (config.token) {
|
if (config.token) {
|
||||||
const token = await getTokenFromConfig(config.token, connection.orgId, db);
|
const token = await getTokenFromConfig(config.token);
|
||||||
return {
|
return {
|
||||||
hostUrl: config.url,
|
hostUrl: config.url,
|
||||||
token,
|
token,
|
||||||
|
|
@ -185,7 +185,7 @@ export const getAuthCredentialsForRepo = async (repo: RepoWithConnections, db: P
|
||||||
} else if (connection.connectionType === 'bitbucket') {
|
} else if (connection.connectionType === 'bitbucket') {
|
||||||
const config = connection.config as unknown as BitbucketConnectionConfig;
|
const config = connection.config as unknown as BitbucketConnectionConfig;
|
||||||
if (config.token) {
|
if (config.token) {
|
||||||
const token = await getTokenFromConfig(config.token, connection.orgId, db);
|
const token = await getTokenFromConfig(config.token);
|
||||||
const username = config.user ?? 'x-token-auth';
|
const username = config.user ?? 'x-token-auth';
|
||||||
return {
|
return {
|
||||||
hostUrl: config.url,
|
hostUrl: config.url,
|
||||||
|
|
@ -202,7 +202,7 @@ export const getAuthCredentialsForRepo = async (repo: RepoWithConnections, db: P
|
||||||
} else if (connection.connectionType === 'azuredevops') {
|
} else if (connection.connectionType === 'azuredevops') {
|
||||||
const config = connection.config as unknown as AzureDevOpsConnectionConfig;
|
const config = connection.config as unknown as AzureDevOpsConnectionConfig;
|
||||||
if (config.token) {
|
if (config.token) {
|
||||||
const token = await getTokenFromConfig(config.token, connection.orgId, db);
|
const token = await getTokenFromConfig(config.token);
|
||||||
|
|
||||||
// For ADO server, multiple auth schemes may be supported. If the ADO deployment supports NTLM, the git clone will default
|
// For ADO server, multiple auth schemes may be supported. If the ADO deployment supports NTLM, the git clone will default
|
||||||
// to this over basic auth. As a result, we cannot embed the token in the clone URL and must force basic auth by passing in the token
|
// to this over basic auth. As a result, we cannot embed the token in the clone URL and must force basic auth by passing in the token
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,7 @@
|
||||||
import { PrismaClient } from "@sourcebot/db";
|
|
||||||
import { Token } from "@sourcebot/schemas/v3/shared.type";
|
import { Token } from "@sourcebot/schemas/v3/shared.type";
|
||||||
import { decrypt } from "./index.js";
|
|
||||||
|
|
||||||
export const getTokenFromConfig = async (token: Token, orgId: number, db: PrismaClient) => {
|
export const getTokenFromConfig = async (token: Token) => {
|
||||||
if ('secret' in token) {
|
if ('env' in token) {
|
||||||
const secretKey = token.secret;
|
|
||||||
const secret = await db.secret.findUnique({
|
|
||||||
where: {
|
|
||||||
orgId_key: {
|
|
||||||
key: secretKey,
|
|
||||||
orgId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!secret) {
|
|
||||||
throw new Error(`Secret with key ${secretKey} not found for org ${orgId}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const decryptedToken = decrypt(secret.iv, secret.encryptedValue);
|
|
||||||
return decryptedToken;
|
|
||||||
} else if ('env' in token) {
|
|
||||||
const envToken = process.env[token.env];
|
const envToken = process.env[token.env];
|
||||||
if (!envToken) {
|
if (!envToken) {
|
||||||
throw new Error(`Environment variable ${token.env} not found.`);
|
throw new Error(`Environment variable ${token.env} not found.`);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
Migrates the `connectionType` column from text to a enum. The values in this field are known to
|
||||||
|
be one of the following: github, gitlab, gitea, gerrit, bitbucket, azuredevops, git.
|
||||||
|
|
||||||
|
This is occording to what we would expect to be in a valid config file for the schema version at commit 4899c9fbc755851af2ddcce99f4a4200f2faa4f6.
|
||||||
|
See: https://github.com/sourcebot-dev/sourcebot/blob/4899c9fbc755851af2ddcce99f4a4200f2faa4f6/packages/schemas/src/v3/connection.type.ts#L3
|
||||||
|
*/
|
||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "ConnectionType" AS ENUM ('github', 'gitlab', 'gitea', 'gerrit', 'bitbucket', 'azuredevops', 'git');
|
||||||
|
|
||||||
|
-- AlterTable - Convert existing column to enum type without dropping data
|
||||||
|
ALTER TABLE "Connection"
|
||||||
|
ALTER COLUMN "connectionType" TYPE "ConnectionType"
|
||||||
|
USING "connectionType"::text::"ConnectionType";
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
Migrates the `external_codeHostType` column from text to a enum. The values in this field are known to
|
||||||
|
be one of the following: github, gitlab, gitea, gerrit, bitbucket-server, bitbucket-cloud, generic-git-host, azuredevops.
|
||||||
|
|
||||||
|
This is occording to what we would expect to be in the database written as of commit 4899c9fbc755851af2ddcce99f4a4200f2faa4f6.
|
||||||
|
See:
|
||||||
|
- https://github.com/sourcebot-dev/sourcebot/blob/4899c9fbc755851af2ddcce99f4a4200f2faa4f6/packages/backend/src/repoCompileUtils.ts#L57
|
||||||
|
- https://github.com/sourcebot-dev/sourcebot/blob/4899c9fbc755851af2ddcce99f4a4200f2faa4f6/packages/backend/src/repoCompileUtils.ts#L135
|
||||||
|
- https://github.com/sourcebot-dev/sourcebot/blob/4899c9fbc755851af2ddcce99f4a4200f2faa4f6/packages/backend/src/repoCompileUtils.ts#L208
|
||||||
|
- https://github.com/sourcebot-dev/sourcebot/blob/4899c9fbc755851af2ddcce99f4a4200f2faa4f6/packages/backend/src/repoCompileUtils.ts#L291
|
||||||
|
- https://github.com/sourcebot-dev/sourcebot/blob/4899c9fbc755851af2ddcce99f4a4200f2faa4f6/packages/backend/src/repoCompileUtils.ts#L407
|
||||||
|
- https://github.com/sourcebot-dev/sourcebot/blob/4899c9fbc755851af2ddcce99f4a4200f2faa4f6/packages/backend/src/repoCompileUtils.ts#L510
|
||||||
|
- https://github.com/sourcebot-dev/sourcebot/blob/4899c9fbc755851af2ddcce99f4a4200f2faa4f6/packages/backend/src/repoCompileUtils.ts#L574
|
||||||
|
- https://github.com/sourcebot-dev/sourcebot/blob/4899c9fbc755851af2ddcce99f4a4200f2faa4f6/packages/backend/src/repoCompileUtils.ts#L642
|
||||||
|
*/
|
||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "CodeHostType" AS ENUM ('github', 'gitlab', 'gitea', 'gerrit', 'bitbucket-server', 'bitbucket-cloud', 'generic-git-host', 'azuredevops');
|
||||||
|
|
||||||
|
-- AlterTable - Convert existing column to enum type without dropping data
|
||||||
|
ALTER TABLE "Repo"
|
||||||
|
ALTER COLUMN "external_codeHostType" TYPE "CodeHostType"
|
||||||
|
USING "external_codeHostType"::text::"CodeHostType";
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- You are about to drop the `Secret` table. If the table is not empty, all the data it contains will be lost.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "Secret" DROP CONSTRAINT "Secret_orgId_fkey";
|
||||||
|
|
||||||
|
-- DropTable
|
||||||
|
DROP TABLE "Secret";
|
||||||
|
|
@ -29,6 +29,21 @@ enum ChatVisibility {
|
||||||
PUBLIC
|
PUBLIC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @note: The @map annotation is required to maintain backwards compatibility
|
||||||
|
/// with the existing database.
|
||||||
|
/// @note: In the generated client, these mapped values will be in pascalCase.
|
||||||
|
/// This behaviour will change in prisma v7. See: https://github.com/prisma/prisma/issues/8446#issuecomment-3356119713
|
||||||
|
enum CodeHostType {
|
||||||
|
github
|
||||||
|
gitlab
|
||||||
|
gitea
|
||||||
|
gerrit
|
||||||
|
bitbucketServer @map("bitbucket-server")
|
||||||
|
bitbucketCloud @map("bitbucket-cloud")
|
||||||
|
genericGitHost @map("generic-git-host")
|
||||||
|
azuredevops
|
||||||
|
}
|
||||||
|
|
||||||
model Repo {
|
model Repo {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
name String /// Full repo name, including the vcs hostname (ex. github.com/sourcebot-dev/sourcebot)
|
name String /// Full repo name, including the vcs hostname (ex. github.com/sourcebot-dev/sourcebot)
|
||||||
|
|
@ -53,7 +68,7 @@ model Repo {
|
||||||
indexedCommitHash String? /// The commit hash of the last indexed commit (on HEAD).
|
indexedCommitHash String? /// The commit hash of the last indexed commit (on HEAD).
|
||||||
|
|
||||||
external_id String /// The id of the repo in the external service
|
external_id String /// The id of the repo in the external service
|
||||||
external_codeHostType String /// The type of the external service (e.g., github, gitlab, etc.)
|
external_codeHostType CodeHostType /// The type of the external service (e.g., github, gitlab, etc.)
|
||||||
external_codeHostUrl String /// The base url of the external service (e.g., https://github.com)
|
external_codeHostUrl String /// The base url of the external service (e.g., https://github.com)
|
||||||
|
|
||||||
org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||||||
|
|
@ -125,6 +140,18 @@ model SearchContext {
|
||||||
@@unique([name, orgId])
|
@@unique([name, orgId])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Matches the union of `type` fields in the schema.
|
||||||
|
/// @see: schemas/v3/connection.type.ts
|
||||||
|
enum ConnectionType {
|
||||||
|
github
|
||||||
|
gitlab
|
||||||
|
gitea
|
||||||
|
gerrit
|
||||||
|
bitbucket
|
||||||
|
azuredevops
|
||||||
|
git
|
||||||
|
}
|
||||||
|
|
||||||
model Connection {
|
model Connection {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
name String
|
name String
|
||||||
|
|
@ -135,7 +162,7 @@ model Connection {
|
||||||
repos RepoToConnection[]
|
repos RepoToConnection[]
|
||||||
|
|
||||||
// The type of connection (e.g., github, gitlab, etc.)
|
// The type of connection (e.g., github, gitlab, etc.)
|
||||||
connectionType String
|
connectionType ConnectionType
|
||||||
|
|
||||||
syncJobs ConnectionSyncJob[]
|
syncJobs ConnectionSyncJob[]
|
||||||
/// When the connection was last synced successfully.
|
/// When the connection was last synced successfully.
|
||||||
|
|
@ -226,7 +253,6 @@ model Org {
|
||||||
members UserToOrg[]
|
members UserToOrg[]
|
||||||
connections Connection[]
|
connections Connection[]
|
||||||
repos Repo[]
|
repos Repo[]
|
||||||
secrets Secret[]
|
|
||||||
apiKeys ApiKey[]
|
apiKeys ApiKey[]
|
||||||
isOnboarded Boolean @default(false)
|
isOnboarded Boolean @default(false)
|
||||||
imageUrl String?
|
imageUrl String?
|
||||||
|
|
@ -276,19 +302,6 @@ model UserToOrg {
|
||||||
@@id([orgId, userId])
|
@@id([orgId, userId])
|
||||||
}
|
}
|
||||||
|
|
||||||
model Secret {
|
|
||||||
orgId Int
|
|
||||||
key String
|
|
||||||
encryptedValue String
|
|
||||||
iv String
|
|
||||||
|
|
||||||
createdAt DateTime @default(now())
|
|
||||||
|
|
||||||
org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
|
||||||
|
|
||||||
@@id([orgId, key])
|
|
||||||
}
|
|
||||||
|
|
||||||
model ApiKey {
|
model ApiKey {
|
||||||
name String
|
name String
|
||||||
hash String @id @unique
|
hash String @id @unique
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,6 @@ const schema = {
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -273,7 +272,6 @@ const schema = {
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token.",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -464,7 +462,6 @@ const schema = {
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An access token.",
|
"description": "An access token.",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -778,7 +775,6 @@ const schema = {
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -975,7 +971,6 @@ const schema = {
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token.",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -1166,7 +1161,6 @@ const schema = {
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An access token.",
|
"description": "An access token.",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -1562,7 +1556,6 @@ const schema = {
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -1759,7 +1752,6 @@ const schema = {
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token.",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
@ -1950,7 +1942,6 @@ const schema = {
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An access token.",
|
"description": "An access token.",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{
|
{
|
||||||
"env": "ENV_VAR_CONTAINING_TOKEN"
|
"env": "ENV_VAR_CONTAINING_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,19 +27,6 @@ const schema = {
|
||||||
"privateKey": {
|
"privateKey": {
|
||||||
"description": "The private key of the GitHub App.",
|
"description": "The private key of the GitHub App.",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -89,19 +76,6 @@ const schema = {
|
||||||
"privateKey": {
|
"privateKey": {
|
||||||
"description": "The private key of the GitHub App.",
|
"description": "The private key of the GitHub App.",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -18,17 +18,10 @@ export interface GitHubAppConfig {
|
||||||
/**
|
/**
|
||||||
* The private key of the GitHub App.
|
* The private key of the GitHub App.
|
||||||
*/
|
*/
|
||||||
privateKey:
|
privateKey: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,25 +10,7 @@ const schema = {
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -8,19 +8,12 @@ export interface AzureDevOpsConnectionConfig {
|
||||||
/**
|
/**
|
||||||
* A Personal Access Token (PAT).
|
* A Personal Access Token (PAT).
|
||||||
*/
|
*/
|
||||||
token:
|
token: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* The URL of the Azure DevOps host. For Azure DevOps Cloud, use https://dev.azure.com. For Azure DevOps Server, use your server URL.
|
* The URL of the Azure DevOps host. For Azure DevOps Cloud, use https://dev.azure.com. For Azure DevOps Server, use your server URL.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -14,25 +14,7 @@ const schema = {
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token.",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -12,19 +12,12 @@ export interface BitbucketConnectionConfig {
|
||||||
/**
|
/**
|
||||||
* An authentication token.
|
* An authentication token.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Bitbucket URL
|
* Bitbucket URL
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -14,25 +14,7 @@ const schema = {
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -227,25 +209,7 @@ const schema = {
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token.",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -434,25 +398,7 @@ const schema = {
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -706,25 +652,7 @@ const schema = {
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token.",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -879,25 +807,7 @@ const schema = {
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -17,19 +17,12 @@ export interface GithubConnectionConfig {
|
||||||
/**
|
/**
|
||||||
* A Personal Access Token (PAT).
|
* A Personal Access Token (PAT).
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* The URL of the GitHub host. Defaults to https://github.com
|
* The URL of the GitHub host. Defaults to https://github.com
|
||||||
*/
|
*/
|
||||||
|
|
@ -106,19 +99,12 @@ export interface GitlabConnectionConfig {
|
||||||
/**
|
/**
|
||||||
* An authentication token.
|
* An authentication token.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* The URL of the GitLab host. Defaults to https://gitlab.com
|
* The URL of the GitLab host. Defaults to https://gitlab.com
|
||||||
*/
|
*/
|
||||||
|
|
@ -177,19 +163,12 @@ export interface GiteaConnectionConfig {
|
||||||
/**
|
/**
|
||||||
* A Personal Access Token (PAT).
|
* A Personal Access Token (PAT).
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* The URL of the Gitea host. Defaults to https://gitea.com
|
* The URL of the Gitea host. Defaults to https://gitea.com
|
||||||
*/
|
*/
|
||||||
|
|
@ -263,19 +242,12 @@ export interface BitbucketConnectionConfig {
|
||||||
/**
|
/**
|
||||||
* An authentication token.
|
* An authentication token.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Bitbucket URL
|
* Bitbucket URL
|
||||||
*/
|
*/
|
||||||
|
|
@ -320,19 +292,12 @@ export interface AzureDevOpsConnectionConfig {
|
||||||
/**
|
/**
|
||||||
* A Personal Access Token (PAT).
|
* A Personal Access Token (PAT).
|
||||||
*/
|
*/
|
||||||
token:
|
token: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* The URL of the Azure DevOps host. For Azure DevOps Cloud, use https://dev.azure.com. For Azure DevOps Server, use your server URL.
|
* The URL of the Azure DevOps host. For Azure DevOps Cloud, use https://dev.azure.com. For Azure DevOps Server, use your server URL.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -10,25 +10,7 @@ const schema = {
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -8,19 +8,12 @@ export interface GiteaConnectionConfig {
|
||||||
/**
|
/**
|
||||||
* A Personal Access Token (PAT).
|
* A Personal Access Token (PAT).
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* The URL of the Gitea host. Defaults to https://gitea.com
|
* The URL of the Gitea host. Defaults to https://gitea.com
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -10,25 +10,7 @@ const schema = {
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -8,19 +8,12 @@ export interface GithubConnectionConfig {
|
||||||
/**
|
/**
|
||||||
* A Personal Access Token (PAT).
|
* A Personal Access Token (PAT).
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* The URL of the GitHub host. Defaults to https://github.com
|
* The URL of the GitHub host. Defaults to https://github.com
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -10,25 +10,7 @@ const schema = {
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token.",
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -8,19 +8,12 @@ export interface GitlabConnectionConfig {
|
||||||
/**
|
/**
|
||||||
* An authentication token.
|
* An authentication token.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* The URL of the GitLab host. Defaults to https://gitlab.com
|
* The URL of the GitLab host. Defaults to https://gitlab.com
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -167,19 +167,12 @@ export interface GithubConnectionConfig {
|
||||||
/**
|
/**
|
||||||
* A Personal Access Token (PAT).
|
* A Personal Access Token (PAT).
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* The URL of the GitHub host. Defaults to https://github.com
|
* The URL of the GitHub host. Defaults to https://github.com
|
||||||
*/
|
*/
|
||||||
|
|
@ -256,19 +249,12 @@ export interface GitlabConnectionConfig {
|
||||||
/**
|
/**
|
||||||
* An authentication token.
|
* An authentication token.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* The URL of the GitLab host. Defaults to https://gitlab.com
|
* The URL of the GitLab host. Defaults to https://gitlab.com
|
||||||
*/
|
*/
|
||||||
|
|
@ -327,19 +313,12 @@ export interface GiteaConnectionConfig {
|
||||||
/**
|
/**
|
||||||
* A Personal Access Token (PAT).
|
* A Personal Access Token (PAT).
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* The URL of the Gitea host. Defaults to https://gitea.com
|
* The URL of the Gitea host. Defaults to https://gitea.com
|
||||||
*/
|
*/
|
||||||
|
|
@ -413,19 +392,12 @@ export interface BitbucketConnectionConfig {
|
||||||
/**
|
/**
|
||||||
* An authentication token.
|
* An authentication token.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Bitbucket URL
|
* Bitbucket URL
|
||||||
*/
|
*/
|
||||||
|
|
@ -470,19 +442,12 @@ export interface AzureDevOpsConnectionConfig {
|
||||||
/**
|
/**
|
||||||
* A Personal Access Token (PAT).
|
* A Personal Access Token (PAT).
|
||||||
*/
|
*/
|
||||||
token:
|
token: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* The URL of the Azure DevOps host. For Azure DevOps Cloud, use https://dev.azure.com. For Azure DevOps Server, use your server URL.
|
* The URL of the Azure DevOps host. For Azure DevOps Cloud, use https://dev.azure.com. For Azure DevOps Server, use your server URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -563,51 +528,30 @@ export interface AmazonBedrockLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional access key ID to use with the model. Defaults to the `AWS_ACCESS_KEY_ID` environment variable.
|
* Optional access key ID to use with the model. Defaults to the `AWS_ACCESS_KEY_ID` environment variable.
|
||||||
*/
|
*/
|
||||||
accessKeyId?:
|
accessKeyId?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional secret access key to use with the model. Defaults to the `AWS_SECRET_ACCESS_KEY` environment variable.
|
* Optional secret access key to use with the model. Defaults to the `AWS_SECRET_ACCESS_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
accessKeySecret?:
|
accessKeySecret?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional session token to use with the model. Defaults to the `AWS_SESSION_TOKEN` environment variable.
|
* Optional session token to use with the model. Defaults to the `AWS_SESSION_TOKEN` environment variable.
|
||||||
*/
|
*/
|
||||||
sessionToken?:
|
sessionToken?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* The AWS region. Defaults to the `AWS_REGION` environment variable.
|
* The AWS region. Defaults to the `AWS_REGION` environment variable.
|
||||||
*/
|
*/
|
||||||
|
|
@ -628,20 +572,12 @@ export interface LanguageModelHeaders {
|
||||||
*/
|
*/
|
||||||
[k: string]:
|
[k: string]:
|
||||||
| string
|
| string
|
||||||
| (
|
| {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
export interface AnthropicLanguageModel {
|
export interface AnthropicLanguageModel {
|
||||||
/**
|
/**
|
||||||
|
|
@ -659,19 +595,12 @@ export interface AnthropicLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `ANTHROPIC_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `ANTHROPIC_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -698,19 +627,12 @@ export interface AzureLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `AZURE_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `AZURE_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Sets a custom api version. Defaults to `preview`.
|
* Sets a custom api version. Defaults to `preview`.
|
||||||
*/
|
*/
|
||||||
|
|
@ -737,19 +659,12 @@ export interface DeepSeekLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `DEEPSEEK_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `DEEPSEEK_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -772,19 +687,12 @@ export interface GoogleGenerativeAILanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `GOOGLE_GENERATIVE_AI_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `GOOGLE_GENERATIVE_AI_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -815,19 +723,12 @@ export interface GoogleVertexAnthropicLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional file path to service account credentials JSON. Defaults to the `GOOGLE_APPLICATION_CREDENTIALS` environment variable or application default credentials.
|
* Optional file path to service account credentials JSON. Defaults to the `GOOGLE_APPLICATION_CREDENTIALS` environment variable or application default credentials.
|
||||||
*/
|
*/
|
||||||
credentials?:
|
credentials?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -858,19 +759,12 @@ export interface GoogleVertexLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional file path to service account credentials JSON. Defaults to the `GOOGLE_APPLICATION_CREDENTIALS` environment variable or application default credentials.
|
* Optional file path to service account credentials JSON. Defaults to the `GOOGLE_APPLICATION_CREDENTIALS` environment variable or application default credentials.
|
||||||
*/
|
*/
|
||||||
credentials?:
|
credentials?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -893,19 +787,12 @@ export interface MistralLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `MISTRAL_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `MISTRAL_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -928,19 +815,12 @@ export interface OpenAILanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `OPENAI_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `OPENAI_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -967,19 +847,12 @@ export interface OpenAICompatibleLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key. If specified, adds an `Authorization` header to request headers with the value Bearer <token>.
|
* Optional API key. If specified, adds an `Authorization` header to request headers with the value Bearer <token>.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Base URL of the OpenAI-compatible chat completions API endpoint.
|
* Base URL of the OpenAI-compatible chat completions API endpoint.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1001,20 +874,12 @@ export interface LanguageModelQueryParams {
|
||||||
*/
|
*/
|
||||||
[k: string]:
|
[k: string]:
|
||||||
| string
|
| string
|
||||||
| (
|
| {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
export interface OpenRouterLanguageModel {
|
export interface OpenRouterLanguageModel {
|
||||||
/**
|
/**
|
||||||
|
|
@ -1032,19 +897,12 @@ export interface OpenRouterLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `OPENROUTER_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `OPENROUTER_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1067,19 +925,12 @@ export interface XaiLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `XAI_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `XAI_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1102,19 +953,12 @@ export interface GitHubAppConfig {
|
||||||
/**
|
/**
|
||||||
* The private key of the GitHub App.
|
* The private key of the GitHub App.
|
||||||
*/
|
*/
|
||||||
privateKey:
|
privateKey: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
export interface GitHubIdentityProviderConfig {
|
export interface GitHubIdentityProviderConfig {
|
||||||
provider: "github";
|
provider: "github";
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -30,51 +30,30 @@ export interface AmazonBedrockLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional access key ID to use with the model. Defaults to the `AWS_ACCESS_KEY_ID` environment variable.
|
* Optional access key ID to use with the model. Defaults to the `AWS_ACCESS_KEY_ID` environment variable.
|
||||||
*/
|
*/
|
||||||
accessKeyId?:
|
accessKeyId?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional secret access key to use with the model. Defaults to the `AWS_SECRET_ACCESS_KEY` environment variable.
|
* Optional secret access key to use with the model. Defaults to the `AWS_SECRET_ACCESS_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
accessKeySecret?:
|
accessKeySecret?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional session token to use with the model. Defaults to the `AWS_SESSION_TOKEN` environment variable.
|
* Optional session token to use with the model. Defaults to the `AWS_SESSION_TOKEN` environment variable.
|
||||||
*/
|
*/
|
||||||
sessionToken?:
|
sessionToken?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* The AWS region. Defaults to the `AWS_REGION` environment variable.
|
* The AWS region. Defaults to the `AWS_REGION` environment variable.
|
||||||
*/
|
*/
|
||||||
|
|
@ -95,20 +74,12 @@ export interface LanguageModelHeaders {
|
||||||
*/
|
*/
|
||||||
[k: string]:
|
[k: string]:
|
||||||
| string
|
| string
|
||||||
| (
|
| {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
export interface AnthropicLanguageModel {
|
export interface AnthropicLanguageModel {
|
||||||
/**
|
/**
|
||||||
|
|
@ -126,19 +97,12 @@ export interface AnthropicLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `ANTHROPIC_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `ANTHROPIC_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -165,19 +129,12 @@ export interface AzureLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `AZURE_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `AZURE_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Sets a custom api version. Defaults to `preview`.
|
* Sets a custom api version. Defaults to `preview`.
|
||||||
*/
|
*/
|
||||||
|
|
@ -204,19 +161,12 @@ export interface DeepSeekLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `DEEPSEEK_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `DEEPSEEK_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -239,19 +189,12 @@ export interface GoogleGenerativeAILanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `GOOGLE_GENERATIVE_AI_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `GOOGLE_GENERATIVE_AI_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -282,19 +225,12 @@ export interface GoogleVertexAnthropicLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional file path to service account credentials JSON. Defaults to the `GOOGLE_APPLICATION_CREDENTIALS` environment variable or application default credentials.
|
* Optional file path to service account credentials JSON. Defaults to the `GOOGLE_APPLICATION_CREDENTIALS` environment variable or application default credentials.
|
||||||
*/
|
*/
|
||||||
credentials?:
|
credentials?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -325,19 +261,12 @@ export interface GoogleVertexLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional file path to service account credentials JSON. Defaults to the `GOOGLE_APPLICATION_CREDENTIALS` environment variable or application default credentials.
|
* Optional file path to service account credentials JSON. Defaults to the `GOOGLE_APPLICATION_CREDENTIALS` environment variable or application default credentials.
|
||||||
*/
|
*/
|
||||||
credentials?:
|
credentials?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -360,19 +289,12 @@ export interface MistralLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `MISTRAL_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `MISTRAL_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -395,19 +317,12 @@ export interface OpenAILanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `OPENAI_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `OPENAI_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -434,19 +349,12 @@ export interface OpenAICompatibleLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key. If specified, adds an `Authorization` header to request headers with the value Bearer <token>.
|
* Optional API key. If specified, adds an `Authorization` header to request headers with the value Bearer <token>.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Base URL of the OpenAI-compatible chat completions API endpoint.
|
* Base URL of the OpenAI-compatible chat completions API endpoint.
|
||||||
*/
|
*/
|
||||||
|
|
@ -468,20 +376,12 @@ export interface LanguageModelQueryParams {
|
||||||
*/
|
*/
|
||||||
[k: string]:
|
[k: string]:
|
||||||
| string
|
| string
|
||||||
| (
|
| {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
export interface OpenRouterLanguageModel {
|
export interface OpenRouterLanguageModel {
|
||||||
/**
|
/**
|
||||||
|
|
@ -499,19 +399,12 @@ export interface OpenRouterLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `OPENROUTER_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `OPENROUTER_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -534,19 +427,12 @@ export interface XaiLanguageModel {
|
||||||
/**
|
/**
|
||||||
* Optional API key to use with the model. Defaults to the `XAI_API_KEY` environment variable.
|
* Optional API key to use with the model. Defaults to the `XAI_API_KEY` environment variable.
|
||||||
*/
|
*/
|
||||||
token?:
|
token?: {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Optional base URL.
|
* Optional base URL.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,6 @@ const schema = {
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"Token": {
|
"Token": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -85,19 +72,6 @@ const schema = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -129,19 +103,6 @@ const schema = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,12 @@
|
||||||
* This interface was referenced by `Shared`'s JSON-Schema
|
* This interface was referenced by `Shared`'s JSON-Schema
|
||||||
* via the `definition` "Token".
|
* via the `definition` "Token".
|
||||||
*/
|
*/
|
||||||
export type Token =
|
export type Token = {
|
||||||
| {
|
/**
|
||||||
/**
|
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
||||||
* The name of the secret that contains the token.
|
*/
|
||||||
*/
|
env: string;
|
||||||
secret: string;
|
};
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* The name of the environment variable that contains the token. Only supported in declarative connection configs.
|
|
||||||
*/
|
|
||||||
env: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface Shared {
|
export interface Shared {
|
||||||
[k: string]: unknown;
|
[k: string]: unknown;
|
||||||
|
|
|
||||||
|
|
@ -255,89 +255,6 @@ export const completeOnboarding = async (domain: string): Promise<{ success: boo
|
||||||
})
|
})
|
||||||
));
|
));
|
||||||
|
|
||||||
export const getSecrets = async (domain: string): Promise<{ createdAt: Date; key: string; }[] | ServiceError> => sew(() =>
|
|
||||||
withAuth((userId) =>
|
|
||||||
withOrgMembership(userId, domain, async ({ org }) => {
|
|
||||||
const secrets = await prisma.secret.findMany({
|
|
||||||
where: {
|
|
||||||
orgId: org.id,
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
key: true,
|
|
||||||
createdAt: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return secrets.map((secret) => ({
|
|
||||||
key: secret.key,
|
|
||||||
createdAt: secret.createdAt,
|
|
||||||
}));
|
|
||||||
})));
|
|
||||||
|
|
||||||
export const createSecret = async (key: string, value: string, domain: string): Promise<{ success: boolean } | ServiceError> => sew(() =>
|
|
||||||
withAuth((userId) =>
|
|
||||||
withOrgMembership(userId, domain, async ({ org }) => {
|
|
||||||
const encrypted = encrypt(value);
|
|
||||||
const existingSecret = await prisma.secret.findUnique({
|
|
||||||
where: {
|
|
||||||
orgId_key: {
|
|
||||||
orgId: org.id,
|
|
||||||
key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (existingSecret) {
|
|
||||||
return secretAlreadyExists();
|
|
||||||
}
|
|
||||||
|
|
||||||
await prisma.secret.create({
|
|
||||||
data: {
|
|
||||||
orgId: org.id,
|
|
||||||
key,
|
|
||||||
encryptedValue: encrypted.encryptedData,
|
|
||||||
iv: encrypted.iv,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
}
|
|
||||||
})));
|
|
||||||
|
|
||||||
export const checkIfSecretExists = async (key: string, domain: string): Promise<boolean | ServiceError> => sew(() =>
|
|
||||||
withAuth((userId) =>
|
|
||||||
withOrgMembership(userId, domain, async ({ org }) => {
|
|
||||||
const secret = await prisma.secret.findUnique({
|
|
||||||
where: {
|
|
||||||
orgId_key: {
|
|
||||||
orgId: org.id,
|
|
||||||
key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return !!secret;
|
|
||||||
})));
|
|
||||||
|
|
||||||
export const deleteSecret = async (key: string, domain: string): Promise<{ success: boolean } | ServiceError> => sew(() =>
|
|
||||||
withAuth((userId) =>
|
|
||||||
withOrgMembership(userId, domain, async ({ org }) => {
|
|
||||||
await prisma.secret.delete({
|
|
||||||
where: {
|
|
||||||
orgId_key: {
|
|
||||||
orgId: org.id,
|
|
||||||
key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
}
|
|
||||||
})));
|
|
||||||
|
|
||||||
export const verifyApiKey = async (apiKeyPayload: ApiKeyPayload): Promise<{ apiKey: ApiKey } | ServiceError> => sew(async () => {
|
export const verifyApiKey = async (apiKeyPayload: ApiKeyPayload): Promise<{ apiKey: ApiKey } | ServiceError> => sew(async () => {
|
||||||
const parts = apiKeyPayload.apiKey.split("-");
|
const parts = apiKeyPayload.apiKey.split("-");
|
||||||
if (parts.length !== 2 || parts[0] !== "sourcebot") {
|
if (parts.length !== 2 || parts[0] !== "sourcebot") {
|
||||||
|
|
@ -1778,21 +1695,21 @@ export const getRepoImage = async (repoId: number): Promise<ArrayBuffer | Servic
|
||||||
if (connection.connectionType === 'github') {
|
if (connection.connectionType === 'github') {
|
||||||
const config = connection.config as unknown as GithubConnectionConfig;
|
const config = connection.config as unknown as GithubConnectionConfig;
|
||||||
if (config.token) {
|
if (config.token) {
|
||||||
const token = await getTokenFromConfig(config.token, connection.orgId, prisma);
|
const token = await getTokenFromConfig(config.token);
|
||||||
authHeaders['Authorization'] = `token ${token}`;
|
authHeaders['Authorization'] = `token ${token}`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (connection.connectionType === 'gitlab') {
|
} else if (connection.connectionType === 'gitlab') {
|
||||||
const config = connection.config as unknown as GitlabConnectionConfig;
|
const config = connection.config as unknown as GitlabConnectionConfig;
|
||||||
if (config.token) {
|
if (config.token) {
|
||||||
const token = await getTokenFromConfig(config.token, connection.orgId, prisma);
|
const token = await getTokenFromConfig(config.token);
|
||||||
authHeaders['PRIVATE-TOKEN'] = token;
|
authHeaders['PRIVATE-TOKEN'] = token;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (connection.connectionType === 'gitea') {
|
} else if (connection.connectionType === 'gitea') {
|
||||||
const config = connection.config as unknown as GiteaConnectionConfig;
|
const config = connection.config as unknown as GiteaConnectionConfig;
|
||||||
if (config.token) {
|
if (config.token) {
|
||||||
const token = await getTokenFromConfig(config.token, connection.orgId, prisma);
|
const token = await getTokenFromConfig(config.token);
|
||||||
authHeaders['Authorization'] = `token ${token}`;
|
authHeaders['Authorization'] = `token ${token}`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ export const CodePreviewPanel = async ({ path, repoName, revisionName }: CodePre
|
||||||
branchDisplayName={revisionName}
|
branchDisplayName={revisionName}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{(fileWebUrl && codeHostInfo) && (
|
{fileWebUrl && (
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href={fileWebUrl}
|
href={fileWebUrl}
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,10 @@ import { Badge } from "@/components/ui/badge";
|
||||||
import { Card } from "@/components/ui/card";
|
import { Card } from "@/components/ui/card";
|
||||||
import { CardContent } from "@/components/ui/card";
|
import { CardContent } from "@/components/ui/card";
|
||||||
import { DemoExamples, DemoSearchExample, DemoSearchScope } from "@/types";
|
import { DemoExamples, DemoSearchExample, DemoSearchScope } from "@/types";
|
||||||
import { cn, CodeHostType, getCodeHostIcon } from "@/lib/utils";
|
import { cn, getCodeHostIcon } from "@/lib/utils";
|
||||||
import useCaptureEvent from "@/hooks/useCaptureEvent";
|
import useCaptureEvent from "@/hooks/useCaptureEvent";
|
||||||
import { SearchScopeInfoCard } from "@/features/chat/components/chatBox/searchScopeInfoCard";
|
import { SearchScopeInfoCard } from "@/features/chat/components/chatBox/searchScopeInfoCard";
|
||||||
|
import { CodeHostType } from "@sourcebot/db";
|
||||||
|
|
||||||
interface DemoCards {
|
interface DemoCards {
|
||||||
demoExamples: DemoExamples;
|
demoExamples: DemoExamples;
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ import { Separator } from "@/components/ui/separator";
|
||||||
import { Schema } from "ajv";
|
import { Schema } from "ajv";
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
||||||
import useCaptureEvent from "@/hooks/useCaptureEvent";
|
import useCaptureEvent from "@/hooks/useCaptureEvent";
|
||||||
import { CodeHostType } from "@/lib/utils";
|
|
||||||
import { useCodeMirrorTheme } from "@/hooks/useCodeMirrorTheme";
|
import { useCodeMirrorTheme } from "@/hooks/useCodeMirrorTheme";
|
||||||
|
import { CodeHostType } from "@sourcebot/db";
|
||||||
|
|
||||||
export type QuickActionFn<T> = (previous: T) => T;
|
export type QuickActionFn<T> = (previous: T) => T;
|
||||||
export type QuickAction<T> = {
|
export type QuickAction<T> = {
|
||||||
|
|
|
||||||
|
|
@ -1,314 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
import { checkIfSecretExists, createSecret } from "@/actions";
|
|
||||||
import { useToast } from "@/components/hooks/use-toast";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
|
||||||
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
|
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import { Separator } from "@/components/ui/separator";
|
|
||||||
import useCaptureEvent from "@/hooks/useCaptureEvent";
|
|
||||||
import { useDomain } from "@/hooks/useDomain";
|
|
||||||
import { CodeHostType, isServiceError } from "@/lib/utils";
|
|
||||||
import githubPatCreation from "@/public/github_pat_creation.png";
|
|
||||||
import gitlabPatCreation from "@/public/gitlab_pat_creation.png";
|
|
||||||
import giteaPatCreation from "@/public/gitea_pat_creation.png";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
|
||||||
import { Eye, EyeOff, Loader2 } from "lucide-react";
|
|
||||||
import Image from "next/image";
|
|
||||||
import Link from "next/link";
|
|
||||||
import { useCallback, useMemo, useState } from "react";
|
|
||||||
import { useForm } from "react-hook-form";
|
|
||||||
import { z } from "zod";
|
|
||||||
|
|
||||||
|
|
||||||
interface ImportSecretDialogProps {
|
|
||||||
open: boolean;
|
|
||||||
onOpenChange: (open: boolean) => void;
|
|
||||||
onSecretCreated: (key: string) => void;
|
|
||||||
codeHostType: CodeHostType;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const ImportSecretDialog = ({ open, onOpenChange, onSecretCreated, codeHostType }: ImportSecretDialogProps) => {
|
|
||||||
const [showValue, setShowValue] = useState(false);
|
|
||||||
const domain = useDomain();
|
|
||||||
const { toast } = useToast();
|
|
||||||
const captureEvent = useCaptureEvent();
|
|
||||||
|
|
||||||
const formSchema = z.object({
|
|
||||||
key: z.string().min(1).refine(async (key) => {
|
|
||||||
const doesSecretExist = await checkIfSecretExists(key, domain);
|
|
||||||
if(!isServiceError(doesSecretExist)) {
|
|
||||||
captureEvent('wa_secret_combobox_import_secret_fail', {
|
|
||||||
type: codeHostType,
|
|
||||||
error: "A secret with this key already exists.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return isServiceError(doesSecretExist) || !doesSecretExist;
|
|
||||||
}, "A secret with this key already exists."),
|
|
||||||
value: z.string().min(1),
|
|
||||||
});
|
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof formSchema>>({
|
|
||||||
resolver: zodResolver(formSchema),
|
|
||||||
defaultValues: {
|
|
||||||
key: "",
|
|
||||||
value: "",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const { isSubmitting } = form.formState;
|
|
||||||
|
|
||||||
const onSubmit = useCallback(async (data: z.infer<typeof formSchema>) => {
|
|
||||||
const response = await createSecret(data.key, data.value, domain);
|
|
||||||
if (isServiceError(response)) {
|
|
||||||
toast({
|
|
||||||
description: `❌ Failed to create secret. Reason: ${response.message}`
|
|
||||||
});
|
|
||||||
captureEvent('wa_secret_combobox_import_secret_fail', {
|
|
||||||
type: codeHostType,
|
|
||||||
error: response.message,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
toast({
|
|
||||||
description: `✅ Secret created successfully!`
|
|
||||||
});
|
|
||||||
captureEvent('wa_secret_combobox_import_secret_success', {
|
|
||||||
type: codeHostType,
|
|
||||||
});
|
|
||||||
form.reset();
|
|
||||||
onOpenChange(false);
|
|
||||||
onSecretCreated(data.key);
|
|
||||||
}
|
|
||||||
}, [domain, toast, onOpenChange, onSecretCreated, form, codeHostType, captureEvent]);
|
|
||||||
|
|
||||||
const codeHostSpecificStep = useMemo(() => {
|
|
||||||
switch (codeHostType) {
|
|
||||||
case 'github':
|
|
||||||
return <GitHubPATCreationStep step={1} />;
|
|
||||||
case 'gitlab':
|
|
||||||
return <GitLabPATCreationStep step={1} />;
|
|
||||||
case 'bitbucket-cloud':
|
|
||||||
return <BitbucketCloudPATCreationStep step={1} />;
|
|
||||||
case 'bitbucket-server':
|
|
||||||
return <BitbucketServerPATCreationStep step={1} />;
|
|
||||||
case 'gitea':
|
|
||||||
return <GiteaPATCreationStep step={1} />;
|
|
||||||
case 'gerrit':
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}, [codeHostType]);
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Dialog
|
|
||||||
open={open}
|
|
||||||
onOpenChange={onOpenChange}
|
|
||||||
>
|
|
||||||
<DialogContent
|
|
||||||
className="p-16 max-w-[90vw] sm:max-w-2xl max-h-[80vh] overflow-scroll rounded-lg"
|
|
||||||
>
|
|
||||||
<DialogHeader>
|
|
||||||
<DialogTitle className="text-2xl font-semibold">Import a secret</DialogTitle>
|
|
||||||
<DialogDescription>
|
|
||||||
Secrets are used to authenticate with a code host. They are encrypted at rest using <Link href="https://en.wikipedia.org/wiki/Advanced_Encryption_Standard" target="_blank" className="underline">AES-256-CBC</Link>.
|
|
||||||
Checkout our <Link href="https://sourcebot.dev/security" target="_blank" className="underline">security docs</Link> for more information.
|
|
||||||
</DialogDescription>
|
|
||||||
</DialogHeader>
|
|
||||||
|
|
||||||
<Form
|
|
||||||
{...form}
|
|
||||||
>
|
|
||||||
<form
|
|
||||||
className="space-y-4 flex flex-col mt-4 gap-4"
|
|
||||||
onSubmit={(event) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
form.handleSubmit(onSubmit)(event);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{codeHostSpecificStep}
|
|
||||||
|
|
||||||
<SecretCreationStep
|
|
||||||
step={2}
|
|
||||||
title="Import the secret"
|
|
||||||
description="Copy the generated token and paste it below."
|
|
||||||
>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="value"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>Value</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<div className="relative">
|
|
||||||
<Input
|
|
||||||
{...field}
|
|
||||||
type={showValue ? "text" : "password"}
|
|
||||||
placeholder="Enter your secret value"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="ghost"
|
|
||||||
size="sm"
|
|
||||||
className="absolute right-2 top-1/2 -translate-y-1/2"
|
|
||||||
onClick={() => setShowValue(!showValue)}
|
|
||||||
>
|
|
||||||
{showValue ? (
|
|
||||||
<EyeOff className="h-4 w-4" />
|
|
||||||
) : (
|
|
||||||
<Eye className="h-4 w-4" />
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
The secret value to store securely.
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</SecretCreationStep>
|
|
||||||
|
|
||||||
<SecretCreationStep
|
|
||||||
step={3}
|
|
||||||
title="Name the secret"
|
|
||||||
description="Give the secret a unique name so that it can be referenced in a connection config."
|
|
||||||
>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="key"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>Key</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
placeholder="my-access-token"
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
A unique name to identify this secret.
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</SecretCreationStep>
|
|
||||||
|
|
||||||
<div className="flex justify-end w-full">
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
disabled={isSubmitting}
|
|
||||||
>
|
|
||||||
{isSubmitting && <Loader2 className="h-4 w-4 animate-spin mr-2" />}
|
|
||||||
Import Secret
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</Form>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const GitHubPATCreationStep = ({ step }: { step: number }) => {
|
|
||||||
return (
|
|
||||||
<SecretCreationStep
|
|
||||||
step={step}
|
|
||||||
title="Create a Personal Access Token"
|
|
||||||
description=<span>Navigate <Link href="https://github.com/settings/tokens/new" target="_blank" className="underline">here on github.com</Link> (or your enterprise instance) and create a new personal access token. Sourcebot needs the <strong>repo</strong> scope in order to access private repositories:</span>
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
className="mx-auto rounded-sm"
|
|
||||||
src={githubPatCreation}
|
|
||||||
alt="Create a personal access token"
|
|
||||||
width={500}
|
|
||||||
height={500}
|
|
||||||
/>
|
|
||||||
</SecretCreationStep>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const GitLabPATCreationStep = ({ step }: { step: number }) => {
|
|
||||||
return (
|
|
||||||
<SecretCreationStep
|
|
||||||
step={step}
|
|
||||||
title="Create a Personal Access Token"
|
|
||||||
description=<span>Navigate <Link href="https://gitlab.com/-/user_settings/personal_access_tokens" target="_blank" className="underline">here on gitlab.com</Link> (or your self-hosted instance) and create a new personal access token. Sourcebot needs the <strong>read_api</strong> scope in order to access private projects:</span>
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
className="mx-auto rounded-sm"
|
|
||||||
src={gitlabPatCreation}
|
|
||||||
alt="Create a personal access token"
|
|
||||||
width={600}
|
|
||||||
height={600}
|
|
||||||
/>
|
|
||||||
</SecretCreationStep>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const GiteaPATCreationStep = ({ step }: { step: number }) => {
|
|
||||||
return (
|
|
||||||
<SecretCreationStep
|
|
||||||
step={step}
|
|
||||||
title="Create a Personal Access Token"
|
|
||||||
description=<span>Navigate <Link href="https://gitea.com/user/settings/applications" target="_blank" className="underline">here on gitea.com</Link> (or your self-hosted instance) and create a new access token. Sourcebot needs the <strong>read:repository</strong>, <strong>read:user</strong>, and <strong>read:organization</strong> scopes:</span>
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
className="mx-auto rounded-sm"
|
|
||||||
src={giteaPatCreation}
|
|
||||||
alt="Create a personal access token"
|
|
||||||
width={600}
|
|
||||||
height={600}
|
|
||||||
/>
|
|
||||||
</SecretCreationStep>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const BitbucketCloudPATCreationStep = ({ step }: { step: number }) => {
|
|
||||||
return (
|
|
||||||
<SecretCreationStep
|
|
||||||
step={step}
|
|
||||||
title="Create an Access Token"
|
|
||||||
description=<span>Please check out our <Link href="https://docs.sourcebot.dev/docs/connections/bitbucket-cloud#authenticating-with-bitbucket-cloud" target="_blank" className="underline">docs</Link> for more information on how to create auth credentials for Bitbucket Cloud.</span>
|
|
||||||
>
|
|
||||||
</SecretCreationStep>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const BitbucketServerPATCreationStep = ({ step }: { step: number }) => {
|
|
||||||
return (
|
|
||||||
<SecretCreationStep
|
|
||||||
step={step}
|
|
||||||
title="Create an Access Token"
|
|
||||||
description=<span>Please check out our <Link href="https://docs.sourcebot.dev/docs/connections/bitbucket-data-center#authenticating-with-bitbucket-data-center" target="_blank" className="underline">docs</Link> for more information on how to create auth credentials for Bitbucket Data Center.</span>
|
|
||||||
>
|
|
||||||
</SecretCreationStep>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SecretCreationStepProps {
|
|
||||||
step: number;
|
|
||||||
title: string;
|
|
||||||
description: string | React.ReactNode;
|
|
||||||
children?: React.ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SecretCreationStep = ({ step, title, description, children }: SecretCreationStepProps) => {
|
|
||||||
return (
|
|
||||||
<div className="relative flex flex-col gap-2">
|
|
||||||
<div className="absolute -left-10 flex flex-col items-center gap-2 h-full">
|
|
||||||
<span className="text-md font-semibold border rounded-full px-2">{step}</span>
|
|
||||||
<Separator className="h-5/6" orientation="vertical" />
|
|
||||||
</div>
|
|
||||||
<h3 className="text-md font-semibold">
|
|
||||||
{title}
|
|
||||||
</h3>
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
{description}
|
|
||||||
</p>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -10,7 +10,7 @@ import { SINGLE_TENANT_ORG_DOMAIN } from "@/lib/constants";
|
||||||
import { RepositoryQuery } from "@/lib/types";
|
import { RepositoryQuery } from "@/lib/types";
|
||||||
import { getCodeHostInfoForRepo, getShortenedNumberDisplayString } from "@/lib/utils";
|
import { getCodeHostInfoForRepo, getShortenedNumberDisplayString } from "@/lib/utils";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { FileIcon, Loader2Icon, RefreshCwIcon } from "lucide-react";
|
import { Loader2Icon, RefreshCwIcon } from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
|
@ -90,23 +90,14 @@ const RepoItem = ({ repo }: { repo: RepositoryQuery }) => {
|
||||||
webUrl: repo.webUrl,
|
webUrl: repo.webUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (info) {
|
|
||||||
return {
|
|
||||||
repoIcon: <Image
|
|
||||||
src={info.icon}
|
|
||||||
alt={info.codeHostName}
|
|
||||||
className={`w-4 h-4 ${info.iconClassName}`}
|
|
||||||
/>,
|
|
||||||
displayName: info.displayName,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
repoIcon: <FileIcon className="w-4 h-4" />,
|
repoIcon: <Image
|
||||||
displayName: repo.repoName,
|
src={info.icon}
|
||||||
|
alt={info.codeHostName}
|
||||||
|
className={`w-4 h-4 ${info.iconClassName}`}
|
||||||
|
/>,
|
||||||
|
displayName: info.displayName,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}, [repo.repoName, repo.codeHostType, repo.repoDisplayName, repo.webUrl]);
|
}, [repo.repoName, repo.codeHostType, repo.repoDisplayName, repo.webUrl]);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { cn, getCodeHostInfoForRepo } from "@/lib/utils";
|
import { cn, getCodeHostInfoForRepo } from "@/lib/utils";
|
||||||
import { LaptopIcon } from "@radix-ui/react-icons";
|
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { getBrowsePath } from "../browse/hooks/utils";
|
import { getBrowsePath } from "../browse/hooks/utils";
|
||||||
import { ChevronRight, MoreHorizontal } from "lucide-react";
|
import { ChevronRight, MoreHorizontal } from "lucide-react";
|
||||||
|
|
@ -17,6 +16,7 @@ import { VscodeFileIcon } from "@/app/components/vscodeFileIcon";
|
||||||
import { CopyIconButton } from "./copyIconButton";
|
import { CopyIconButton } from "./copyIconButton";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useDomain } from "@/hooks/useDomain";
|
import { useDomain } from "@/hooks/useDomain";
|
||||||
|
import { CodeHostType } from "@sourcebot/db";
|
||||||
|
|
||||||
interface FileHeaderProps {
|
interface FileHeaderProps {
|
||||||
path: string;
|
path: string;
|
||||||
|
|
@ -27,7 +27,7 @@ interface FileHeaderProps {
|
||||||
pathType?: 'blob' | 'tree';
|
pathType?: 'blob' | 'tree';
|
||||||
repo: {
|
repo: {
|
||||||
name: string;
|
name: string;
|
||||||
codeHostType: string;
|
codeHostType: CodeHostType;
|
||||||
displayName?: string;
|
displayName?: string;
|
||||||
webUrl?: string;
|
webUrl?: string;
|
||||||
},
|
},
|
||||||
|
|
@ -202,17 +202,13 @@ export const PathHeader = ({
|
||||||
<div className="flex flex-row gap-2 items-center w-full overflow-hidden">
|
<div className="flex flex-row gap-2 items-center w-full overflow-hidden">
|
||||||
{isCodeHostIconVisible && (
|
{isCodeHostIconVisible && (
|
||||||
<>
|
<>
|
||||||
{info?.icon ? (
|
<a href={info.repoLink} target="_blank" rel="noopener noreferrer">
|
||||||
<a href={info.repoLink} target="_blank" rel="noopener noreferrer">
|
<Image
|
||||||
<Image
|
src={info.icon}
|
||||||
src={info.icon}
|
alt={info.codeHostName}
|
||||||
alt={info.codeHostName}
|
className={`w-4 h-4 ${info.iconClassName}`}
|
||||||
className={`w-4 h-4 ${info.iconClassName}`}
|
/>
|
||||||
/>
|
</a>
|
||||||
</a>
|
|
||||||
) : (
|
|
||||||
<LaptopIcon className="w-4 h-4" />
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import {
|
||||||
import { captureEvent } from "@/hooks/useCaptureEvent";
|
import { captureEvent } from "@/hooks/useCaptureEvent";
|
||||||
import { RepositoryQuery } from "@/lib/types";
|
import { RepositoryQuery } from "@/lib/types";
|
||||||
import { getCodeHostInfoForRepo } from "@/lib/utils";
|
import { getCodeHostInfoForRepo } from "@/lib/utils";
|
||||||
import { FileIcon } from "@radix-ui/react-icons";
|
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import Autoscroll from "embla-carousel-auto-scroll";
|
import Autoscroll from "embla-carousel-auto-scroll";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
|
|
@ -121,20 +120,13 @@ const RepositoryBadge = ({
|
||||||
webUrl: repo.webUrl,
|
webUrl: repo.webUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (info) {
|
|
||||||
return {
|
|
||||||
repoIcon: <Image
|
|
||||||
src={info.icon}
|
|
||||||
alt={info.codeHostName}
|
|
||||||
className={`w-4 h-4 ${info.iconClassName}`}
|
|
||||||
/>,
|
|
||||||
displayName: info.displayName,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
repoIcon: <FileIcon className="w-4 h-4" />,
|
repoIcon: <Image
|
||||||
displayName: repo.repoName,
|
src={info.icon}
|
||||||
|
alt={info.codeHostName}
|
||||||
|
className={`w-4 h-4 ${info.iconClassName}`}
|
||||||
|
/>,
|
||||||
|
displayName: info.displayName,
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ export default async function RepoDetailPage({ params }: { params: Promise<{ id:
|
||||||
<h1 className="text-3xl font-semibold">{repo.displayName || repo.name}</h1>
|
<h1 className="text-3xl font-semibold">{repo.displayName || repo.name}</h1>
|
||||||
<p className="text-muted-foreground mt-2">{repo.name}</p>
|
<p className="text-muted-foreground mt-2">{repo.name}</p>
|
||||||
</div>
|
</div>
|
||||||
{(codeHostInfo && codeHostInfo.repoLink) && (
|
{codeHostInfo.repoLink && (
|
||||||
<Button variant="outline" asChild>
|
<Button variant="outline" asChild>
|
||||||
<Link href={codeHostInfo.repoLink} target="_blank" rel="noopener noreferrer" className="flex items-center">
|
<Link href={codeHostInfo.repoLink} target="_blank" rel="noopener noreferrer" className="flex items-center">
|
||||||
<Image
|
<Image
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,14 @@ import {
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Input } from "@/components/ui/input"
|
import { Input } from "@/components/ui/input"
|
||||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||||||
import { CodeHostType, getCodeHostBrowseAtBranchUrl } from "@/lib/utils"
|
import { getCodeHostBrowseAtBranchUrl } from "@/lib/utils"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
|
import { CodeHostType } from "@sourcebot/db";
|
||||||
|
|
||||||
type RepoBranchesTableProps = {
|
type RepoBranchesTableProps = {
|
||||||
indexRevisions: string[];
|
indexRevisions: string[];
|
||||||
repoWebUrl: string | null;
|
repoWebUrl: string | null;
|
||||||
repoCodeHostType: string;
|
repoCodeHostType: CodeHostType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RepoBranchesTable = ({ indexRevisions, repoWebUrl, repoCodeHostType }: RepoBranchesTableProps) => {
|
export const RepoBranchesTable = ({ indexRevisions, repoWebUrl, repoCodeHostType }: RepoBranchesTableProps) => {
|
||||||
|
|
@ -39,7 +40,7 @@ export const RepoBranchesTable = ({ indexRevisions, repoWebUrl, repoCodeHostType
|
||||||
|
|
||||||
const branchUrl = getCodeHostBrowseAtBranchUrl({
|
const branchUrl = getCodeHostBrowseAtBranchUrl({
|
||||||
webUrl: repoWebUrl,
|
webUrl: repoWebUrl,
|
||||||
codeHostType: repoCodeHostType as CodeHostType,
|
codeHostType: repoCodeHostType,
|
||||||
branchName: refName,
|
branchName: refName,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import { Input } from "@/components/ui/input"
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||||||
import { SINGLE_TENANT_ORG_DOMAIN } from "@/lib/constants"
|
import { SINGLE_TENANT_ORG_DOMAIN } from "@/lib/constants"
|
||||||
import { cn, CodeHostType, getCodeHostCommitUrl, getCodeHostIcon, getCodeHostInfoForRepo, getRepoImageSrc } from "@/lib/utils"
|
import { cn, getCodeHostCommitUrl, getCodeHostIcon, getCodeHostInfoForRepo, getRepoImageSrc } from "@/lib/utils"
|
||||||
import {
|
import {
|
||||||
type ColumnDef,
|
type ColumnDef,
|
||||||
type ColumnFiltersState,
|
type ColumnFiltersState,
|
||||||
|
|
@ -38,6 +38,7 @@ import { useToast } from "@/components/hooks/use-toast";
|
||||||
import { DisplayDate } from "../../components/DisplayDate"
|
import { DisplayDate } from "../../components/DisplayDate"
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||||
import { NotificationDot } from "../../components/notificationDot"
|
import { NotificationDot } from "../../components/notificationDot"
|
||||||
|
import { CodeHostType } from "@sourcebot/db"
|
||||||
|
|
||||||
// @see: https://v0.app/chat/repo-indexing-status-uhjdDim8OUS
|
// @see: https://v0.app/chat/repo-indexing-status-uhjdDim8OUS
|
||||||
|
|
||||||
|
|
@ -50,7 +51,7 @@ export type Repo = {
|
||||||
indexedAt: Date | null
|
indexedAt: Date | null
|
||||||
createdAt: Date
|
createdAt: Date
|
||||||
webUrl: string | null
|
webUrl: string | null
|
||||||
codeHostType: string
|
codeHostType: CodeHostType
|
||||||
imageUrl: string | null
|
imageUrl: string | null
|
||||||
indexedCommitHash: string | null
|
indexedCommitHash: string | null
|
||||||
latestJobStatus: "PENDING" | "IN_PROGRESS" | "COMPLETED" | "FAILED" | null
|
latestJobStatus: "PENDING" | "IN_PROGRESS" | "COMPLETED" | "FAILED" | null
|
||||||
|
|
@ -97,7 +98,7 @@ export const columns: ColumnDef<Repo>[] = [
|
||||||
},
|
},
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const repo = row.original;
|
const repo = row.original;
|
||||||
const codeHostIcon = getCodeHostIcon(repo.codeHostType as CodeHostType);
|
const codeHostIcon = getCodeHostIcon(repo.codeHostType);
|
||||||
const repoImageSrc = repo.imageUrl ? getRepoImageSrc(repo.imageUrl, repo.id) : undefined;
|
const repoImageSrc = repo.imageUrl ? getRepoImageSrc(repo.imageUrl, repo.id) : undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -192,7 +193,7 @@ export const columns: ColumnDef<Repo>[] = [
|
||||||
|
|
||||||
const smallHash = hash.slice(0, 7);
|
const smallHash = hash.slice(0, 7);
|
||||||
const repo = row.original;
|
const repo = row.original;
|
||||||
const codeHostType = repo.codeHostType as CodeHostType;
|
const codeHostType = repo.codeHostType;
|
||||||
const webUrl = repo.webUrl;
|
const webUrl = repo.webUrl;
|
||||||
|
|
||||||
const commitUrl = getCodeHostCommitUrl({
|
const commitUrl = getCodeHostCommitUrl({
|
||||||
|
|
@ -252,7 +253,7 @@ export const columns: ColumnDef<Repo>[] = [
|
||||||
<DropdownMenuItem asChild>
|
<DropdownMenuItem asChild>
|
||||||
<Link href={`/${SINGLE_TENANT_ORG_DOMAIN}/repos/${repo.id}`}>View details</Link>
|
<Link href={`/${SINGLE_TENANT_ORG_DOMAIN}/repos/${repo.id}`}>View details</Link>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
{(repo.webUrl && codeHostInfo) && (
|
{repo.webUrl && (
|
||||||
<>
|
<>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItem asChild>
|
<DropdownMenuItem asChild>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip
|
||||||
import { env } from "@/env.mjs";
|
import { env } from "@/env.mjs";
|
||||||
import { SINGLE_TENANT_ORG_DOMAIN } from "@/lib/constants";
|
import { SINGLE_TENANT_ORG_DOMAIN } from "@/lib/constants";
|
||||||
import { notFound, ServiceErrorException } from "@/lib/serviceError";
|
import { notFound, ServiceErrorException } from "@/lib/serviceError";
|
||||||
import { CodeHostType, isServiceError } from "@/lib/utils";
|
import { isServiceError } from "@/lib/utils";
|
||||||
import { withAuthV2 } from "@/withAuthV2";
|
import { withAuthV2 } from "@/withAuthV2";
|
||||||
import { AzureDevOpsConnectionConfig, BitbucketConnectionConfig, GenericGitHostConnectionConfig, GerritConnectionConfig, GiteaConnectionConfig, GithubConnectionConfig, GitlabConnectionConfig } from "@sourcebot/schemas/v3/index.type";
|
import { AzureDevOpsConnectionConfig, BitbucketConnectionConfig, GenericGitHostConnectionConfig, GerritConnectionConfig, GiteaConnectionConfig, GithubConnectionConfig, GitlabConnectionConfig } from "@sourcebot/schemas/v3/index.type";
|
||||||
import { getConfigSettings } from "@sourcebot/shared";
|
import { getConfigSettings } from "@sourcebot/shared";
|
||||||
|
|
@ -47,8 +47,9 @@ export default async function ConnectionDetailPage(props: ConnectionDetailPagePr
|
||||||
return undefined;
|
return undefined;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const codeHostUrl = (() => {
|
// Extracts the code host URL from the connection config.
|
||||||
const connectionType = connection.connectionType as CodeHostType;
|
const codeHostUrl: string = (() => {
|
||||||
|
const connectionType = connection.connectionType;
|
||||||
switch (connectionType) {
|
switch (connectionType) {
|
||||||
case 'github': {
|
case 'github': {
|
||||||
const config = connection.config as unknown as GithubConnectionConfig;
|
const config = connection.config as unknown as GithubConnectionConfig;
|
||||||
|
|
@ -66,19 +67,19 @@ export default async function ConnectionDetailPage(props: ConnectionDetailPagePr
|
||||||
const config = connection.config as unknown as GerritConnectionConfig;
|
const config = connection.config as unknown as GerritConnectionConfig;
|
||||||
return config.url;
|
return config.url;
|
||||||
}
|
}
|
||||||
case 'bitbucket-server': {
|
case 'bitbucket': {
|
||||||
const config = connection.config as unknown as BitbucketConnectionConfig;
|
const config = connection.config as unknown as BitbucketConnectionConfig;
|
||||||
return config.url!;
|
if (config.deploymentType === 'cloud') {
|
||||||
}
|
return config.url ?? 'https://bitbucket.org';
|
||||||
case 'bitbucket-cloud': {
|
} else {
|
||||||
const config = connection.config as unknown as BitbucketConnectionConfig;
|
return config.url!;
|
||||||
return config.url ?? 'https://bitbucket.org';
|
}
|
||||||
}
|
}
|
||||||
case 'azuredevops': {
|
case 'azuredevops': {
|
||||||
const config = connection.config as unknown as AzureDevOpsConnectionConfig;
|
const config = connection.config as unknown as AzureDevOpsConnectionConfig;
|
||||||
return config.url ?? 'https://dev.azure.com';
|
return config.url ?? 'https://dev.azure.com';
|
||||||
}
|
}
|
||||||
case 'generic-git-host': {
|
case 'git': {
|
||||||
const config = connection.config as unknown as GenericGitHostConnectionConfig;
|
const config = connection.config as unknown as GenericGitHostConnectionConfig;
|
||||||
return config.url;
|
return config.url;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
|
||||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||||
import { SINGLE_TENANT_ORG_DOMAIN } from "@/lib/constants"
|
import { SINGLE_TENANT_ORG_DOMAIN } from "@/lib/constants"
|
||||||
import { CodeHostType, getCodeHostIcon } from "@/lib/utils"
|
import { getCodeHostIcon } from "@/lib/utils"
|
||||||
|
import { ConnectionType } from "@sourcebot/db"
|
||||||
import {
|
import {
|
||||||
type ColumnDef,
|
type ColumnDef,
|
||||||
type ColumnFiltersState,
|
type ColumnFiltersState,
|
||||||
|
|
@ -35,7 +36,7 @@ export type Connection = {
|
||||||
id: number
|
id: number
|
||||||
name: string
|
name: string
|
||||||
syncedAt: Date | null
|
syncedAt: Date | null
|
||||||
codeHostType: CodeHostType
|
connectionType: ConnectionType
|
||||||
latestJobStatus: "PENDING" | "IN_PROGRESS" | "COMPLETED" | "FAILED" | null
|
latestJobStatus: "PENDING" | "IN_PROGRESS" | "COMPLETED" | "FAILED" | null
|
||||||
isFirstTimeSync: boolean
|
isFirstTimeSync: boolean
|
||||||
}
|
}
|
||||||
|
|
@ -80,13 +81,13 @@ export const columns: ColumnDef<Connection>[] = [
|
||||||
},
|
},
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const connection = row.original;
|
const connection = row.original;
|
||||||
const codeHostIcon = getCodeHostIcon(connection.codeHostType);
|
const codeHostIcon = getCodeHostIcon(connection.connectionType);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-row gap-2 items-center">
|
<div className="flex flex-row gap-2 items-center">
|
||||||
<Image
|
<Image
|
||||||
src={codeHostIcon.src}
|
src={codeHostIcon.src}
|
||||||
alt={`${connection.codeHostType} logo`}
|
alt={`${connection.connectionType} logo`}
|
||||||
className={codeHostIcon.className}
|
className={codeHostIcon.className}
|
||||||
width={20}
|
width={20}
|
||||||
height={20}
|
height={20}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { sew } from "@/actions";
|
import { sew } from "@/actions";
|
||||||
import { ServiceErrorException } from "@/lib/serviceError";
|
import { ServiceErrorException } from "@/lib/serviceError";
|
||||||
import { CodeHostType, isServiceError } from "@/lib/utils";
|
import { isServiceError } from "@/lib/utils";
|
||||||
import { withAuthV2 } from "@/withAuthV2";
|
import { withAuthV2 } from "@/withAuthV2";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { ConnectionsTable } from "./components/connectionsTable";
|
import { ConnectionsTable } from "./components/connectionsTable";
|
||||||
|
|
@ -40,7 +40,7 @@ export default async function ConnectionsPage() {
|
||||||
<ConnectionsTable data={connections.map((connection) => ({
|
<ConnectionsTable data={connections.map((connection) => ({
|
||||||
id: connection.id,
|
id: connection.id,
|
||||||
name: connection.name,
|
name: connection.name,
|
||||||
codeHostType: connection.connectionType as CodeHostType,
|
connectionType: connection.connectionType,
|
||||||
syncedAt: connection.syncedAt,
|
syncedAt: connection.syncedAt,
|
||||||
latestJobStatus: connection.latestJobStatus,
|
latestJobStatus: connection.latestJobStatus,
|
||||||
isFirstTimeSync: connection.isFirstTimeSync,
|
isFirstTimeSync: connection.isFirstTimeSync,
|
||||||
|
|
|
||||||
|
|
@ -106,10 +106,6 @@ export default async function SettingsLayout(
|
||||||
isNotificationDotVisible: connectionStats.numberOfConnectionsWithFirstTimeSyncJobsInProgress > 0,
|
isNotificationDotVisible: connectionStats.numberOfConnectionsWithFirstTimeSyncJobsInProgress > 0,
|
||||||
}
|
}
|
||||||
] : []),
|
] : []),
|
||||||
{
|
|
||||||
title: "Secrets",
|
|
||||||
href: `/${domain}/settings/secrets`,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: "API Keys",
|
title: "API Keys",
|
||||||
href: `/${domain}/settings/apiKeys`,
|
href: `/${domain}/settings/apiKeys`,
|
||||||
|
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
import { CodeHostIconButton } from "@/app/[domain]/components/codeHostIconButton";
|
|
||||||
import { Card, CardTitle, CardDescription, CardHeader, CardContent } from "@/components/ui/card";
|
|
||||||
import { getCodeHostIcon } from "@/lib/utils";
|
|
||||||
import { cn, CodeHostType } from "@/lib/utils";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { ImportSecretDialog } from "@/app/[domain]/components/importSecretDialog";
|
|
||||||
import { useRouter } from "next/navigation";
|
|
||||||
|
|
||||||
interface ImportSecretCardProps {
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ImportSecretCard = ({ className }: ImportSecretCardProps) => {
|
|
||||||
const [selectedCodeHost, setSelectedCodeHost] = useState<CodeHostType | null>(null);
|
|
||||||
const [isImportSecretDialogOpen, setIsImportSecretDialogOpen] = useState(false);
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Card className={cn(className)}>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Import a new secret</CardTitle>
|
|
||||||
<CardDescription>Import a secret from a code host to allow Sourcebot to sync private repositories.</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent className="flex flex-row gap-4 w-full justify-center">
|
|
||||||
<CodeHostIconButton
|
|
||||||
name="GitHub"
|
|
||||||
logo={getCodeHostIcon("github")}
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedCodeHost("github");
|
|
||||||
setIsImportSecretDialogOpen(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<CodeHostIconButton
|
|
||||||
name="GitLab"
|
|
||||||
logo={getCodeHostIcon("gitlab")}
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedCodeHost("gitlab");
|
|
||||||
setIsImportSecretDialogOpen(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<CodeHostIconButton
|
|
||||||
name="Gitea"
|
|
||||||
logo={getCodeHostIcon("gitea")}
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedCodeHost("gitea");
|
|
||||||
setIsImportSecretDialogOpen(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
{selectedCodeHost && (
|
|
||||||
<ImportSecretDialog
|
|
||||||
open={isImportSecretDialogOpen}
|
|
||||||
onOpenChange={setIsImportSecretDialogOpen}
|
|
||||||
onSecretCreated={() => {
|
|
||||||
router.refresh();
|
|
||||||
}}
|
|
||||||
codeHostType={selectedCodeHost ?? "github"}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,158 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import { LucideKeyRound, MoreVertical, Search, LucideTrash } from "lucide-react";
|
|
||||||
import { useState, useMemo, useCallback } from "react";
|
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
||||||
import { getFormattedDate, isServiceError } from "@/lib/utils";
|
|
||||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog";
|
|
||||||
import { deleteSecret } from "@/actions";
|
|
||||||
import { useDomain } from "@/hooks/useDomain";
|
|
||||||
import { useToast } from "@/components/hooks/use-toast";
|
|
||||||
import { useRouter } from "next/navigation";
|
|
||||||
import { CodeSnippet } from "@/app/components/codeSnippet";
|
|
||||||
|
|
||||||
interface Secret {
|
|
||||||
key: string;
|
|
||||||
createdAt: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SecretsListProps {
|
|
||||||
secrets: Secret[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SecretsList = ({ secrets }: SecretsListProps) => {
|
|
||||||
const [searchQuery, setSearchQuery] = useState("");
|
|
||||||
const [dateSort, setDateSort] = useState<"newest" | "oldest">("newest");
|
|
||||||
const [secretToDelete, setSecretToDelete] = useState<Secret | null>(null);
|
|
||||||
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
|
|
||||||
const domain = useDomain();
|
|
||||||
const { toast } = useToast();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const filteredSecrets = useMemo(() => {
|
|
||||||
return secrets
|
|
||||||
.filter((secret) => {
|
|
||||||
const searchLower = searchQuery.toLowerCase();
|
|
||||||
const matchesSearch = secret.key.toLowerCase().includes(searchLower);
|
|
||||||
return matchesSearch;
|
|
||||||
})
|
|
||||||
.sort((a, b) => {
|
|
||||||
return dateSort === "newest"
|
|
||||||
? b.createdAt.getTime() - a.createdAt.getTime()
|
|
||||||
: a.createdAt.getTime() - b.createdAt.getTime()
|
|
||||||
});
|
|
||||||
}, [secrets, searchQuery, dateSort]);
|
|
||||||
|
|
||||||
const onDeleteSecret = useCallback(() => {
|
|
||||||
deleteSecret(secretToDelete?.key ?? "", domain)
|
|
||||||
.then((response) => {
|
|
||||||
if (isServiceError(response)) {
|
|
||||||
toast({
|
|
||||||
description: `❌ Failed to delete secret. Reason: ${response.message}`
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
toast({
|
|
||||||
description: `✅ Secret deleted successfully.`
|
|
||||||
});
|
|
||||||
router.refresh();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}, [domain, secretToDelete?.key, toast, router]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="w-full mx-auto space-y-6">
|
|
||||||
<div className="flex gap-4 flex-col sm:flex-row">
|
|
||||||
<div className="relative flex-1">
|
|
||||||
<Search className="absolute left-3 top-2.5 h-4 w-4 text-muted-foreground" />
|
|
||||||
<Input
|
|
||||||
placeholder="Filter by secret name..."
|
|
||||||
className="pl-9"
|
|
||||||
value={searchQuery}
|
|
||||||
onChange={(e) => setSearchQuery(e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Select value={dateSort} onValueChange={(value) => setDateSort(value as "newest" | "oldest")}>
|
|
||||||
<SelectTrigger className="w-[140px]">
|
|
||||||
<SelectValue placeholder="Date" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="newest">Newest</SelectItem>
|
|
||||||
<SelectItem value="oldest">Oldest</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="border rounded-lg overflow-hidden">
|
|
||||||
<div className="max-h-[600px] overflow-y-auto divide-y">
|
|
||||||
{secrets.length === 0 || (filteredSecrets.length === 0 && searchQuery.length > 0) ? (
|
|
||||||
<div className="flex flex-col items-center justify-center h-96 p-4">
|
|
||||||
<p className="font-medium text-sm">No Secrets Found</p>
|
|
||||||
<p className="text-sm text-muted-foreground mt-2">
|
|
||||||
{filteredSecrets.length === 0 && searchQuery.length > 0 ? "No secrets found matching your filters." : "Use the form above to create a new secret."}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
filteredSecrets.map((secret) => (
|
|
||||||
<div key={secret.key} className="p-4 flex items-center justify-between bg-background">
|
|
||||||
<div className="flex items-center">
|
|
||||||
<LucideKeyRound className="w-4 h-4 mr-2" />
|
|
||||||
<p className="font-mono">{secret.key}</p>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-4">
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
Created {getFormattedDate(secret.createdAt)}
|
|
||||||
</p>
|
|
||||||
<DropdownMenu modal={false}>
|
|
||||||
<DropdownMenuTrigger asChild>
|
|
||||||
<Button variant="ghost" className="h-8 w-8 p-0">
|
|
||||||
<MoreVertical className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent align="end">
|
|
||||||
<DropdownMenuItem
|
|
||||||
className="cursor-pointer text-destructive"
|
|
||||||
onClick={() => {
|
|
||||||
setSecretToDelete(secret);
|
|
||||||
setIsDeleteDialogOpen(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<LucideTrash className="w-4 h-4 mr-2" />
|
|
||||||
Delete secret
|
|
||||||
</DropdownMenuItem>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<AlertDialog
|
|
||||||
open={isDeleteDialogOpen}
|
|
||||||
onOpenChange={setIsDeleteDialogOpen}
|
|
||||||
>
|
|
||||||
<AlertDialogContent>
|
|
||||||
<AlertDialogHeader>
|
|
||||||
<AlertDialogTitle>Delete Secret</AlertDialogTitle>
|
|
||||||
<AlertDialogDescription>
|
|
||||||
Are you sure you want to delete the secret <CodeSnippet>{secretToDelete?.key}</CodeSnippet>? Any connections that use this secret will <strong>fail to sync.</strong>
|
|
||||||
</AlertDialogDescription>
|
|
||||||
</AlertDialogHeader>
|
|
||||||
<AlertDialogFooter>
|
|
||||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
||||||
<AlertDialogAction
|
|
||||||
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
|
||||||
onClick={onDeleteSecret}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</AlertDialogAction>
|
|
||||||
</AlertDialogFooter>
|
|
||||||
</AlertDialogContent>
|
|
||||||
</AlertDialog>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
import { getSecrets } from "@/actions";
|
|
||||||
import { SecretsList } from "./components/secretsList";
|
|
||||||
import { isServiceError } from "@/lib/utils";
|
|
||||||
import { ImportSecretCard } from "./components/importSecretCard";
|
|
||||||
import { ServiceErrorException } from "@/lib/serviceError";
|
|
||||||
|
|
||||||
interface SecretsPageProps {
|
|
||||||
params: Promise<{
|
|
||||||
domain: string;
|
|
||||||
}>
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async function SecretsPage(props: SecretsPageProps) {
|
|
||||||
const params = await props.params;
|
|
||||||
|
|
||||||
const {
|
|
||||||
domain
|
|
||||||
} = params;
|
|
||||||
|
|
||||||
const secrets = await getSecrets(domain);
|
|
||||||
if (isServiceError(secrets)) {
|
|
||||||
throw new ServiceErrorException(secrets);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col gap-6">
|
|
||||||
<div>
|
|
||||||
<h3 className="text-lg font-medium">Manage Secrets</h3>
|
|
||||||
<p className="text-sm text-muted-foreground">These secrets grant Sourcebot access to private code.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<SecretsList secrets={secrets} />
|
|
||||||
<ImportSecretCard className="mt-4" />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -92,7 +92,7 @@ export async function POST(req: Request) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const { model, providerOptions } = await _getAISDKLanguageModelAndOptions(languageModelConfig, org.id);
|
const { model, providerOptions } = await _getAISDKLanguageModelAndOptions(languageModelConfig);
|
||||||
|
|
||||||
return createMessageStreamResponse({
|
return createMessageStreamResponse({
|
||||||
messages,
|
messages,
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import { createXai } from '@ai-sdk/xai';
|
||||||
import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
|
import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
|
||||||
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
|
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
|
||||||
import { getTokenFromConfig } from "@sourcebot/crypto";
|
import { getTokenFromConfig } from "@sourcebot/crypto";
|
||||||
import { ChatVisibility, OrgRole, Prisma, PrismaClient } from "@sourcebot/db";
|
import { ChatVisibility, OrgRole, Prisma } from "@sourcebot/db";
|
||||||
import { LanguageModel } from "@sourcebot/schemas/v3/languageModel.type";
|
import { LanguageModel } from "@sourcebot/schemas/v3/languageModel.type";
|
||||||
import { Token } from "@sourcebot/schemas/v3/shared.type";
|
import { Token } from "@sourcebot/schemas/v3/shared.type";
|
||||||
import { loadConfig } from "@sourcebot/shared";
|
import { loadConfig } from "@sourcebot/shared";
|
||||||
|
|
@ -204,7 +204,7 @@ export const generateAndUpdateChatNameFromMessage = async ({ chatId, languageMod
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const { model } = await _getAISDKLanguageModelAndOptions(languageModelConfig, org.id);
|
const { model } = await _getAISDKLanguageModelAndOptions(languageModelConfig);
|
||||||
|
|
||||||
const prompt = `Convert this question into a short topic title (max 50 characters).
|
const prompt = `Convert this question into a short topic title (max 50 characters).
|
||||||
|
|
||||||
|
|
@ -374,7 +374,7 @@ export const _getConfiguredLanguageModelsFull = async (): Promise<LanguageModel[
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel, orgId: number): Promise<{
|
export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel): Promise<{
|
||||||
model: AISDKLanguageModelV2,
|
model: AISDKLanguageModelV2,
|
||||||
providerOptions?: Record<string, Record<string, JSONValue>>,
|
providerOptions?: Record<string, Record<string, JSONValue>>,
|
||||||
}> => {
|
}> => {
|
||||||
|
|
@ -386,16 +386,16 @@ export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel, or
|
||||||
baseURL: config.baseUrl,
|
baseURL: config.baseUrl,
|
||||||
region: config.region ?? env.AWS_REGION,
|
region: config.region ?? env.AWS_REGION,
|
||||||
accessKeyId: config.accessKeyId
|
accessKeyId: config.accessKeyId
|
||||||
? await getTokenFromConfig(config.accessKeyId, orgId, prisma)
|
? await getTokenFromConfig(config.accessKeyId)
|
||||||
: env.AWS_ACCESS_KEY_ID,
|
: env.AWS_ACCESS_KEY_ID,
|
||||||
secretAccessKey: config.accessKeySecret
|
secretAccessKey: config.accessKeySecret
|
||||||
? await getTokenFromConfig(config.accessKeySecret, orgId, prisma)
|
? await getTokenFromConfig(config.accessKeySecret)
|
||||||
: env.AWS_SECRET_ACCESS_KEY,
|
: env.AWS_SECRET_ACCESS_KEY,
|
||||||
sessionToken: config.sessionToken
|
sessionToken: config.sessionToken
|
||||||
? await getTokenFromConfig(config.sessionToken, orgId, prisma)
|
? await getTokenFromConfig(config.sessionToken)
|
||||||
: env.AWS_SESSION_TOKEN,
|
: env.AWS_SESSION_TOKEN,
|
||||||
headers: config.headers
|
headers: config.headers
|
||||||
? await extractLanguageModelKeyValuePairs(config.headers, orgId, prisma)
|
? await extractLanguageModelKeyValuePairs(config.headers)
|
||||||
: undefined,
|
: undefined,
|
||||||
// Fallback to the default Node.js credential provider chain if no credentials are provided.
|
// Fallback to the default Node.js credential provider chain if no credentials are provided.
|
||||||
// See: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-credential-providers/#fromnodeproviderchain
|
// See: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-credential-providers/#fromnodeproviderchain
|
||||||
|
|
@ -412,10 +412,10 @@ export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel, or
|
||||||
const anthropic = createAnthropic({
|
const anthropic = createAnthropic({
|
||||||
baseURL: config.baseUrl,
|
baseURL: config.baseUrl,
|
||||||
apiKey: config.token
|
apiKey: config.token
|
||||||
? await getTokenFromConfig(config.token, orgId, prisma)
|
? await getTokenFromConfig(config.token)
|
||||||
: env.ANTHROPIC_API_KEY,
|
: env.ANTHROPIC_API_KEY,
|
||||||
headers: config.headers
|
headers: config.headers
|
||||||
? await extractLanguageModelKeyValuePairs(config.headers, orgId, prisma)
|
? await extractLanguageModelKeyValuePairs(config.headers)
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -434,11 +434,11 @@ export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel, or
|
||||||
case 'azure': {
|
case 'azure': {
|
||||||
const azure = createAzure({
|
const azure = createAzure({
|
||||||
baseURL: config.baseUrl,
|
baseURL: config.baseUrl,
|
||||||
apiKey: config.token ? (await getTokenFromConfig(config.token, orgId, prisma)) : env.AZURE_API_KEY,
|
apiKey: config.token ? (await getTokenFromConfig(config.token)) : env.AZURE_API_KEY,
|
||||||
apiVersion: config.apiVersion,
|
apiVersion: config.apiVersion,
|
||||||
resourceName: config.resourceName ?? env.AZURE_RESOURCE_NAME,
|
resourceName: config.resourceName ?? env.AZURE_RESOURCE_NAME,
|
||||||
headers: config.headers
|
headers: config.headers
|
||||||
? await extractLanguageModelKeyValuePairs(config.headers, orgId, prisma)
|
? await extractLanguageModelKeyValuePairs(config.headers)
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -449,9 +449,9 @@ export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel, or
|
||||||
case 'deepseek': {
|
case 'deepseek': {
|
||||||
const deepseek = createDeepSeek({
|
const deepseek = createDeepSeek({
|
||||||
baseURL: config.baseUrl,
|
baseURL: config.baseUrl,
|
||||||
apiKey: config.token ? (await getTokenFromConfig(config.token, orgId, prisma)) : env.DEEPSEEK_API_KEY,
|
apiKey: config.token ? (await getTokenFromConfig(config.token)) : env.DEEPSEEK_API_KEY,
|
||||||
headers: config.headers
|
headers: config.headers
|
||||||
? await extractLanguageModelKeyValuePairs(config.headers, orgId, prisma)
|
? await extractLanguageModelKeyValuePairs(config.headers)
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -463,10 +463,10 @@ export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel, or
|
||||||
const google = createGoogleGenerativeAI({
|
const google = createGoogleGenerativeAI({
|
||||||
baseURL: config.baseUrl,
|
baseURL: config.baseUrl,
|
||||||
apiKey: config.token
|
apiKey: config.token
|
||||||
? await getTokenFromConfig(config.token, orgId, prisma)
|
? await getTokenFromConfig(config.token)
|
||||||
: env.GOOGLE_GENERATIVE_AI_API_KEY,
|
: env.GOOGLE_GENERATIVE_AI_API_KEY,
|
||||||
headers: config.headers
|
headers: config.headers
|
||||||
? await extractLanguageModelKeyValuePairs(config.headers, orgId, prisma)
|
? await extractLanguageModelKeyValuePairs(config.headers)
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -480,11 +480,11 @@ export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel, or
|
||||||
location: config.region ?? env.GOOGLE_VERTEX_REGION,
|
location: config.region ?? env.GOOGLE_VERTEX_REGION,
|
||||||
...(config.credentials ? {
|
...(config.credentials ? {
|
||||||
googleAuthOptions: {
|
googleAuthOptions: {
|
||||||
keyFilename: await getTokenFromConfig(config.credentials, orgId, prisma),
|
keyFilename: await getTokenFromConfig(config.credentials),
|
||||||
}
|
}
|
||||||
} : {}),
|
} : {}),
|
||||||
headers: config.headers
|
headers: config.headers
|
||||||
? await extractLanguageModelKeyValuePairs(config.headers, orgId, prisma)
|
? await extractLanguageModelKeyValuePairs(config.headers)
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -506,11 +506,11 @@ export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel, or
|
||||||
location: config.region ?? env.GOOGLE_VERTEX_REGION,
|
location: config.region ?? env.GOOGLE_VERTEX_REGION,
|
||||||
...(config.credentials ? {
|
...(config.credentials ? {
|
||||||
googleAuthOptions: {
|
googleAuthOptions: {
|
||||||
keyFilename: await getTokenFromConfig(config.credentials, orgId, prisma),
|
keyFilename: await getTokenFromConfig(config.credentials),
|
||||||
}
|
}
|
||||||
} : {}),
|
} : {}),
|
||||||
headers: config.headers
|
headers: config.headers
|
||||||
? await extractLanguageModelKeyValuePairs(config.headers, orgId, prisma)
|
? await extractLanguageModelKeyValuePairs(config.headers)
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -522,10 +522,10 @@ export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel, or
|
||||||
const mistral = createMistral({
|
const mistral = createMistral({
|
||||||
baseURL: config.baseUrl,
|
baseURL: config.baseUrl,
|
||||||
apiKey: config.token
|
apiKey: config.token
|
||||||
? await getTokenFromConfig(config.token, orgId, prisma)
|
? await getTokenFromConfig(config.token)
|
||||||
: env.MISTRAL_API_KEY,
|
: env.MISTRAL_API_KEY,
|
||||||
headers: config.headers
|
headers: config.headers
|
||||||
? await extractLanguageModelKeyValuePairs(config.headers, orgId, prisma)
|
? await extractLanguageModelKeyValuePairs(config.headers)
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -537,10 +537,10 @@ export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel, or
|
||||||
const openai = createOpenAI({
|
const openai = createOpenAI({
|
||||||
baseURL: config.baseUrl,
|
baseURL: config.baseUrl,
|
||||||
apiKey: config.token
|
apiKey: config.token
|
||||||
? await getTokenFromConfig(config.token, orgId, prisma)
|
? await getTokenFromConfig(config.token)
|
||||||
: env.OPENAI_API_KEY,
|
: env.OPENAI_API_KEY,
|
||||||
headers: config.headers
|
headers: config.headers
|
||||||
? await extractLanguageModelKeyValuePairs(config.headers, orgId, prisma)
|
? await extractLanguageModelKeyValuePairs(config.headers)
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -558,13 +558,13 @@ export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel, or
|
||||||
baseURL: config.baseUrl,
|
baseURL: config.baseUrl,
|
||||||
name: config.displayName ?? modelId,
|
name: config.displayName ?? modelId,
|
||||||
apiKey: config.token
|
apiKey: config.token
|
||||||
? await getTokenFromConfig(config.token, orgId, prisma)
|
? await getTokenFromConfig(config.token)
|
||||||
: undefined,
|
: undefined,
|
||||||
headers: config.headers
|
headers: config.headers
|
||||||
? await extractLanguageModelKeyValuePairs(config.headers, orgId, prisma)
|
? await extractLanguageModelKeyValuePairs(config.headers)
|
||||||
: undefined,
|
: undefined,
|
||||||
queryParams: config.queryParams
|
queryParams: config.queryParams
|
||||||
? await extractLanguageModelKeyValuePairs(config.queryParams, orgId, prisma)
|
? await extractLanguageModelKeyValuePairs(config.queryParams)
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -585,10 +585,10 @@ export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel, or
|
||||||
const openrouter = createOpenRouter({
|
const openrouter = createOpenRouter({
|
||||||
baseURL: config.baseUrl,
|
baseURL: config.baseUrl,
|
||||||
apiKey: config.token
|
apiKey: config.token
|
||||||
? await getTokenFromConfig(config.token, orgId, prisma)
|
? await getTokenFromConfig(config.token)
|
||||||
: env.OPENROUTER_API_KEY,
|
: env.OPENROUTER_API_KEY,
|
||||||
headers: config.headers
|
headers: config.headers
|
||||||
? await extractLanguageModelKeyValuePairs(config.headers, orgId, prisma)
|
? await extractLanguageModelKeyValuePairs(config.headers)
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -600,10 +600,10 @@ export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel, or
|
||||||
const xai = createXai({
|
const xai = createXai({
|
||||||
baseURL: config.baseUrl,
|
baseURL: config.baseUrl,
|
||||||
apiKey: config.token
|
apiKey: config.token
|
||||||
? await getTokenFromConfig(config.token, orgId, prisma)
|
? await getTokenFromConfig(config.token)
|
||||||
: env.XAI_API_KEY,
|
: env.XAI_API_KEY,
|
||||||
headers: config.headers
|
headers: config.headers
|
||||||
? await extractLanguageModelKeyValuePairs(config.headers, orgId, prisma)
|
? await extractLanguageModelKeyValuePairs(config.headers)
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -617,9 +617,7 @@ export const _getAISDKLanguageModelAndOptions = async (config: LanguageModel, or
|
||||||
const extractLanguageModelKeyValuePairs = async (
|
const extractLanguageModelKeyValuePairs = async (
|
||||||
pairs: {
|
pairs: {
|
||||||
[k: string]: string | Token;
|
[k: string]: string | Token;
|
||||||
},
|
}
|
||||||
orgId: number,
|
|
||||||
db: PrismaClient,
|
|
||||||
): Promise<Record<string, string>> => {
|
): Promise<Record<string, string>> => {
|
||||||
const resolvedPairs: Record<string, string> = {};
|
const resolvedPairs: Record<string, string> = {};
|
||||||
|
|
||||||
|
|
@ -633,7 +631,7 @@ const extractLanguageModelKeyValuePairs = async (
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const value = await getTokenFromConfig(val, orgId, db);
|
const value = await getTokenFromConfig(val);
|
||||||
resolvedPairs[key] = value;
|
resolvedPairs[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import { createCodeFoldingExtension } from "./codeFoldingExtension";
|
||||||
import useCaptureEvent from "@/hooks/useCaptureEvent";
|
import useCaptureEvent from "@/hooks/useCaptureEvent";
|
||||||
import { createAuditAction } from "@/ee/features/audit/actions";
|
import { createAuditAction } from "@/ee/features/audit/actions";
|
||||||
import { useDomain } from "@/hooks/useDomain";
|
import { useDomain } from "@/hooks/useDomain";
|
||||||
|
import { CodeHostType } from "@sourcebot/db";
|
||||||
|
|
||||||
const lineDecoration = Decoration.line({
|
const lineDecoration = Decoration.line({
|
||||||
attributes: { class: "cm-range-border-radius chat-lineHighlight" },
|
attributes: { class: "cm-range-border-radius chat-lineHighlight" },
|
||||||
|
|
@ -40,7 +41,7 @@ interface ReferencedFileSourceListItemProps {
|
||||||
language: string;
|
language: string;
|
||||||
revision: string;
|
revision: string;
|
||||||
repoName: string;
|
repoName: string;
|
||||||
repoCodeHostType: string;
|
repoCodeHostType: CodeHostType;
|
||||||
repoDisplayName?: string;
|
repoDisplayName?: string;
|
||||||
repoWebUrl?: string;
|
repoWebUrl?: string;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { cn, CodeHostType, getCodeHostIcon } from "@/lib/utils";
|
import { cn, getCodeHostIcon } from "@/lib/utils";
|
||||||
|
import { CodeHostType } from "@sourcebot/db";
|
||||||
import { LibraryBigIcon } from "lucide-react";
|
import { LibraryBigIcon } from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { SearchScope } from "../types";
|
import { SearchScope } from "../types";
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ const getRepoPath = (repo: Repo): { path: string, isReadOnly: boolean } => {
|
||||||
// If we are dealing with a local repository, then use that as the path.
|
// If we are dealing with a local repository, then use that as the path.
|
||||||
// Mark as read-only since we aren't guaranteed to have write access to the local filesystem.
|
// Mark as read-only since we aren't guaranteed to have write access to the local filesystem.
|
||||||
const cloneUrl = new URL(repo.cloneUrl);
|
const cloneUrl = new URL(repo.cloneUrl);
|
||||||
if (repo.external_codeHostType === 'generic-git-host' && cloneUrl.protocol === 'file:') {
|
if (repo.external_codeHostType === 'genericGitHost' && cloneUrl.protocol === 'file:') {
|
||||||
return {
|
return {
|
||||||
path: cloneUrl.pathname,
|
path: cloneUrl.pathname,
|
||||||
isReadOnly: true,
|
isReadOnly: true,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// @NOTE : Please keep this file in sync with @sourcebot/mcp/src/schemas.ts
|
// @NOTE : Please keep this file in sync with @sourcebot/mcp/src/schemas.ts
|
||||||
|
import { CodeHostType } from "@sourcebot/db";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
export const locationSchema = z.object({
|
export const locationSchema = z.object({
|
||||||
|
|
@ -33,7 +34,7 @@ export const searchRequestSchema = z.object({
|
||||||
|
|
||||||
export const repositoryInfoSchema = z.object({
|
export const repositoryInfoSchema = z.object({
|
||||||
id: z.number(),
|
id: z.number(),
|
||||||
codeHostType: z.string(),
|
codeHostType: z.nativeEnum(CodeHostType),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
displayName: z.string().optional(),
|
displayName: z.string().optional(),
|
||||||
webUrl: z.string().optional(),
|
webUrl: z.string().optional(),
|
||||||
|
|
@ -153,7 +154,7 @@ export const fileSourceResponseSchema = z.object({
|
||||||
language: z.string(),
|
language: z.string(),
|
||||||
path: z.string(),
|
path: z.string(),
|
||||||
repository: z.string(),
|
repository: z.string(),
|
||||||
repositoryCodeHostType: z.string(),
|
repositoryCodeHostType: z.nativeEnum(CodeHostType),
|
||||||
repositoryDisplayName: z.string().optional(),
|
repositoryDisplayName: z.string().optional(),
|
||||||
repositoryWebUrl: z.string().optional(),
|
repositoryWebUrl: z.string().optional(),
|
||||||
branch: z.string().optional(),
|
branch: z.string().optional(),
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { checkIfOrgDomainExists } from "@/actions";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { isServiceError } from "./utils";
|
import { isServiceError } from "./utils";
|
||||||
import { serviceErrorSchema } from "./serviceError";
|
import { serviceErrorSchema } from "./serviceError";
|
||||||
|
import { CodeHostType } from "@sourcebot/db";
|
||||||
|
|
||||||
export const secretCreateRequestSchema = z.object({
|
export const secretCreateRequestSchema = z.object({
|
||||||
key: z.string(),
|
key: z.string(),
|
||||||
|
|
@ -13,7 +14,7 @@ export const secreteDeleteRequestSchema = z.object({
|
||||||
});
|
});
|
||||||
|
|
||||||
export const repositoryQuerySchema = z.object({
|
export const repositoryQuerySchema = z.object({
|
||||||
codeHostType: z.string(),
|
codeHostType: z.nativeEnum(CodeHostType),
|
||||||
repoId: z.number(),
|
repoId: z.number(),
|
||||||
repoName: z.string(),
|
repoName: z.string(),
|
||||||
repoDisplayName: z.string().optional(),
|
repoDisplayName: z.string().optional(),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
|
|
||||||
export const strings = {
|
|
||||||
connectionConfigDescription: "Configure what repositories, organizations, users, etc. you want to sync with Sourcebot. Use the quick actions below to help you configure your connection.",
|
|
||||||
createSecretDescription: "Secrets are used to authenticate with the code host, allowing Sourcebot to access private repositories.",
|
|
||||||
}
|
|
||||||
|
|
||||||
export default strings;
|
|
||||||
|
|
@ -15,9 +15,10 @@ import { ServiceError } from "./serviceError";
|
||||||
import { StatusCodes } from "http-status-codes";
|
import { StatusCodes } from "http-status-codes";
|
||||||
import { ErrorCode } from "./errorCodes";
|
import { ErrorCode } from "./errorCodes";
|
||||||
import { NextRequest } from "next/server";
|
import { NextRequest } from "next/server";
|
||||||
import { Org } from "@sourcebot/db";
|
import { ConnectionType, Org } from "@sourcebot/db";
|
||||||
import { OrgMetadata, orgMetadataSchema } from "@/types";
|
import { OrgMetadata, orgMetadataSchema } from "@/types";
|
||||||
import { SINGLE_TENANT_ORG_DOMAIN } from "./constants";
|
import { SINGLE_TENANT_ORG_DOMAIN } from "./constants";
|
||||||
|
import { CodeHostType } from "@sourcebot/db";
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs))
|
return twMerge(clsx(inputs))
|
||||||
|
|
@ -64,16 +65,6 @@ export const createPathWithQueryParams = (path: string, ...queryParams: [string,
|
||||||
return `${path}?${queryString}`;
|
return `${path}?${queryString}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CodeHostType =
|
|
||||||
"github" |
|
|
||||||
"gitlab" |
|
|
||||||
"gitea" |
|
|
||||||
"gerrit" |
|
|
||||||
"bitbucket-cloud" |
|
|
||||||
"bitbucket-server" |
|
|
||||||
"azuredevops" |
|
|
||||||
"generic-git-host";
|
|
||||||
|
|
||||||
export type AuthProviderType =
|
export type AuthProviderType =
|
||||||
"github" |
|
"github" |
|
||||||
"gitlab" |
|
"gitlab" |
|
||||||
|
|
@ -183,11 +174,11 @@ type CodeHostInfo = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getCodeHostInfoForRepo = (repo: {
|
export const getCodeHostInfoForRepo = (repo: {
|
||||||
codeHostType: string,
|
codeHostType: CodeHostType,
|
||||||
name: string,
|
name: string,
|
||||||
displayName?: string,
|
displayName?: string,
|
||||||
webUrl?: string,
|
webUrl?: string,
|
||||||
}): CodeHostInfo | undefined => {
|
}): CodeHostInfo => {
|
||||||
const { codeHostType, name, displayName, webUrl } = repo;
|
const { codeHostType, name, displayName, webUrl } = repo;
|
||||||
|
|
||||||
switch (codeHostType) {
|
switch (codeHostType) {
|
||||||
|
|
@ -235,8 +226,7 @@ export const getCodeHostInfoForRepo = (repo: {
|
||||||
iconClassName: className,
|
iconClassName: className,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'gerrit':
|
case 'gerrit': {
|
||||||
case 'gitiles': {
|
|
||||||
const { src, className } = getCodeHostIcon('gerrit')!;
|
const { src, className } = getCodeHostIcon('gerrit')!;
|
||||||
return {
|
return {
|
||||||
type: "gerrit",
|
type: "gerrit",
|
||||||
|
|
@ -247,10 +237,10 @@ export const getCodeHostInfoForRepo = (repo: {
|
||||||
iconClassName: className,
|
iconClassName: className,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "bitbucket-server": {
|
case "bitbucketServer": {
|
||||||
const { src, className } = getCodeHostIcon('bitbucket-server')!;
|
const { src, className } = getCodeHostIcon('bitbucketServer')!;
|
||||||
return {
|
return {
|
||||||
type: "bitbucket-server",
|
type: "bitbucketServer",
|
||||||
displayName: displayName ?? name,
|
displayName: displayName ?? name,
|
||||||
codeHostName: "Bitbucket",
|
codeHostName: "Bitbucket",
|
||||||
repoLink: webUrl,
|
repoLink: webUrl,
|
||||||
|
|
@ -258,10 +248,10 @@ export const getCodeHostInfoForRepo = (repo: {
|
||||||
iconClassName: className,
|
iconClassName: className,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "bitbucket-cloud": {
|
case "bitbucketCloud": {
|
||||||
const { src, className } = getCodeHostIcon('bitbucket-cloud')!;
|
const { src, className } = getCodeHostIcon('bitbucketCloud')!;
|
||||||
return {
|
return {
|
||||||
type: "bitbucket-cloud",
|
type: "bitbucketCloud",
|
||||||
displayName: displayName ?? name,
|
displayName: displayName ?? name,
|
||||||
codeHostName: "Bitbucket",
|
codeHostName: "Bitbucket",
|
||||||
repoLink: webUrl,
|
repoLink: webUrl,
|
||||||
|
|
@ -269,10 +259,10 @@ export const getCodeHostInfoForRepo = (repo: {
|
||||||
iconClassName: className,
|
iconClassName: className,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "generic-git-host": {
|
case "genericGitHost": {
|
||||||
const { src, className } = getCodeHostIcon('generic-git-host')!;
|
const { src, className } = getCodeHostIcon('genericGitHost')!;
|
||||||
return {
|
return {
|
||||||
type: "generic-git-host",
|
type: "genericGitHost",
|
||||||
displayName: displayName ?? name,
|
displayName: displayName ?? name,
|
||||||
codeHostName: "Git Host",
|
codeHostName: "Git Host",
|
||||||
repoLink: webUrl,
|
repoLink: webUrl,
|
||||||
|
|
@ -283,7 +273,7 @@ export const getCodeHostInfoForRepo = (repo: {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getCodeHostIcon = (codeHostType: CodeHostType): { src: string, className?: string } => {
|
export const getCodeHostIcon = (codeHostType: CodeHostType | ConnectionType): { src: string, className?: string } => {
|
||||||
switch (codeHostType) {
|
switch (codeHostType) {
|
||||||
case "github":
|
case "github":
|
||||||
return {
|
return {
|
||||||
|
|
@ -302,8 +292,9 @@ export const getCodeHostIcon = (codeHostType: CodeHostType): { src: string, clas
|
||||||
return {
|
return {
|
||||||
src: gerritLogo,
|
src: gerritLogo,
|
||||||
}
|
}
|
||||||
case "bitbucket-cloud":
|
case "bitbucket":
|
||||||
case "bitbucket-server":
|
case "bitbucketCloud":
|
||||||
|
case "bitbucketServer":
|
||||||
return {
|
return {
|
||||||
src: bitbucketLogo,
|
src: bitbucketLogo,
|
||||||
}
|
}
|
||||||
|
|
@ -311,7 +302,8 @@ export const getCodeHostIcon = (codeHostType: CodeHostType): { src: string, clas
|
||||||
return {
|
return {
|
||||||
src: azuredevopsLogo,
|
src: azuredevopsLogo,
|
||||||
}
|
}
|
||||||
case "generic-git-host":
|
case "git":
|
||||||
|
case "genericGitHost":
|
||||||
return {
|
return {
|
||||||
src: gitLogo,
|
src: gitLogo,
|
||||||
}
|
}
|
||||||
|
|
@ -340,13 +332,13 @@ export const getCodeHostCommitUrl = ({
|
||||||
return `${webUrl}/commit/${commitHash}`;
|
return `${webUrl}/commit/${commitHash}`;
|
||||||
case 'azuredevops':
|
case 'azuredevops':
|
||||||
return `${webUrl}/commit/${commitHash}`;
|
return `${webUrl}/commit/${commitHash}`;
|
||||||
case 'bitbucket-cloud':
|
case 'bitbucketCloud':
|
||||||
return `${webUrl}/commits/${commitHash}`;
|
return `${webUrl}/commits/${commitHash}`;
|
||||||
case 'bitbucket-server':
|
case 'bitbucketServer':
|
||||||
return `${webUrl}/commits/${commitHash}`;
|
return `${webUrl}/commits/${commitHash}`;
|
||||||
case 'gerrit':
|
case 'gerrit':
|
||||||
return `${webUrl}/+/${commitHash}`;
|
return `${webUrl}/+/${commitHash}`;
|
||||||
case 'generic-git-host':
|
case 'genericGitHost':
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -373,13 +365,13 @@ export const getCodeHostBrowseAtBranchUrl = ({
|
||||||
return `${webUrl}/src/branch/${branchName}`;
|
return `${webUrl}/src/branch/${branchName}`;
|
||||||
case 'azuredevops':
|
case 'azuredevops':
|
||||||
return `${webUrl}?branch=${branchName}`;
|
return `${webUrl}?branch=${branchName}`;
|
||||||
case 'bitbucket-cloud':
|
case 'bitbucketCloud':
|
||||||
return `${webUrl}?at=${branchName}`;
|
return `${webUrl}?at=${branchName}`;
|
||||||
case 'bitbucket-server':
|
case 'bitbucketServer':
|
||||||
return `${webUrl}?at=${branchName}`;
|
return `${webUrl}?at=${branchName}`;
|
||||||
case 'gerrit':
|
case 'gerrit':
|
||||||
return `${webUrl}/+/${branchName}`;
|
return `${webUrl}/+/${branchName}`;
|
||||||
case 'generic-git-host':
|
case 'genericGitHost':
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -389,11 +381,11 @@ export const isAuthSupportedForCodeHost = (codeHostType: CodeHostType): boolean
|
||||||
case "github":
|
case "github":
|
||||||
case "gitlab":
|
case "gitlab":
|
||||||
case "gitea":
|
case "gitea":
|
||||||
case "bitbucket-cloud":
|
case "bitbucketCloud":
|
||||||
case "bitbucket-server":
|
case "bitbucketServer":
|
||||||
case "azuredevops":
|
case "azuredevops":
|
||||||
return true;
|
return true;
|
||||||
case "generic-git-host":
|
case "genericGitHost":
|
||||||
case "gerrit":
|
case "gerrit":
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,6 @@
|
||||||
"$ref": "#/definitions/Token",
|
"$ref": "#/definitions/Token",
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT).",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{ "env": "ENV_VAR_CONTAINING_TOKEN" }
|
{ "env": "ENV_VAR_CONTAINING_TOKEN" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -210,7 +209,6 @@
|
||||||
"$ref": "#/definitions/Token",
|
"$ref": "#/definitions/Token",
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token.",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{ "env": "ENV_VAR_CONTAINING_TOKEN" }
|
{ "env": "ENV_VAR_CONTAINING_TOKEN" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -332,7 +330,6 @@
|
||||||
"$ref": "#/definitions/Token",
|
"$ref": "#/definitions/Token",
|
||||||
"description": "An access token.",
|
"description": "An access token.",
|
||||||
"examples": [
|
"examples": [
|
||||||
"secret-token",
|
|
||||||
{ "env": "ENV_VAR_CONTAINING_TOKEN" }
|
{ "env": "ENV_VAR_CONTAINING_TOKEN" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,7 @@
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"$ref": "./shared.json#/definitions/Token",
|
"$ref": "./shared.json#/definitions/Token",
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT)."
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,7 @@
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"$ref": "./shared.json#/definitions/Token",
|
"$ref": "./shared.json#/definitions/Token",
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token."
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,7 @@
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"$ref": "./shared.json#/definitions/Token",
|
"$ref": "./shared.json#/definitions/Token",
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT)."
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,7 @@
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"$ref": "./shared.json#/definitions/Token",
|
"$ref": "./shared.json#/definitions/Token",
|
||||||
"description": "A Personal Access Token (PAT).",
|
"description": "A Personal Access Token (PAT)."
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,7 @@
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"$ref": "./shared.json#/definitions/Token",
|
"$ref": "./shared.json#/definitions/Token",
|
||||||
"description": "An authentication token.",
|
"description": "An authentication token."
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"secret": "SECRET_KEY"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,6 @@
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"Token": {
|
"Token": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secret": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the secret that contains the token."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue