136 lines
4.0 KiB
YAML
136 lines
4.0 KiB
YAML
stages:
|
|
- test
|
|
- build
|
|
- deploy
|
|
|
|
test:
|
|
stage: test
|
|
image: laravelsail/php84-composer
|
|
|
|
variables:
|
|
APP_ENV: testing
|
|
APP_KEY: base64:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
|
DB_CONNECTION: sqlite
|
|
DB_DATABASE: ":memory:"
|
|
|
|
before_script:
|
|
- apt-get update && apt-get install -y libicu-dev
|
|
- docker-php-ext-configure intl && docker-php-ext-install intl
|
|
- composer install --no-interaction --prefer-dist
|
|
|
|
script:
|
|
- php artisan test
|
|
|
|
rules:
|
|
- when: always
|
|
|
|
docker-build-push:
|
|
stage: build
|
|
image: docker:24
|
|
services:
|
|
- docker:24-dind
|
|
|
|
variables:
|
|
DOCKER_TLS_CERTDIR: "/certs"
|
|
IMAGE_TAG: "$CI_REGISTRY_IMAGE:${CI_COMMIT_SHORT_SHA}"
|
|
IMAGE_LATEST: "$CI_REGISTRY_IMAGE:latest"
|
|
|
|
before_script:
|
|
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
|
|
|
|
script:
|
|
- docker build -t "$IMAGE_TAG" -t "$IMAGE_LATEST" .
|
|
- docker push "$IMAGE_TAG"
|
|
- docker push "$IMAGE_LATEST"
|
|
|
|
rules:
|
|
- if: '$CI_COMMIT_BRANCH == "main"'
|
|
|
|
deploy-to-portainer:
|
|
stage: deploy
|
|
image: alpine:latest
|
|
needs:
|
|
- docker-build-push
|
|
|
|
before_script:
|
|
- apk add --no-cache curl jq gettext
|
|
|
|
script:
|
|
- envsubst < docker-compose.prod.yml > docker-compose.rendered.yml
|
|
|
|
- |
|
|
set -eu
|
|
|
|
PORTAINER_BASE_URL="${PORTAINER_URL%/}"
|
|
|
|
for required_var in PORTAINER_URL PORTAINER_API_KEY PORTAINER_ENDPOINT_ID PORTAINER_STACK_NAME; do
|
|
eval "required_value=\${$required_var:-}"
|
|
if [ -z "$required_value" ]; then
|
|
echo "Missing required CI variable: ${required_var}"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
STACKS_RESPONSE=$(curl -sS -w "\n%{http_code}" \
|
|
-H "X-API-Key: $PORTAINER_API_KEY" \
|
|
"$PORTAINER_BASE_URL/api/stacks")
|
|
STACKS_HTTP_CODE=$(echo "$STACKS_RESPONSE" | tail -n1)
|
|
STACKS_JSON=$(echo "$STACKS_RESPONSE" | sed '$d')
|
|
|
|
if [ "$STACKS_HTTP_CODE" -ge 400 ]; then
|
|
echo "Failed to list stacks on Portainer (HTTP $STACKS_HTTP_CODE)"
|
|
echo "$STACKS_JSON"
|
|
exit 1
|
|
fi
|
|
|
|
echo "$STACKS_JSON" | jq -e . >/dev/null
|
|
STACK_ID=$(echo "$STACKS_JSON" | jq ".[] | select(.Name == \"$PORTAINER_STACK_NAME\") | .Id")
|
|
STACK_FILE_PATH="docker-compose.rendered.yml"
|
|
|
|
if [ -z "$STACK_ID" ]; then
|
|
JSON_PAYLOAD=$(jq -n \
|
|
--arg name "$PORTAINER_STACK_NAME" \
|
|
--rawfile content "$STACK_FILE_PATH" \
|
|
'{name: $name, stackFileContent: $content, prune: true, fromAppTemplate: false}')
|
|
|
|
CREATE_RESPONSE=$(curl -sS -w "\n%{http_code}" \
|
|
-X POST "$PORTAINER_BASE_URL/api/stacks/create/standalone/string?endpointId=$PORTAINER_ENDPOINT_ID" \
|
|
-H "X-API-Key: $PORTAINER_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
--data "$JSON_PAYLOAD")
|
|
CREATE_HTTP_CODE=$(echo "$CREATE_RESPONSE" | tail -n1)
|
|
CREATE_BODY=$(echo "$CREATE_RESPONSE" | sed '$d')
|
|
|
|
if [ "$CREATE_HTTP_CODE" -ge 400 ]; then
|
|
echo "Portainer stack creation failed (HTTP $CREATE_HTTP_CODE)"
|
|
echo "$CREATE_BODY"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Stack created successfully."
|
|
else
|
|
JSON_PAYLOAD=$(jq -n \
|
|
--arg id "$STACK_ID" \
|
|
--rawfile content "$STACK_FILE_PATH" \
|
|
'{id: ($id|tonumber), stackFileContent: $content, prune: false, pullImage: true}')
|
|
|
|
UPDATE_RESPONSE=$(curl -sS -w "\n%{http_code}" \
|
|
-X PUT "$PORTAINER_BASE_URL/api/stacks/$STACK_ID?endpointId=$PORTAINER_ENDPOINT_ID&method=string" \
|
|
-H "X-API-Key: $PORTAINER_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
--data "$JSON_PAYLOAD")
|
|
UPDATE_HTTP_CODE=$(echo "$UPDATE_RESPONSE" | tail -n1)
|
|
UPDATE_BODY=$(echo "$UPDATE_RESPONSE" | sed '$d')
|
|
|
|
if [ "$UPDATE_HTTP_CODE" -ge 400 ]; then
|
|
echo "Portainer stack update failed (HTTP $UPDATE_HTTP_CODE)"
|
|
echo "$UPDATE_BODY"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Stack updated successfully."
|
|
fi
|
|
|
|
rules:
|
|
- if: '$CI_COMMIT_BRANCH == "main"'
|