diff --git a/Dockerfile b/Dockerfile index dbdf951..89c2e01 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,12 @@ FROM python:3.12-slim +ENV HOME=/app \ + PYTHONUNBUFFERED=1 \ + STREAMLIT_SERVER_PORT=8501 \ + STREAMLIT_SERVER_ADDRESS=0.0.0.0 \ + STREAMLIT_SERVER_HEADLESS=true \ + STREAMLIT_BROWSER_GATHER_USAGE_STATS=false + WORKDIR /app # Systeem-dependency voor de HEALTHCHECK hieronder @@ -11,8 +18,9 @@ RUN pip install --no-cache-dir -r requirements.txt COPY . . +RUN chgrp -R 0 /app && chmod -R g=u /app + +USER 1001 EXPOSE 8501 - HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health || exit 1 - -ENTRYPOINT ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"] +CMD ["streamlit", "run", "app.py"] diff --git a/Jenkinsfile b/Jenkinsfile index cc4c8cd..1768340 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,11 +1,92 @@ pipeline { - agent any + agent { label 'ssh-agent' } + + environment { + REGISTRY = 'gitea.zb-kw.duckdns.org' + IMAGE = "${REGISTRY}/willemjan/glucose-dashboard" + OC_SERVER = 'https://api.rm1.0a51.p1.openshiftapps.com:6443' + OC_PROJECT = 'willemjan-dev' + } + + options { + buildDiscarder(logRotator(numToKeepStr: '20')) + timeout(time: 20, unit: 'MINUTES') + } stages { - stage('Do nothing') { + stage('Checkout') { steps { - sh '/bin/true' + checkout scm + script { + env.TAG = sh(script: 'git rev-parse --short HEAD', + returnStdout: true).trim() + } + } + } + + stage('Test') { + steps { + sh ''' + python -m venv .venv + . .venv/bin/activate + pip install -q -r requirements.txt -r requirements-dev.txt + pytest -q --junitxml=report.xml + ''' + } + post { + always { junit 'report.xml' } + } + } + + stage('Build & push image') { + steps { + withCredentials([usernamePassword( + credentialsId: 'gitea-registry', + usernameVariable: 'REG_USER', + passwordVariable: 'REG_PASS')]) { + sh ''' + echo "$REG_PASS" | docker login $REGISTRY -u "$REG_USER" --password-stdin + docker build -t $IMAGE:$TAG -t $IMAGE:latest . + docker push $IMAGE:$TAG + docker push $IMAGE:latest + ''' + } + } + } + + stage('Scan') { + steps { + sh 'trivy image --exit-code 0 --severity HIGH,CRITICAL $IMAGE:$TAG' + } + } + + stage('Deploy to OpenShift') { + steps { + withCredentials([string( + credentialsId: 'openshift-token', + variable: 'OC_TOKEN')]) { + sh ''' + oc login --token="$OC_TOKEN" --server="$OC_SERVER" + oc project $OC_PROJECT + + oc apply -f openshift/service.yaml + oc apply -f openshift/route.yaml + oc apply -f openshift/deployment.yaml + + oc set image deployment/glucose-dashboard \ + glucose-dashboard=$IMAGE:$TAG + + oc rollout status deployment/glucose-dashboard --timeout=5m + ''' + } } } } + + post { + always { sh 'oc logout || true' } + success { + sh 'echo "Deployed: $(oc get route glucose-dashboard -o jsonpath={.spec.host})" || true' + } + } } \ No newline at end of file diff --git a/openshift/deployment.yaml b/openshift/deployment.yaml new file mode 100644 index 0000000..1b7abba --- /dev/null +++ b/openshift/deployment.yaml @@ -0,0 +1,32 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: glucose-dashboard + labels: + app: glucose-dashboard +spec: + replicas: 1 + selector: + matchLabels: + app: glucose-dashboard + template: + metadata: + labels: + app: glucose-dashboard + spec: + imagePullSecrets: + - name: gitea-registry + containers: + - name: glucose-dashboard + image: PLACEHOLDER + ports: + - containerPort: 8501 + resources: + requests: { cpu: 100m, memory: 256Mi } + limits: { cpu: 500m, memory: 512Mi } + readinessProbe: + httpGet: { path: /_stcore/health, port: 8501 } + initialDelaySeconds: 10 + livenessProbe: + httpGet: { path: /_stcore/health, port: 8501 } + initialDelaySeconds: 30 \ No newline at end of file diff --git a/openshift/route.yaml b/openshift/route.yaml new file mode 100644 index 0000000..8dc2cd9 --- /dev/null +++ b/openshift/route.yaml @@ -0,0 +1,13 @@ +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: glucose-dashboard +spec: + to: + kind: Service + name: glucose-dashboard + port: + targetPort: 8501 + tls: + termination: edge + insecureEdgeTerminationPolicy: Redirect \ No newline at end of file diff --git a/openshift/service.yaml b/openshift/service.yaml new file mode 100644 index 0000000..ac5699a --- /dev/null +++ b/openshift/service.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: glucose-dashboard +spec: + selector: + app: glucose-dashboard + ports: + - port: 8501 + targetPort: 8501 \ No newline at end of file