Zum Inhalt

Workspace API für CI/CD

Die Workspace API liest und ändert Dateien eines DATAMIMIC-Projekts aus CI/CD. Sie ist der kanonische 4.0-Ersatz für die veralteten /files-Routen.

Authentifizierung

Erstelle ein Project Access Token für das Zielprojekt und sende es als Bearer-Token:

1
2
3
4
export DATAMIMIC_URL="https://datamimic.example.com"
export PROJECT_ID="deine-projekt-id"
export PROJECT_TOKEN="dein-project-access-token"
export CLIENT_BINDING="ci-${CI_PIPELINE_ID:-local}"

Das Token kann nur auf sein eigenes Projekt zugreifen und muss als Secret behandelt werden. X-DATAMIMIC-Client-Binding ist kein Secret. Verwende einen stabilen Wert für die Lebensdauer eines CI-Jobs oder Client-Prozesses.

Was die Concurrency-Header bedeuten

Zum Lesen oder Erstellen einer neuen Datei ist kein Lock nötig. Bestehende Dateien werden durch drei Werte geschützt:

Wert Bedeutung Herkunft
X-DATAMIMIC-Client-Binding Identifiziert diesen CI-Job oder Client-Prozess Ein stabiler, frei gewählter Wert pro Job
ETag / If-Match Identifiziert die gelesene Dateiversion Aus /workspace/tree oder dem File-Response
X-DATAMIMIC-Lock-Generation Beweist den Besitz des aktuellen Locks generation aus /workspace/locks/acquire

Damit können zwei Clients einander nicht unbemerkt überschreiben. Ein veralteter ETag oder eine alte Lock-Generation schlägt sicher fehl.

Öffentliche Endpunkte

Methode Endpoint Verwendung
GET /workspace/tree Sichtbare Dateien, Quellen, ETags und Read-only-Zustand auflisten
GET /workspace/files/{path} Eine Base64-kodierte Datei und ihren ETag lesen
PUT /workspace/files/{path} Eine Datei erstellen oder aktualisieren
POST /workspace/locks/acquire Lock-Generation für eine Mutation an einer bestehenden Datei übernehmen
POST /workspace/locks/heartbeat Ein länger gehaltenes Lock erneuern
POST /workspace/locks/release Lock nach der letzten Mutation freigeben

Dateien auflisten und lesen

Der Tree enthält die wirkliche Quelle jeder sichtbaren Datei. workspace_path ist der sichtbare Pfad, source_project_id die Quellprojekt-ID. Gewinner aus verknüpften globalen Projekten sind readonly.

1
2
3
curl --fail-with-body --silent \
  "$DATAMIMIC_URL/api/v2/projects/$PROJECT_ID/workspace/tree" \
  -H "Authorization: Bearer $PROJECT_TOKEN"

Dateiinhalte werden als Base64-kodiertes text/plain zurückgegeben. Der Response enthält zusätzlich den aktuellen ETag-Header.

1
2
3
4
5
6
FILE_PATH="models/customer.xml"

curl --fail-with-body --silent \
  "$DATAMIMIC_URL/api/v2/projects/$PROJECT_ID/workspace/files/$FILE_PATH" \
  -H "Authorization: Bearer $PROJECT_TOKEN" \
  | base64 --decode > customer.xml

Datei atomar erstellen

If-None-Match: * erzwingt Create-only-Semantik. Existiert der Pfad bereits, schlägt der Request fehl, statt die Datei zu überschreiben.

1
2
3
4
5
6
curl --fail-with-body --request PUT \
  "$DATAMIMIC_URL/api/v2/projects/$PROJECT_ID/workspace/files/$FILE_PATH" \
  -H "Authorization: Bearer $PROJECT_TOKEN" \
  -H "X-DATAMIMIC-Client-Binding: $CLIENT_BINDING" \
  -H 'If-None-Match: *' \
  -F '[email protected];type=application/xml'

Datei sicher aktualisieren

Ein Update benötigt den aktuellen ETag und eine eigene Lock-Generation. Lies den ETag aus dem Tree und übernimm danach das Lock:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
ETAG=$(curl --fail-with-body --silent \
  "$DATAMIMIC_URL/api/v2/projects/$PROJECT_ID/workspace/tree" \
  -H "Authorization: Bearer $PROJECT_TOKEN" \
  | jq --raw-output --arg path "$FILE_PATH" \
    '.entries[] | select(.workspace_path == $path) | .etag')

GENERATION=$(curl --fail-with-body --silent --request POST \
  "$DATAMIMIC_URL/api/v2/projects/$PROJECT_ID/workspace/locks/acquire" \
  -H "Authorization: Bearer $PROJECT_TOKEN" \
  -H "X-DATAMIMIC-Client-Binding: $CLIENT_BINDING" \
  -H 'Content-Type: application/json' \
  --data "{\"path\":\"$FILE_PATH\"}" \
  | jq --raw-output '.generation')

curl --fail-with-body --request PUT \
  "$DATAMIMIC_URL/api/v2/projects/$PROJECT_ID/workspace/files/$FILE_PATH" \
  -H "Authorization: Bearer $PROJECT_TOKEN" \
  -H "X-DATAMIMIC-Client-Binding: $CLIENT_BINDING" \
  -H "X-DATAMIMIC-Lock-Generation: $GENERATION" \
  -H "If-Match: $ETAG" \
  -F '[email protected];type=application/xml'

Ein lang laufender Job erneuert das Lease über /workspace/locks/heartbeat. Wenn keine weitere Mutation geplant ist, gibt er es frei:

1
2
3
4
5
6
7
curl --fail-with-body --request POST \
  "$DATAMIMIC_URL/api/v2/projects/$PROJECT_ID/workspace/locks/release" \
  -H "Authorization: Bearer $PROJECT_TOKEN" \
  -H "X-DATAMIMIC-Client-Binding: $CLIENT_BINDING" \
  -H "X-DATAMIMIC-Lock-Generation: $GENERATION" \
  -H 'Content-Type: application/json' \
  --data "{\"path\":\"$FILE_PATH\"}"

Was bewusst nicht öffentlich ist

Template-Helfer, Bulk-Wizard-Flows, Entry-Move/Delete, Directory-Darstellungsmetadaten, Entry Visibility, Lock-Takeover, Durable Upload-/Database-Operationen und der Collaboration-WebSocket gehören zu first-party Produkt-Flows. Sie erscheinen nicht in /external_openapi.json.

Bei einem fremden Lock-Konflikt muss ein CI-Job stoppen. Er darf das Lock eines anderen Clients nicht automatisch übernehmen. Dieser Client kann ungespeicherte Änderungen besitzen.