911e42996b
- GitHub Actions: login with secrets.HARBOR_USERNAME + HARBOR_PASSWORD - deploy.sh step 7: creates stonks-oracle project, robot account, tag retention - All API calls are idempotent (safe to re-run)
230 lines
7.2 KiB
YAML
230 lines
7.2 KiB
YAML
name: Build and Push
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
env:
|
|
REGISTRY: registry.celestium.life
|
|
IMAGE_BASE: registry.celestium.life/stonks-oracle
|
|
|
|
jobs:
|
|
lint-and-test:
|
|
runs-on: self-hosted-gremlin
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
|
|
- uses: actions/setup-python@v6
|
|
with:
|
|
python-version: "3.12"
|
|
cache: pip
|
|
|
|
- name: Install dependencies
|
|
run: pip install -r requirements.txt
|
|
|
|
- name: Lint
|
|
run: |
|
|
python -m ruff --version
|
|
python -m ruff check --diff services/
|
|
|
|
- name: Test
|
|
run: python -m pytest tests/ -x --tb=short -q || true
|
|
|
|
- uses: actions/setup-node@v5
|
|
with:
|
|
node-version: "24"
|
|
cache: npm
|
|
cache-dependency-path: frontend/package-lock.json
|
|
|
|
- name: Install frontend deps
|
|
run: npm ci
|
|
working-directory: frontend
|
|
|
|
- name: Frontend tests
|
|
run: npm test
|
|
working-directory: frontend
|
|
|
|
build-services:
|
|
needs: lint-and-test
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
runs-on: self-hosted-gremlin
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
strategy:
|
|
matrix:
|
|
service:
|
|
- name: scheduler
|
|
cmd: "python -m services.scheduler.app"
|
|
- name: symbol-registry
|
|
cmd: "uvicorn services.symbol_registry.app:app --host 0.0.0.0 --port 8000"
|
|
- name: ingestion
|
|
cmd: "python -m services.ingestion.worker"
|
|
- name: parser
|
|
cmd: "python -m services.parser.worker"
|
|
- name: extractor
|
|
cmd: "python -m services.extractor.worker"
|
|
- name: aggregation
|
|
cmd: "python -m services.aggregation.worker"
|
|
- name: recommendation
|
|
cmd: "python -m services.recommendation.worker"
|
|
- name: risk
|
|
cmd: "uvicorn services.risk.app:app --host 0.0.0.0 --port 8000"
|
|
- name: broker-adapter
|
|
cmd: "python -m services.adapters.broker_adapter"
|
|
- name: lake-publisher
|
|
cmd: "python -m services.lake_publisher.worker"
|
|
- name: query-api
|
|
cmd: "uvicorn services.api.app:app --host 0.0.0.0 --port 8000"
|
|
- name: trading-engine
|
|
cmd: "uvicorn services.trading.app:app --host 0.0.0.0 --port 8000"
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
|
|
- name: Log in to Harbor
|
|
uses: docker/login-action@v4
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ secrets.HARBOR_USERNAME }}
|
|
password: ${{ secrets.HARBOR_PASSWORD }}
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v4
|
|
|
|
- name: Build and push ${{ matrix.service.name }}
|
|
uses: docker/build-push-action@v7
|
|
with:
|
|
context: .
|
|
file: docker/Dockerfile
|
|
push: true
|
|
tags: |
|
|
${{ env.IMAGE_BASE }}/${{ matrix.service.name }}:${{ github.sha }}
|
|
${{ env.IMAGE_BASE }}/${{ matrix.service.name }}:latest
|
|
build-args: |
|
|
SERVICE_CMD=${{ matrix.service.cmd }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
|
|
build-dashboard:
|
|
needs: lint-and-test
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
runs-on: self-hosted-gremlin
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
|
|
- name: Log in to Harbor
|
|
uses: docker/login-action@v4
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ secrets.HARBOR_USERNAME }}
|
|
password: ${{ secrets.HARBOR_PASSWORD }}
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v4
|
|
|
|
- name: Build and push dashboard
|
|
uses: docker/build-push-action@v7
|
|
with:
|
|
context: frontend
|
|
file: frontend/Dockerfile
|
|
push: true
|
|
tags: |
|
|
${{ env.IMAGE_BASE }}/dashboard:${{ github.sha }}
|
|
${{ env.IMAGE_BASE }}/dashboard:latest
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
|
|
build-superset:
|
|
needs: lint-and-test
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
runs-on: self-hosted-gremlin
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
|
|
- name: Log in to Harbor
|
|
uses: docker/login-action@v4
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ secrets.HARBOR_USERNAME }}
|
|
password: ${{ secrets.HARBOR_PASSWORD }}
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v4
|
|
|
|
- name: Build and push superset
|
|
uses: docker/build-push-action@v7
|
|
with:
|
|
context: docker
|
|
file: docker/Dockerfile.superset
|
|
push: true
|
|
tags: |
|
|
${{ env.IMAGE_BASE }}/superset:${{ github.sha }}
|
|
${{ env.IMAGE_BASE }}/superset:latest
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
|
|
integration-test:
|
|
needs: [build-services, build-dashboard]
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
runs-on: self-hosted-gremlin
|
|
permissions:
|
|
contents: read
|
|
packages: read
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
|
|
- name: Install kubectl
|
|
run: |
|
|
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
|
|
chmod +x kubectl
|
|
sudo mv kubectl /usr/local/bin/kubectl
|
|
kubectl version --client
|
|
|
|
- name: Install Helm
|
|
run: |
|
|
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | sudo bash
|
|
helm version
|
|
|
|
- name: Install pipeline dependencies
|
|
run: |
|
|
sudo apt-get update -qq && sudo apt-get install -y -qq gettext-base python3 python3-pip > /dev/null 2>&1
|
|
envsubst --version
|
|
pip3 install httpx asyncpg pytest pytest-asyncio --quiet 2>/dev/null || true
|
|
|
|
- name: Configure kubectl
|
|
run: |
|
|
# Use in-cluster service account if available, otherwise skip
|
|
if [ -f /var/run/secrets/kubernetes.io/serviceaccount/token ]; then
|
|
kubectl config set-cluster in-cluster \
|
|
--server=https://kubernetes.default.svc \
|
|
--certificate-authority=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
|
kubectl config set-credentials runner \
|
|
--token="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
|
|
kubectl config set-context runner --cluster=in-cluster --user=runner
|
|
kubectl config use-context runner
|
|
echo "Using in-cluster service account"
|
|
else
|
|
echo "No in-cluster credentials found — kubectl must be pre-configured"
|
|
fi
|
|
kubectl cluster-info || echo "WARNING: kubectl cannot reach cluster API"
|
|
|
|
- name: Run integration tests
|
|
run: |
|
|
bash infra/inttest/run_pipeline.sh \
|
|
--image-tag ${{ github.sha }} \
|
|
--results-file inttest-results.json
|
|
- name: Upload results
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: inttest-results
|
|
path: inttest-results.json
|