mirror of
https://github.com/blackboxprogramming/BlackRoad-Operating-System.git
synced 2026-03-17 23:34:00 -05:00
Merge commit 'ada9006b1d2e73bc72267f4a7e6c34d5fb333b12'
This commit is contained in:
21
.github/workflows/deploy-all.yml
vendored
21
.github/workflows/deploy-all.yml
vendored
@@ -1,4 +1,5 @@
|
|||||||
name: Deploy All Services
|
name: Deploy All Services
|
||||||
|
name: Deploy BlackRoad OS
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@@ -7,6 +8,9 @@ on:
|
|||||||
description: "Optional service id to deploy"
|
description: "Optional service id to deploy"
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
|
description: "Optional service id to deploy (core, api, operator, agents, console, web, docs)"
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
@@ -25,6 +29,14 @@ jobs:
|
|||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: "18"
|
node-version: "18"
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Use Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm install
|
run: npm install
|
||||||
@@ -34,5 +46,14 @@ jobs:
|
|||||||
if [ -n "${{ github.event.inputs.serviceId }}" ]; then
|
if [ -n "${{ github.event.inputs.serviceId }}" ]; then
|
||||||
npm run deploy:service -- ${{ github.event.inputs.serviceId }}
|
npm run deploy:service -- ${{ github.event.inputs.serviceId }}
|
||||||
else
|
else
|
||||||
|
- name: Deploy
|
||||||
|
env:
|
||||||
|
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
|
||||||
|
run: |
|
||||||
|
if [ -n "${{ github.event.inputs.serviceId }}" ]; then
|
||||||
|
echo "Deploying single service: ${{ github.event.inputs.serviceId }}"
|
||||||
|
npm run deploy:service -- ${{ github.event.inputs.serviceId }}
|
||||||
|
else
|
||||||
|
echo "Deploying all services"
|
||||||
npm run deploy:all
|
npm run deploy:all
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -27,3 +27,39 @@ Use the **Deploy All** workflow in the Actions tab (`.github/workflows/deploy-al
|
|||||||
- Trigger manually with **Run workflow** to deploy every service.
|
- Trigger manually with **Run workflow** to deploy every service.
|
||||||
- Provide the optional `serviceId` input to deploy just one service using `deploy:service`.
|
- Provide the optional `serviceId` input to deploy just one service using `deploy:service`.
|
||||||
- Deployments expect `RAILWAY_TOKEN` to be available as a GitHub Actions secret and run with `NODE_ENV=production`.
|
- Deployments expect `RAILWAY_TOKEN` to be available as a GitHub Actions secret and run with `NODE_ENV=production`.
|
||||||
|
# BlackRoad OS Deployment
|
||||||
|
|
||||||
|
This repo is the *orchestrator* for all BlackRoad OS services.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
- `npm run deploy:all`
|
||||||
|
Deploys all services (core, api, operator, agents, console, web, docs) via Railway.
|
||||||
|
|
||||||
|
- `npm run deploy:service -- core`
|
||||||
|
Deploy only a single service by `id`.
|
||||||
|
|
||||||
|
- `npm run health:all`
|
||||||
|
Check health endpoints for all services using their public domains.
|
||||||
|
|
||||||
|
## Service Registry
|
||||||
|
|
||||||
|
All services are defined in `infra/services.json`.
|
||||||
|
|
||||||
|
To add or change a service:
|
||||||
|
|
||||||
|
1. Edit `infra/services.json` and update:
|
||||||
|
- `id`
|
||||||
|
- `railwayProject`
|
||||||
|
- `railwayService`
|
||||||
|
- `domain`
|
||||||
|
- `healthPath`
|
||||||
|
2. Make sure the Railway project/service names match.
|
||||||
|
3. Commit and push your changes.
|
||||||
|
|
||||||
|
## GitHub Actions
|
||||||
|
|
||||||
|
The workflow `.github/workflows/deploy-all.yml` lets you:
|
||||||
|
|
||||||
|
- Trigger **Deploy BlackRoad OS** from the Actions tab.
|
||||||
|
- Optionally pass `serviceId` to deploy just one service.
|
||||||
|
|||||||
185
package-lock.json
generated
185
package-lock.json
generated
@@ -8,13 +8,17 @@
|
|||||||
"name": "blackroad-operating-system",
|
"name": "blackroad-operating-system",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.21.0"
|
"express": "^4.21.0",
|
||||||
|
"node-fetch": "^2.6.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.12.7",
|
"@types/node": "^20.12.7",
|
||||||
"node-fetch": "^3.0.0",
|
"node-fetch": "^3.0.0",
|
||||||
"ts-node": "^10.0.0",
|
"ts-node": "^10.0.0",
|
||||||
"typescript": "^5.0.0"
|
"typescript": "^5.0.0"
|
||||||
|
"@types/node-fetch": "^2.6.11",
|
||||||
|
"ts-node": "^10.9.2",
|
||||||
|
"typescript": "^5.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cspotcode/source-map-support": {
|
"node_modules/@cspotcode/source-map-support": {
|
||||||
@@ -94,6 +98,65 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~6.21.0"
|
"undici-types": "~6.21.0"
|
||||||
|
},
|
||||||
|
"node_modules/@jridgewell/trace-mapping": {
|
||||||
|
"version": "0.3.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
|
||||||
|
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/resolve-uri": "^3.0.3",
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tsconfig/node10": {
|
||||||
|
"version": "1.0.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
|
||||||
|
"integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@tsconfig/node12": {
|
||||||
|
"version": "1.0.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
|
||||||
|
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@tsconfig/node14": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@tsconfig/node16": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@types/node": {
|
||||||
|
"version": "20.19.25",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz",
|
||||||
|
"integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~6.21.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/node-fetch": {
|
||||||
|
"version": "2.6.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz",
|
||||||
|
"integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*",
|
||||||
|
"form-data": "^4.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/accepts": {
|
"node_modules/accepts": {
|
||||||
@@ -148,6 +211,13 @@
|
|||||||
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
|
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/body-parser": {
|
"node_modules/body-parser": {
|
||||||
"version": "1.20.3",
|
"version": "1.20.3",
|
||||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
|
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
|
||||||
@@ -210,6 +280,19 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/content-disposition": {
|
"node_modules/content-disposition": {
|
||||||
"version": "0.5.4",
|
"version": "0.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
|
||||||
@@ -272,6 +355,16 @@
|
|||||||
"ms": "2.0.0"
|
"ms": "2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/depd": {
|
"node_modules/depd": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
@@ -360,6 +453,22 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/es-set-tostringtag": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"get-intrinsic": "^1.2.6",
|
||||||
|
"has-tostringtag": "^1.0.2",
|
||||||
|
"hasown": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/escape-html": {
|
"node_modules/escape-html": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||||
@@ -474,6 +583,21 @@
|
|||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12.20.0"
|
"node": ">=12.20.0"
|
||||||
|
"node_modules/form-data": {
|
||||||
|
"version": "4.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
|
||||||
|
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"es-set-tostringtag": "^2.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/forwarded": {
|
"node_modules/forwarded": {
|
||||||
@@ -564,6 +688,22 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/has-tostringtag": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"has-symbols": "^1.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hasown": {
|
"node_modules/hasown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||||
@@ -748,6 +888,24 @@
|
|||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/node-fetch"
|
"url": "https://opencollective.com/node-fetch"
|
||||||
|
"node_modules/node-fetch": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "4.x || >=6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"encoding": "^0.1.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"encoding": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/object-inspect": {
|
"node_modules/object-inspect": {
|
||||||
@@ -1017,6 +1175,12 @@
|
|||||||
"node": ">=0.6"
|
"node": ">=0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tr46": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
|
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ts-node": {
|
"node_modules/ts-node": {
|
||||||
"version": "10.9.2",
|
"version": "10.9.2",
|
||||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
||||||
@@ -1137,6 +1301,25 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/webidl-conversions": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
|
||||||
|
"license": "BSD-2-Clause"
|
||||||
|
},
|
||||||
|
"node_modules/whatwg-url": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tr46": "~0.0.3",
|
||||||
|
"webidl-conversions": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/yn": {
|
"node_modules/yn": {
|
||||||
|
|||||||
11
package.json
11
package.json
@@ -2,7 +2,6 @@
|
|||||||
"name": "blackroad-operating-system",
|
"name": "blackroad-operating-system",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
|
||||||
"main": "server.mjs",
|
"main": "server.mjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node server.mjs",
|
"start": "node server.mjs",
|
||||||
@@ -14,14 +13,22 @@
|
|||||||
"deploy:service": "ts-node --esm scripts/deployService.ts",
|
"deploy:service": "ts-node --esm scripts/deployService.ts",
|
||||||
"deploy:all": "ts-node --esm scripts/deployAll.ts",
|
"deploy:all": "ts-node --esm scripts/deployAll.ts",
|
||||||
"health:all": "ts-node --esm scripts/checkHealth.ts"
|
"health:all": "ts-node --esm scripts/checkHealth.ts"
|
||||||
|
"check:health": "ts-node tools/health-check.ts",
|
||||||
|
"deploy:service": "ts-node scripts/deployService.ts",
|
||||||
|
"deploy:all": "ts-node scripts/deployAll.ts",
|
||||||
|
"health:all": "ts-node scripts/checkHealth.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.21.0"
|
"express": "^4.21.0",
|
||||||
|
"node-fetch": "^2.6.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.12.7",
|
"@types/node": "^20.12.7",
|
||||||
"node-fetch": "^3.0.0",
|
"node-fetch": "^3.0.0",
|
||||||
"ts-node": "^10.0.0",
|
"ts-node": "^10.0.0",
|
||||||
"typescript": "^5.0.0"
|
"typescript": "^5.0.0"
|
||||||
|
"@types/node-fetch": "^2.6.11",
|
||||||
|
"ts-node": "^10.9.2",
|
||||||
|
"typescript": "^5.6.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,3 +33,44 @@ async function main(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
import * as path from "path";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { ServiceConfig } from "./types";
|
||||||
|
import fetch from "node-fetch";
|
||||||
|
|
||||||
|
function loadServices(): ServiceConfig[] {
|
||||||
|
const filePath = path.join(__dirname, "..", "infra", "services.json");
|
||||||
|
const raw = fs.readFileSync(filePath, "utf-8");
|
||||||
|
return JSON.parse(raw) as ServiceConfig[];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkService(service: ServiceConfig) {
|
||||||
|
const url = `https://${service.domain}${service.healthPath}`;
|
||||||
|
try {
|
||||||
|
const res = await fetch(url, { method: "GET" });
|
||||||
|
const statusText = res.statusText || "";
|
||||||
|
console.log(
|
||||||
|
`[OK] ${service.id.padEnd(8)} ${res.status} ${statusText} - ${url}`
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(
|
||||||
|
`[FAIL] ${service.id.padEnd(8)} - ${(err as Error).message} - ${url}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const services = loadServices();
|
||||||
|
console.log("\n🌡 Checking health of all services:\n");
|
||||||
|
|
||||||
|
for (const svc of services) {
|
||||||
|
await checkService(svc);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("\nDone.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|||||||
@@ -30,3 +30,72 @@ async function main(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
import { spawn } from "child_process";
|
||||||
|
import * as path from "path";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { ServiceConfig } from "./types";
|
||||||
|
|
||||||
|
function loadServices(): ServiceConfig[] {
|
||||||
|
const filePath = path.join(__dirname, "..", "infra", "services.json");
|
||||||
|
const raw = fs.readFileSync(filePath, "utf-8");
|
||||||
|
return JSON.parse(raw) as ServiceConfig[];
|
||||||
|
}
|
||||||
|
|
||||||
|
function runCommand(cmd: string, args: string[]): Promise<void> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const child = spawn(cmd, args, {
|
||||||
|
stdio: "inherit",
|
||||||
|
shell: process.platform === "win32"
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on("close", (code) => {
|
||||||
|
if (code === 0) {
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject(new Error(`Command failed with code ${code}`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deployAll() {
|
||||||
|
const services = loadServices();
|
||||||
|
|
||||||
|
// Fixed order so dependencies come up first
|
||||||
|
const order = ["core", "api", "operator", "agents", "console", "web", "docs"];
|
||||||
|
|
||||||
|
const ordered = order
|
||||||
|
.map((id) => services.find((s) => s.id === id))
|
||||||
|
.filter((s): s is ServiceConfig => Boolean(s));
|
||||||
|
|
||||||
|
for (const service of ordered) {
|
||||||
|
console.log(
|
||||||
|
`\n===============================\nDeploying ${service.id} (${service.name})\n===============================`
|
||||||
|
);
|
||||||
|
|
||||||
|
const args = [
|
||||||
|
"railway",
|
||||||
|
"up",
|
||||||
|
"--project",
|
||||||
|
service.railwayProject,
|
||||||
|
"--service",
|
||||||
|
service.railwayService
|
||||||
|
];
|
||||||
|
|
||||||
|
try {
|
||||||
|
await runCommand("npx", args);
|
||||||
|
console.log(`✅ Done: ${service.id}`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`❌ Failed: ${service.id}`);
|
||||||
|
console.error(String(err));
|
||||||
|
// Keep going to try the rest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("\n🏁 Deployment run finished.");
|
||||||
|
}
|
||||||
|
|
||||||
|
deployAll().catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|||||||
@@ -84,3 +84,63 @@ async function main(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
import * as path from "path";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { ServiceConfig } from "./types";
|
||||||
|
|
||||||
|
function loadServices(): ServiceConfig[] {
|
||||||
|
const filePath = path.join(__dirname, "..", "infra", "services.json");
|
||||||
|
const raw = fs.readFileSync(filePath, "utf-8");
|
||||||
|
return JSON.parse(raw) as ServiceConfig[];
|
||||||
|
}
|
||||||
|
|
||||||
|
function deployService(serviceId: string) {
|
||||||
|
const services = loadServices();
|
||||||
|
const service = services.find((s) => s.id === serviceId);
|
||||||
|
|
||||||
|
if (!service) {
|
||||||
|
console.error(`Service "${serviceId}" not found.`);
|
||||||
|
console.error(
|
||||||
|
"Valid ids: " + services.map((s) => s.id).join(", ")
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`\n🚀 Deploying service: ${service.name} (${service.id})`);
|
||||||
|
console.log(
|
||||||
|
` Railway project: ${service.railwayProject}, service: ${service.railwayService}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const cmd = "npx";
|
||||||
|
const args = [
|
||||||
|
"railway",
|
||||||
|
"up",
|
||||||
|
"--project",
|
||||||
|
service.railwayProject,
|
||||||
|
"--service",
|
||||||
|
service.railwayService
|
||||||
|
];
|
||||||
|
|
||||||
|
const child = spawn(cmd, args, {
|
||||||
|
stdio: "inherit",
|
||||||
|
shell: process.platform === "win32"
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on("close", (code) => {
|
||||||
|
if (code === 0) {
|
||||||
|
console.log(`✅ Deploy complete: ${service.id}`);
|
||||||
|
} else {
|
||||||
|
console.error(`❌ Deploy failed for ${service.id} (exit code ${code})`);
|
||||||
|
}
|
||||||
|
process.exit(code === null ? 1 : code);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const serviceId = process.argv[2];
|
||||||
|
|
||||||
|
if (!serviceId) {
|
||||||
|
console.error("Usage: npm run deploy:service -- <serviceId>");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
deployService(serviceId);
|
||||||
|
|||||||
@@ -3,14 +3,21 @@
|
|||||||
"target": "ES2021",
|
"target": "ES2021",
|
||||||
"module": "NodeNext",
|
"module": "NodeNext",
|
||||||
"moduleResolution": "NodeNext",
|
"moduleResolution": "NodeNext",
|
||||||
|
"target": "ES2019",
|
||||||
|
"module": "commonjs",
|
||||||
|
"strict": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"resolveJsonModule": true,
|
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"types": ["node"],
|
"resolveJsonModule": true,
|
||||||
"lib": ["ES2021", "DOM"]
|
"outDir": "dist",
|
||||||
|
"rootDir": "."
|
||||||
},
|
},
|
||||||
"include": ["scripts/**/*.ts", "tools/**/*.ts", "infra/**/*.json"],
|
"include": ["scripts/**/*.ts", "tools/**/*.ts", "infra/**/*.json"],
|
||||||
"ts-node": {
|
"ts-node": {
|
||||||
"esm": true
|
"esm": true
|
||||||
}
|
}
|
||||||
|
"include": [
|
||||||
|
"scripts/**/*.ts",
|
||||||
|
"infra/**/*.json"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user