Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ published version with a date and open a fresh empty `[Unreleased]` above it.

### Added

- `@relayfile/adapter-gitlab` now creates issues, branches, and merge requests from file-native drafts; accepts or closes/reopens merge requests through canonical sidecars; and publishes schemas, examples, catalog paths, and `LAYOUT.md` guidance for every supported GitLab writeback route.
- `@relayfile/adapter-github` and the core GitHub mapping now declare `check_run` and `issue_comment` webhook keys, so consumers that read the mapping's `webhooks:` block can subscribe to CI check completions and issue/PR conversation comments.
- `@relayfile/adapter-github` now exports a cursor-resumable pull-index convergence primitive that backfills `headRef` with one GitHub list request per invocation and no per-record metadata, file, or diff fetches.
- `@relayfile/adapter-linear` now materializes `/linear/issues/by-project/<project-id>/<identifier>.json` aliases so project-scoped consumers can avoid mounting the full issue tree. The path mapper and generated `LAYOUT.md` contract expose the new lookup; existing mounts must resync to materialize and discover it.
Expand Down
2 changes: 1 addition & 1 deletion docs/writeback-spec-coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Contract-backed means the endpoint uses `contractEndpoint(...)`, loads its reque
| fathom | None | 0 | 0 | Read-only adapter for meetings, recording summaries/transcripts, teams, and team members; no writeback endpoints. |
| gcp | None | 0 | 0 | Read-only observer adapter for Cloud Run services, Cloud Monitoring alert policies, and Cloud Billing current state; no writeback endpoints. |
| gcs | None | 0 | 2 | Inline JS schemas. |
| gitlab | None | 0 | 2 | Inline JS schemas. |
| gitlab | None | 0 | 9 | Inline JS schemas for issue and merge-request create/update, branch creation, merge-request accept/close/reopen, discussions, and issue notes. |
| gmail | None | 0 | 3 | Three legacy discovery schemas remain inline. The additive `/gmail` control contract owns Cloud's separate bounded 13-action Gmail surface; it is not a discovery schema or a provider executor. |
| google-calendar | None | 0 | 1 | Inline JS schemas. |
| google-drive | None | 0 | 2 | Inline JS schemas. |
Expand Down
15 changes: 15 additions & 0 deletions packages/core/mappings/adapters/gitlab.mapping.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,24 @@ resources:
path: /gitlab/projects/{namespace}/{project}/pipelines/{id}__{ref}/jobs/{job_id}.json
iterate: true
writebacks:
issue_create:
match: /gitlab/projects/*/issues/*.json
endpoint: POST /projects/{project_id}/issues
merge_request_update:
match: /gitlab/projects/*/merge_requests/*/meta.json
endpoint: PUT /projects/{project_id}/merge_requests/{iid}
merge_request_create:
match: /gitlab/projects/*/merge-requests/*.json
endpoint: POST /projects/{project_id}/merge_requests
merge_request_merge:
match: /gitlab/projects/*/merge_requests/*/merge.json
endpoint: PUT /projects/{project_id}/merge_requests/{iid}/merge
merge_request_close:
match: /gitlab/projects/*/merge_requests/*/close.json
endpoint: PUT /projects/{project_id}/merge_requests/{iid}
branch_create:
match: /gitlab/projects/*/refs/*.json
endpoint: POST /projects/{project_id}/repository/branches
merge_request_discussion:
match: /gitlab/projects/*/merge_requests/*/discussions/*.json
endpoint: POST /projects/{project_id}/merge_requests/{iid}/discussions
Expand Down
22 changes: 17 additions & 5 deletions packages/core/src/runtime/file-native-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -708,15 +708,27 @@ function readExactFileResourceId(
): string | undefined {
const pathSegments = path.split("/").filter(Boolean);
const resourceSegments = resource.path.split("/").filter(Boolean);
if (pathSegments.length !== resourceSegments.length) {
if (pathSegments.length < resourceSegments.length) {
return undefined;
}

for (let index = resourceSegments.length - 1; index >= 0; index -= 1) {
const resourceSegment = resourceSegments[index];
const pathSegment = pathSegments[index];
// A `{projectPath}` placeholder may stand for a nested GitLab namespace,
// so an exact sidecar template can have fewer segments than its concrete
// path. Match fixed suffix segments from the right and return the nearest
// dynamic record-id segment instead of requiring equal segment counts.
let pathIndex = pathSegments.length - 1;
for (let resourceIndex = resourceSegments.length - 1; resourceIndex >= 0; resourceIndex -= 1) {
const resourceSegment = resourceSegments[resourceIndex];
const pathSegment = pathSegments[pathIndex];
if (!resourceSegment || !pathSegment) {
return undefined;
}
const placeholder = /\{[^}]+\}/u.exec(resourceSegment);
if (!placeholder || !pathSegment) {
if (!placeholder) {
if (resourceSegment !== pathSegment) {
return undefined;
}
pathIndex -= 1;
continue;
}
if (resourceSegment.endsWith(".json") && pathSegment.endsWith(".json")) {
Expand Down
60 changes: 60 additions & 0 deletions packages/core/src/writeback-paths/catalog.generated.json
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,16 @@
]
},
"gitlab": {
"close-merge-request": [
{
"path": "/gitlab/projects/{projectPath}/merge_requests/{mergeRequestIid}__{slug}/close.json",
"params": [
"projectPath",
"mergeRequestIid",
"slug"
]
}
],
"comments": [
{
"path": "/gitlab/projects/{projectPath}/issues/{issueIid}__{slug}/comments",
Expand All @@ -388,6 +398,56 @@
"slug"
]
}
],
"issues": [
{
"path": "/gitlab/projects/{projectPath}/issues",
"params": [
"projectPath"
]
},
{
"path": "/gitlab/projects/{projectPath}/issues/{issueIid}__{slug}/meta.json",
"params": [
"projectPath",
"issueIid",
"slug"
]
}
],
"merge": [
{
"path": "/gitlab/projects/{projectPath}/merge_requests/{mergeRequestIid}__{slug}/merge.json",
"params": [
"projectPath",
"mergeRequestIid",
"slug"
]
}
],
"merge-requests": [
{
"path": "/gitlab/projects/{projectPath}/merge_requests/{mergeRequestIid}__{slug}/meta.json",
"params": [
"projectPath",
"mergeRequestIid",
"slug"
]
},
{
"path": "/gitlab/projects/{projectPath}/merge-requests",
"params": [
"projectPath"
]
}
],
"refs": [
{
"path": "/gitlab/projects/{projectPath}/refs",
"params": [
"projectPath"
]
}
]
},
"gmail": {
Expand Down
60 changes: 60 additions & 0 deletions packages/core/src/writeback-paths/catalog.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,16 @@ export const WRITEBACK_PATH_CATALOG = {
]
},
"gitlab": {
"close-merge-request": [
{
"path": "/gitlab/projects/{projectPath}/merge_requests/{mergeRequestIid}__{slug}/close.json",
"params": [
"projectPath",
"mergeRequestIid",
"slug"
]
}
],
"comments": [
{
"path": "/gitlab/projects/{projectPath}/issues/{issueIid}__{slug}/comments",
Expand All @@ -398,6 +408,56 @@ export const WRITEBACK_PATH_CATALOG = {
"slug"
]
}
],
"issues": [
{
"path": "/gitlab/projects/{projectPath}/issues",
"params": [
"projectPath"
]
},
{
"path": "/gitlab/projects/{projectPath}/issues/{issueIid}__{slug}/meta.json",
"params": [
"projectPath",
"issueIid",
"slug"
]
}
],
"merge": [
{
"path": "/gitlab/projects/{projectPath}/merge_requests/{mergeRequestIid}__{slug}/merge.json",
"params": [
"projectPath",
"mergeRequestIid",
"slug"
]
}
],
"merge-requests": [
{
"path": "/gitlab/projects/{projectPath}/merge_requests/{mergeRequestIid}__{slug}/meta.json",
"params": [
"projectPath",
"mergeRequestIid",
"slug"
]
},
{
"path": "/gitlab/projects/{projectPath}/merge-requests",
"params": [
"projectPath"
]
}
],
"refs": [
{
"path": "/gitlab/projects/{projectPath}/refs",
"params": [
"projectPath"
]
}
]
},
"gmail": {
Expand Down
Loading
Loading