Presets / Harness CI/CD pipeline
preset Communauté

Harness CI/CD pipeline

other  · 

Pipeline CI/CD pour harness

harness CI/CD pipeline
kind: pipeline
spec:
  stages:
    - name: build
      type: ci
      spec:
        steps:
          - name: push_image
            type: run
            spec:
              container: gcr.io/kaniko-project/executor:debug
              envs:
                REGISTRY_PASSWORD: ${{ secrets.get("my_token_name") }}
                REGISTRY_HOST: "HOST"
                REGISTRY_USER: "USER"
                IMAGE_NAME: "my/image/name"
              script: |-
                mkdir -p /kaniko/.docker
                echo "{\"auths\":{\"$REGISTRY_HOST\":{\"username\":\"$REGISTRY_USER\",\"password\":\"$REGISTRY_PASSWORD\"}}}" \
                  > /kaniko/.docker/config.json
                /kaniko/executor \
                  --context=dir://. \
                  --dockerfile=Dockerfile \
                  --destination=$REGISTRY_HOST/$IMAGE_NAME:latest \
                  --skip-tls-verify

          - name: redeploy
            type: run
            spec:
              container: alpine:latest
              envs:
                PORTAINER_TOKEN: ${{ secrets.get("portainer_token") }}
                PORTAINER_HOST: "https://IP"
                STACK_NAME: "stack_name"
                SECRET_KEY: ${{ secrets.get("SECRET_NAME") }}
              script: |-
                set -e
                apk add --no-cache curl jq

                # -- lookup stack --
                STACKS_RAW=$(curl -sk \
                  -H "X-API-Key: $PORTAINER_TOKEN" \
                  "$PORTAINER_HOST/api/stacks")

                if ! echo "$STACKS_RAW" | jq -e 'type == "array"' > /dev/null 2>&1; then
                  echo "ERREUR : Portainer /api/stacks n'a pas retourné un tableau"
                  echo "Réponse brute : $STACKS_RAW"
                  exit 1
                fi

                STACK=$(echo "$STACKS_RAW" | jq ".[] | select(.Name == \"$STACK_NAME\")")

                if [ -z "$STACK" ]; then
                  echo "ERREUR : stack '$STACK_NAME' introuvable dans Portainer"
                  exit 1
                fi

                STACK_ID=$(echo "$STACK" | jq -r '.Id')
                ENDPOINT_ID=$(echo "$STACK" | jq -r '.EndpointId')
                echo "Stack: $STACK_NAME → Id=$STACK_ID EndpointId=$ENDPOINT_ID"

                # -- récupère le compose actuel --
                curl -sk \
                  -H "X-API-Key: $PORTAINER_TOKEN" \
                  "$PORTAINER_HOST/api/stacks/$STACK_ID/file" \
                  | jq -r '.StackFileContent' > /tmp/compose.yml

                if [ ! -s /tmp/compose.yml ]; then
                  echo "ERREUR : compose file vide ou non récupéré"
                  exit 1
                fi

                # -- valide la SECRET_KEY --
                if [ -z "$SECRET_KEY" ]; then
                  echo "ERREUR : SECRET_KEY est vide — créer le secret 'secret_key' dans Harness"
                  exit 1
                fi

                # -- déclenche le redéploiement --
                PAYLOAD=$(jq -n \
                  --rawfile compose /tmp/compose.yml \
                  --arg sk "$SECRET_KEY" \
                  '{StackFileContent: $compose, Env: [{name: "SECRET_KEY", value: $sk}], Prune: false, PullImage: true}')

                RESPONSE=$(curl -sk -X PUT \
                  -H "X-API-Key: $PORTAINER_TOKEN" \
                  -H "Content-Type: application/json" \
                  --data-binary "$PAYLOAD" \
                  "$PORTAINER_HOST/api/stacks/$STACK_ID?endpointId=$ENDPOINT_ID")

                echo "Réponse Portainer : $RESPONSE"

                if echo "$RESPONSE" | jq -e '.message' > /dev/null 2>&1; then
                  echo "ERREUR Portainer : $(echo $RESPONSE | jq -r '.message')"
                  exit 1
                fi

                echo "Redéploiement OK"