neo.sh 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #!/usr/bin/env bash
  2. # The NEO web client as service `neo` in the una-ci Railway project, next to `una` and `mariadb`.
  3. # Used by .github/workflows/ci.yml. Kept out of the workflow because Railway's reference syntax
  4. # (${{una.UNA_API_KEY}}) is also GitHub Actions expression syntax.
  5. #
  6. # neo.sh instance <environment> give <environment> a neo instance if it has none
  7. # neo.sh vars <environment> <una-url> <app-url> set the variables the build and the server need
  8. # neo.sh stage <dir> NEO sources plus scripts/railway/neo/* in <dir>
  9. #
  10. # Environment: RAILWAY_API_TOKEN, RAILWAY_PROJECT_ID.
  11. set -euo pipefail
  12. NEO_SERVICE=neo
  13. die() { echo "neo.sh: $*" >&2; exit 1; }
  14. # Railway services are project-scoped, but an environment only runs the services it has an
  15. # instance of. PR environments get theirs by duplicating pr-template; one duplicated before
  16. # the neo service existed, or the template itself, gets it through a config patch.
  17. instance() {
  18. local env=$1 env_id service_id
  19. if railway service status --service "$NEO_SERVICE" --environment "$env" >/dev/null 2>&1; then
  20. echo "neo: $env has a $NEO_SERVICE instance"
  21. return
  22. fi
  23. [ -n "${RAILWAY_PROJECT_ID:-}" ] || die "RAILWAY_PROJECT_ID is not set"
  24. local project
  25. project=$(railway api 'query($id: String!) { project(id: $id) { environments { edges { node { id name } } } services { edges { node { id name } } } } }' \
  26. --variables "$(jq -nc --arg id "$RAILWAY_PROJECT_ID" '{id: $id}')")
  27. env_id=$(jq -r --arg e "$env" '.data.project.environments.edges[].node | select(.name == $e) | .id' <<< "$project")
  28. service_id=$(jq -r --arg s "$NEO_SERVICE" '.data.project.services.edges[].node | select(.name == $s) | .id' <<< "$project")
  29. [ -n "$env_id" ] || die "no environment $env"
  30. [ -n "$service_id" ] || die "no service $NEO_SERVICE in the project"
  31. railway api 'mutation($e: String!, $p: EnvironmentConfig!) { environmentPatchCommit(environmentId: $e, patch: $p, commitMessage: "Add neo service", skipDeploys: true) }' \
  32. --variables "$(jq -nc --arg e "$env_id" --arg s "$service_id" \
  33. '{e: $e, p: {services: {($s): {isCreated: true, build: {builder: "DOCKERFILE"}}}}}')" >/dev/null
  34. for _ in $(seq 1 12); do
  35. railway service status --service "$NEO_SERVICE" --environment "$env" >/dev/null 2>&1 && { echo "neo: added a $NEO_SERVICE instance to $env"; return; }
  36. sleep 5
  37. done
  38. die "the $NEO_SERVICE instance did not appear in $env"
  39. }
  40. # UNA_API_KEY references the una service's own variable, so the key lives in one place and
  41. # Railway shows the two services as connected. <una-url> may be a reference too.
  42. vars() {
  43. local env=$1 una_url=$2 app_url=$3
  44. railway variable set --service "$NEO_SERVICE" --environment "$env" --skip-deploys \
  45. "UNA_URL=$una_url" \
  46. "NEXT_PUBLIC_UNA_URL=$una_url" \
  47. "APP_URL=$app_url" \
  48. "NEXT_PUBLIC_APP_URL=$app_url" \
  49. 'UNA_API_KEY=${{una.UNA_API_KEY}}'
  50. }
  51. stage() {
  52. local dir=$1 root
  53. root=$(git rev-parse --show-toplevel)
  54. rm -rf "$dir"
  55. mkdir -p "$dir"
  56. git -C "$root" archive HEAD neo | tar -x --strip-components=1 -C "$dir"
  57. cp "$root/scripts/railway/neo/Dockerfile" "$root/scripts/railway/neo/railway.toml" "$root/scripts/railway/neo/.dockerignore" "$dir/"
  58. }
  59. case "${1:-}" in
  60. instance) instance "${2:?environment}" ;;
  61. vars) vars "${2:?environment}" "${3:?una-url}" "${4:?app-url}" ;;
  62. stage) stage "${2:?dir}" ;;
  63. *) die "usage: neo.sh instance|vars|stage ..." ;;
  64. esac