Files
stonks-oracle/.github/workflows/build.yml
T

221 lines
6.8 KiB
YAML

name: Build and Push
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_BASE: ghcr.io/${{ github.repository_owner }}/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 GHCR
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- 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 GHCR
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- 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 GHCR
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- 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
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: 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