Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions .ankra/manifests/api-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
labels:
app.kubernetes.io/name: api
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: api
template:
metadata:
labels:
app.kubernetes.io/name: api
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
containers:
- name: api
image: ghcr.io/CodeStaple/musclebuilder/api:${{ ankra.image_tag }}
imagePullPolicy: IfNotPresent
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop:
- ALL
ports:
- name: http
containerPort: 8000
protocol: TCP
env:
- name: PORT
value: "8000"
livenessProbe:
httpGet:
path: /health
port: http
readinessProbe:
httpGet:
path: /health
port: http
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
15 changes: 15 additions & 0 deletions .ankra/manifests/api-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: api
labels:
app.kubernetes.io/name: api
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: api
ports:
- name: http
port: 80
targetPort: 8000
protocol: TCP
58 changes: 58 additions & 0 deletions .ankra/manifests/web-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels:
app.kubernetes.io/name: web
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: web
template:
metadata:
labels:
app.kubernetes.io/name: web
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
containers:
- name: web
image: ghcr.io/CodeStaple/musclebuilder/web:${{ ankra.image_tag }}
imagePullPolicy: IfNotPresent
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop:
- ALL
ports:
- name: http
containerPort: 3000
protocol: TCP
env:
- name: NODE_ENV
value: "production"
- name: PORT
value: "3000"
- name: HOSTNAME
value: "0.0.0.0"
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
15 changes: 15 additions & 0 deletions .ankra/manifests/web-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: web
labels:
app.kubernetes.io/name: web
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: web
ports:
- name: http
port: 80
targetPort: 3000
protocol: TCP
136 changes: 136 additions & 0 deletions .github/workflows/api-build-and-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
name: Build and Publish (api)

on:
push:
branches: [main]
paths:
- apps/api/**
- .github/workflows/api-build-and-publish.yml
- apps/api/uv.lock
- apps/api/pyproject.toml

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}/api

jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
actions: read

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Run Semgrep
run: |
pip install semgrep
semgrep scan --config "p/default" --config "p/javascript" --config "p/docker" --config "p/github-actions" --json --output semgrep-results.json || true
continue-on-error: true

- name: Upload Semgrep results
uses: actions/upload-artifact@v4
if: always() && hashFiles('semgrep-results.json') != ''
with:
name: ankra-semgrep-scan
path: semgrep-results.json
retention-days: 90

- name: Run Checkov IaC scan
uses: bridgecrewio/checkov-action@v12
with:
directory: .
output_format: json
output_file_path: checkov-results.json
soft_fail: true
framework: dockerfile,helm,github_actions
continue-on-error: true

- name: Upload Checkov results
uses: actions/upload-artifact@v4
if: always() && hashFiles('checkov-results.json') != ''
with:
name: ankra-checkov-scan
path: checkov-results.json
retention-days: 90

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}/api
tags: |
type=sha
type=ref,event=branch
type=semver,pattern={{version}}
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}

- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: apps/api
push: true
platforms: linux/amd64,linux/arm64
provenance: false
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Get short SHA
id: vars
run: echo "short_sha=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT

- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@v0.35.0
with:
image-ref: ghcr.io/${{ github.repository }}/api:sha-${{ steps.vars.outputs.short_sha }}
format: json
output: trivy-results.json
severity: CRITICAL,HIGH,MEDIUM,LOW
continue-on-error: true

- name: Upload Trivy scan results
uses: actions/upload-artifact@v4
if: always() && hashFiles('trivy-results.json') != ''
with:
name: ankra-security-scan
path: trivy-results.json
retention-days: 90

- name: Make packages public
continue-on-error: true
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OWNER: ${{ github.repository_owner }}
IMAGE_PKG: ${{ github.event.repository.name }}%2Fapi
run: |
set +e
for pkg in "$IMAGE_PKG"; do
echo "Setting $pkg to public..."
if gh api -X PATCH -H "Accept: application/vnd.github+json" "/orgs/$OWNER/packages/container/$pkg" -f visibility=public >/dev/null 2>&1; then
echo " done (org)"
continue
fi
if gh api -X PATCH -H "Accept: application/vnd.github+json" "/user/packages/container/$pkg" -f visibility=public >/dev/null 2>&1; then
echo " done (user)"
continue
fi
echo " skipped — flip visibility once in the GHCR UI: https://github.com/orgs/$OWNER/packages/container/$pkg/settings"
done
Loading
Loading