Repository Connections API

Manages links to source-control and object-storage providers so DB DevOps can pull migration scripts from your existing repositories and buckets. Base path /api/db-devops/repo-connections, needs an active license, authenticated. Provider tokens/keys are stored in the encrypted config blob and never returned in cleartext.

Endpoints

MethodEndpointDescription
GET/repo-connectionsList
GET/repo-connections/:idSingle
POST/repo-connectionsCreate
PUT/repo-connections/:idUpdate
DELETE/repo-connections/:idDelete
POST/repo-connections/:id/testTest connectivity (no writes)
POST/repo-connections/test-configValidate a config payload before saving
POST/repo-connections/:id/pullPull scripts into DB DevOps as migration records
POST/repo-connections/:id/browseList files matching file_pattern without importing

POST /api/db-devops/repo-connections

Common fields

FieldTypeRequiredDescription
namestringYesDisplay name
providerstringYesgithub, gitlab, bitbucket, azure_devops, s3, azure_blob, gcs, dropbox
configobjectYesProvider-specific credentials (below)
default_branchstringNoSCM only (e.g. main); ignored for storage
release_pathstringNoPath/prefix for release scripts
adhoc_pathstringNoPath/prefix for ad-hoc scripts
file_patternstringNoGlob for script files (default *.sql)

Provider config schemas

GitHub

curl -X POST http://localhost:5002/api/db-devops/repo-connections \\
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \\
  -d '{ "name": "Production GitHub", "provider": "github",
        "config": { "token": "GITHUB_PAT", "owner": "my-org", "repo": "db-migrations" },
        "default_branch": "main", "release_path": "migrations/release",
        "adhoc_path": "migrations/adhoc", "file_pattern": "*.sql" }'

token (PAT with repo scope), owner, repo — all required.

GitLab

{ "provider": "gitlab",
  "config": { "token": "GITLAB_PAT", "project_id": "12345678", "base_url": "https://gitlab.com" } }

token (read_repository), project_id required; base_url optional for self-hosted.

Bitbucket

{ "provider": "bitbucket",
  "config": { "username": "you@example.com", "app_password": "ATLASSIAN_API_TOKEN",
              "workspace": "my-workspace", "repo_slug": "db-migrations" } }

username is the Atlassian account email and app_password holds an Atlassian API token created with Bitbucket scopes (at least read:repository:bitbucket); the field keeps its name for existing sources.

Azure DevOps

{ "provider": "azure_devops",
  "config": { "token": "ADO_PAT", "organization": "my-org",
              "project": "my-project", "repository": "db-migrations" } }

token needs Code (Read) scope.

Amazon S3

{ "provider": "s3",
  "config": { "accessKeyId": "AKIA...", "secretAccessKey": "...",
              "region": "us-east-1", "bucket": "my-db-migrations" } }

Azure Blob Storage

{ "provider": "azure_blob",
  "config": { "connection_string": "DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...",
              "container": "db-migrations" } }

Google Cloud Storage

{ "provider": "gcs",
  "config": { "credentials_json": "{...service account JSON...}",
              "bucket": "my-db-migrations" } }

The service account needs only Storage Object Viewer (roles/storage.objectViewer) on the bucket.

Dropbox

{ "provider": "dropbox",
  "config": { "app_key": "APP_KEY", "app_secret": "APP_SECRET",
              "refresh_token": "REFRESH_TOKEN", "root_folder": "/migrations" } }

The refresh token comes from Dropbox's OAuth code flow with token_access_type=offline; the app exchanges it for short-lived access tokens as needed. An access_token alone also works, but Dropbox access tokens expire after about four hours. The app needs the files.metadata.read and files.content.read permissions. release_path/adhoc_path are folder paths below root_folder.

Test, pull, browse

// POST /repo-connections/:id/test   (POST /repo-connections/test-config tests unsaved settings)
{ "success": true,  "message": "Connected to my-org/db-migrations (default branch main)" }
{ "success": false, "message": "GitHub returned 401: Bad credentials (check the token and its permissions)" }

// POST /repo-connections/:id/pull   body: { "mode": "release" | "adhoc", "environment": "Staging",
//        "targetConnectionId"?: "", "targetDatabase"?: "orders", "branch"?: "main", "path"?: "override/folder" }
// environment is required and must exist (matched regardless of case, stored under its own name); without it, or with an
// unknown one or a target that is not a connection, the pull is 400 INVALID_SCRIPT_TARGET before anything is read:
// { "success": false, "code": "INVALID_SCRIPT_TARGET", "message": "environment is required: choose one of: Development, Staging" }
// A target in another environment is 400 TARGET_IN_OTHER_ENVIRONMENT, also before anything is read:
// { "success": false, "code": "TARGET_IN_OTHER_ENVIRONMENT", "message": "Orders is in Staging, not Development: choose an instance in Development, or set the script's environment to Staging" }
// Walks the folder and every subfolder. New files are imported as pending scripts in that environment and target; a changed
// file updates its script (keeping its environment and target) and returns it to pending approval; unchanged files are skipped.
{ "success": true, "imported": 3, "updated": 2, "unchanged": 10, "matched": 15, "failed": [],
  "message": "Imported 3, updated 2, unchanged 10 (15 matching files)", "scripts": [ "..." ] }
// A provider error (bad token, missing branch, bucket or folder) returns 502 { "success": false, "message": "..." }
// and is recorded as the source's last sync status.

// POST /repo-connections/:id/browse   body: { "branch"?: "main", "path"?: "release" }   (lists one level without importing)
[ { "name": "postgresql", "path": "release/postgresql", "type": "directory" },
  { "name": "001_create_users.sql", "path": "release/001_create_users.sql", "type": "file", "size": 1024 } ]