9 months ago
Hello everyone,
I'm making a simple React app which eventually will become two Docker containers: one for my app, the other for my API.
I tried to implement the Railway API to my CI/CD pipeline, basically, what I wanted to do :
- My changed are pushed to/merged onto 'main' branch
- Github Actions runs some tests
- Then, it runs a Python script which executes steps 4-6
- Two containers are built from my project and pushed to Docker Hub with a specific tag
- The script sends a mutation request for the 'serviceInstanceUpdate()' method
- The scripts sends another mutation request for the 'serviceInstanceRedeploy()' method
- My two services are updated and running with the correct container image
Keep in mind that I'm very new using this kind of automated pipeline, and I never touched GraphQL before. I tried my best with the Railway sandbox, using the same mutation with the same variables and header, but to no avail.
If that might help, here's the python script:
import os, requests, datetime, subprocess
DOCKER_USER = "username"
API_NAME = "xxx-api"
APP_NAME = "xxx-app"
RAILWAY_API_URL = "https://backboard.railway.com/graphql/v2"
RAILWAY_TOKEN = os.environ.get("RAILWAY_TOKEN")
RAILWAY_API_SERVICE_ID = os.environ.get("RAILWAY_API_SERVICE_ID")
RAILWAY_API_ENV_ID = os.environ.get("RAILWAY_API_ENV_ID")
RAILWAY_APP_SERVICE_ID = os.environ.get("RAILWAY_APP_SERVICE_ID")
RAILWAY_APP_ENV_ID = os.environ.get("RAILWAY_APP_ENV_ID")
TAG = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
def run(cmd):
print(f"$ {cmd}")
subprocess.run(cmd, shell=True, check=True)
def docker_build_and_push(name, path):
image = f"{DOCKER_USER}/{name}:{TAG}"
run(f"docker build -t {image} {path}")
run(f"docker push {image}")
return image
def railway_update(service_id, env_id, image):
mutation = """
mutation serviceInstanceUpdate($environmentId: String!, $input: ServiceInstanceUpdateInput!, $serviceId: $String!) {
serviceInstanceUpdate(environmentId: $id, input: $input, serviceId: $serviceId) {
environmentId
input
serviceId
}
}
"""
variables = {
"environmentId": env_id,
"serviceId": service_id,
"input": {
"source": {
"image": image
}
}
}
headers = {
"Authorization": f"Bearer {RAILWAY_TOKEN}",
"Content-Type": "application/json"
}
req = requests.post(
RAILWAY_API_URL,
json={ "query": mutation, "variables": variables },
headers=headers
)
req.raise_for_status()
print("Railway update response:", req.json())
def main():
print("[1/3] Building and pushing API...")
api_image = docker_build_and_push(API_NAME, "./api")
print("[2/3] Building and pushing app...")
app_image = docker_build_and_push(APP_NAME, "./")
print("[3/3] Updating Railway services...")
railway_update(RAILWAY_API_SERVICE_ID, RAILWAY_API_ENV_ID, api_image)
railway_update(RAILWAY_APP_SERVICE_ID, RAILWAY_APP_ENV_ID, app_image)
print("🚀 Deployment successful with tag:", TAG)
if __name__ == "__main__":
main()The closest hint I can get is from the Github Actions' error message, telling me that it returned an error code 400, which might mean I didn't properly write the request.
I'm very thankful for your help, it's been bothering me for a while, and this is pretty time-sensitive. And, apologies for my bad english.
Attachments
2 Replies
9 months ago
Hey there! We've found the following might help you get unblocked faster:
- 🧵 Getting error Bad request 400 when trying to access my website AVEXCLUSIVEAUTO.com
- 🧵 Error while connecting Google OAuth 2.0 Client IDs
- 🧵 Bad Request Error
If you find the answer from one of these, please let us know by solving the thread!
9 months ago
Oh, by the way, I forgot the "serviceInstanceRedeploy" method in python
def railway_redeploy(env_id, service_id):
mutation = """
mutation serviceInstanceRedeploy($environmentId: String!, $serviceId: $String!) {
serviceInstanceRedeploy(environmentId: $id, serviceId: $serviceId) {
environmentId
input
serviceId
}
}
"""
variables = {
"environmentId": env_id,
"serviceId": service_id
}
headers = {
"Authorization": f"Bearer {RAILWAY_TOKEN}",
"Content-Type": "application/json"
}
req = requests.post(
RAILWAY_API_URL,
json={ "query": mutation, "variables": variables },
headers=headers
)
req.raise_for_status()
print("Railway update response:", req.json())