Aufgaben mit der API automatisieren
Während die Codesphere CLI hervorragend für Terminal-Workflows und die Nutzung in CI/CD-Pipelines mit vorab festgelegten Anwendungsfällen geeignet ist, ermöglicht die Public API das Schreiben eigener Skripte, um deine Pipelines zu automatisieren, Infrastruktur-Lebenszyklen zu verwalten und Codesphere in deine internen Tools zu integrieren.
Dieser Leitfaden behandelt die Grundlagen des Skriptings und liefert praxisnahe Automatisierungsbeispiele.
Erste Schritte
Um programmatisch mit der Codesphere API zu interagieren, benötigst du zwei Dinge: einen HTTP-Client und einen sicheren Weg, deinen Authentifizierungstoken zu übergeben.
Authentifizierungs-Header
Jede API-Anfrage benötigt einen Authorization-Header, der deinen API-Token im Bearer-Token-Format enthält.
Secret-Management
Hardcode niemals deinen API-Token in deinen Skripten. Lade ihn immer aus einer Umgebungsvariable oder einem sicheren Secret Manager (z. B. AWS Secrets Manager, GitHub Secrets), um versehentliche Leaks in der Versionskontrolle zu vermeiden.
Grundlegende HTTP-Client-Einrichtung
Hier ist ein Beispiel, wie du eine grundlegende authentifizierte Anfrage einrichtest, um die Workspaces deines Teams in gängigen Sprachen abzurufen. Idealerweise testest du einzelne Anfragen mit Tools wie Postman, bevor du diese Skripte schreibst.
- Python (requests)
- Node.js (fetch)
Mit der beliebten requests-Bibliothek:
import os
import requests
# Zugangsdaten aus Umgebungsvariablen laden
API_TOKEN = os.environ.get("CODESPHERE_TOKEN")
TEAM_ID = os.environ.get("CODESPHERE_TEAM_ID")
BASE_URL = "https://cloud.codesphere.com/api"
headers = {
"Authorization": f"Bearer {API_TOKEN}",
"Content-Type": "application/json"
}
# Beispiel: Alle Workspaces abrufen
response = requests.get(f"{BASE_URL}/workspaces?teamId={TEAM_ID}", headers=headers)
if response.status_code == 200:
print("Workspaces fetched successfully!")
print(response.json())
else:
print(f"Error: {response.status_code} - {response.text}")
Mit der nativen fetch-API (Node.js 18+):
// Zugangsdaten aus Umgebungsvariablen laden
const API_TOKEN = process.env.CODESPHERE_TOKEN;
const TEAM_ID = process.env.CODESPHERE_TEAM_ID;
const BASE_URL = "https://cloud.codesphere.com/api";
const headers = {
"Authorization": `Bearer ${API_TOKEN}`,
"Content-Type": "application/json"
};
// Beispiel: Alle Workspaces abrufen
async function getWorkspaces() {
const response = await fetch(`${BASE_URL}/workspaces?teamId=${TEAM_ID}`, {
method: 'GET',
headers: headers
});
if (response.ok) {
const data = await response.json();
console.log("Workspaces fetched successfully!", data);
} else {
console.error(`Error: ${response.status} - ${await response.text()}`);
}
}
getWorkspaces();
Automatisierungsbeispiele
Im Folgenden findest du praxisnahe Beispiele, wie du die API nutzen kannst, um mühsame Aufgaben im Lebenszyklus-Management zu automatisieren.
Deployment-Status in interne Tools integrieren
Wenn dein Unternehmen ein eigenes internes Entwicklerportal (wie Backstage) oder einen benutzerdefinierten Slack-Bot verwendet, möchtest du vielleicht regelmäßig die API abfragen, um den Zustand und Pipeline-Status eines bestimmten Deployments zu melden.
Dieses Skript zeigt, wie man den Status der Pipeline eines bestimmten Workspaces abruft.
- Python
- Node.js
import os
import requests
API_TOKEN = os.environ.get("CODESPHERE_TOKEN")
WORKSPACE_ID = "YOUR_WORKSPACE_ID"
BASE_URL = "https://cloud.codesphere.com/api"
HEADERS = {"Authorization": f"Bearer {API_TOKEN}"}
def check_deployment_status():
# Status der Run-Pipeline abrufen
url = f"{BASE_URL}/workspaces/{WORKSPACE_ID}/pipeline/run"
response = requests.get(url, headers=HEADERS)
if response.status_code == 200:
status_data = response.json()
# Relevante Statusinformationen extrahieren
state = status_data.get("status", "UNKNOWN")
is_running = state == "RUNNING"
print(f"Deployment Status: {state}")
# Beispiellogik für die Integration in interne Tools
if not is_running:
print("Alert: The application is currently down or stopped!")
# trigger_slack_alert(f"Workspace {WORKSPACE_ID} is down!")
return state
else:
print(f"Failed to fetch status: {response.text}")
return None
if __name__ == "__main__":
check_deployment_status()
const API_TOKEN = process.env.CODESPHERE_TOKEN;
const WORKSPACE_ID = "YOUR_WORKSPACE_ID";
const BASE_URL = "https://cloud.codesphere.com/api";
const HEADERS = { "Authorization": `Bearer ${API_TOKEN}` };
async function checkDeploymentStatus() {
// Status der Run-Pipeline abrufen
const url = `${BASE_URL}/workspaces/${WORKSPACE_ID}/pipeline/run`;
const response = await fetch(url, { headers: HEADERS });
if (response.ok) {
const statusData = await response.json();
// Relevante Statusinformationen extrahieren
const state = statusData.status || "UNKNOWN";
const isRunning = state === "RUNNING";
console.log(`Deployment Status: ${state}`);
// Beispiellogik für die Integration in interne Tools
if (!isRunning) {
console.warn("Alert: The application is currently down or stopped!");
// triggerSlackAlert(`Workspace ${WORKSPACE_ID} is down!`);
}
return state;
} else {
console.error(`Failed to fetch status: ${await response.text()}`);
return null;
}
}
checkDeploymentStatus();
Umgang mit API-Limits
Wenn du Skripte schreibst, die Endpunkte abfragen (z. B. Deployment-Status in einer Schleife prüfen), stelle sicher, dass du eine Verzögerung (z. B. time.sleep(5) oder setTimeout) zwischen den Anfragen einbaust, um Rate-Limits zu vermeiden.
Deployment- & Release-Workflows
Während einzelne Endpunkte für sich genommen wertvoll sind, entfaltet sich die eigentliche Stärke erst durch die Kombination mehrerer API-Aufrufe zu einem vollständigen Release-Flow (z. B. das Auslösen eines Releases bei einem Merge in einer GitHub Action).
Einfacher Release-Fall
Der einfache Fall eignet sich gut für statische Websites und Anwendungen, die fast augenblicklich neu starten können.
- Änderungen abrufen (Pull):
POST /workspaces/{workspaceId}/git/pull/{remote} - Anwendung neu bauen (optional):
POST /workspaces/{workspaceId}/pipeline/prepare/start - Auf Build warten:
GET /workspaces/{workspaceId}/pipeline/prepareabfragen, bis 200 zurückgegeben wird. - Anwendung stoppen:
POST /workspaces/{workspaceId}/pipeline/run/stop - Anwendung neu starten:
POST /workspaces/{workspaceId}/pipeline/run/start
Zero-Downtime-Releases automatisieren
Für unternehmenskritische Anwendungen, bei denen Ausfallzeiten nicht akzeptabel sind, kannst du ein Blue/Green-Zero-Downtime-Release vollständig über die API automatisieren:
- Neuen Workspace erstellen:
POST /workspaces(Definiere den neuen Git-Commit, die Team-ID, Plan-ID, den Branch und die Replica-Anzahl). - Abhängigkeiten bauen:
POST /workspaces/{workspaceId}/pipeline/prepare/start - Auf Build warten:
GET /workspaces/{workspaceId}/pipeline/prepareabfragen, bis erfolgreich. - Tests ausführen (optional):
POST /workspaces/{workspaceId}/pipeline/test/startund abfragen, bis erfolgreich. Brich den Ablauf ab, falls Tests fehlschlagen! - Anwendung starten:
POST /workspaces/{workspaceId}/pipeline/run/start - Domain-Routing umschalten: Sobald die neue Anwendung fehlerfrei läuft, leite den Traffic sofort dorthin um, indem du die Workspace-Verbindung aktualisierst:
PUT /domains/team/{teamId}/domain/{domainName}/workspace-connections
Replicas programmatisch skalieren
Codesphere Workspaces können mehrere Services gleichzeitig als Teil eines Landscapes ausführen (z. B. ein Frontend, ein Backend und eine Datenbank).
Du kannst die Anzahl der horizontalen Replicas für bestimmte Services innerhalb deines Workspaces dynamisch anpassen.
Über den Endpunkt PATCH /workspaces/{workspaceId}/landscape/scale kannst du ein JSON-Objekt übergeben, bei dem die Keys die exakten Namen deiner Services sind und die Values die gewünschte Anzahl an Replicas.
- Python
- Node.js
import os
import json
import urllib.request
API_TOKEN = os.environ.get("CODESPHERE_TOKEN")
WORKSPACE_ID = "YOUR_WORKSPACE_ID"
BASE_URL = "YOUR_CODESPHERE_INSTANCE_URL/api"
url = f"{BASE_URL}/workspaces/{WORKSPACE_ID}/landscape/scale"
payload = json.dumps({
"YOUR-SERVICE-NAME": 1 # <--- ÄNDERE DIES ZU DEINEM SERVICE-NAMEN & der gewünschten Anzahl an Replicas (z. B. "backend")
}).encode('utf-8')
headers = {
"Authorization": f"Bearer {API_TOKEN}",
"Content-Type": "application/json",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
}
req = urllib.request.Request(url, data=payload, headers=headers, method='PATCH')
try:
with urllib.request.urlopen(req) as response:
if response.status in [200, 204]:
print(f"Success! Services in Workspace {WORKSPACE_ID} have been scaled.")
except urllib.error.HTTPError as e:
print(f"Failed to scale. Error code: {e.code}")
print(e.read().decode())
except Exception as e:
print(f"An error occurred: {e}")
const API_TOKEN = process.env.CODESPHERE_TOKEN;
const WORKSPACE_ID = "YOUR_WORKSPACE_ID";
const BASE_URL = "https://cloud.codesphere.com/api";
const headers = {
"Authorization": `Bearer ${API_TOKEN}`,
"Content-Type": "application/json",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
};
async function scaleServices(servicesMap) {
// Der Landscape-Scaling-Endpunkt
const url = `${BASE_URL}/workspaces/${WORKSPACE_ID}/landscape/scale`;
const response = await fetch(url, {
method: 'PATCH',
headers: headers,
body: JSON.stringify(servicesMap)
});
if (response.ok) {
console.log(`Successfully scaled services in workspace ${WORKSPACE_ID}!`);
} else {
const errorText = await response.text();
console.error(`Failed to scale. Status code: ${response.status}`);
console.error(errorText);
}
}
// Frontend auf 2 Replicas skalieren
scaleServices({
"YOUR-SERVICE-NAME": 2 // <--- ÄNDERE DIES ZU DEINEM TATSÄCHLICHEN SERVICE-NAMEN (z. B. "backend")
});
400-Fehler: Plan-Limits & ungültige Werte
Wenn du beim Skalieren von Replicas einen 400 Bad Request-Fehler erhältst, bedeutet das in der Regel eines von zwei Dingen:
- Plan-Limit überschritten: Du versuchst, über die maximale Anzahl an Replicas hinaus zu skalieren, die im aktuellen Plan deines Services erlaubt ist. Zum Beispiel schlägt eine Anfrage nach
5Replicas bei einem auf3begrenzten Plan fehl. - Ungültige Ganzzahl: Die API erfordert eine positive Ganzzahl. Wird die Replica-Anzahl auf
0oder eine negative Zahl gesetzt, führt das zu einem Typfehler.