Skip to content
Draft
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
156 changes: 67 additions & 89 deletions examples/gitlab-ci/push-solution.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,103 +5,81 @@ stages:
variables:
GIT_STRATEGY: clone
GIT_DEPTH: 0 # Full clone for accurate branch history
# Required: Set your Upsun project ID
# UPSUN_PROJECT_ID: your-project-id
# Required: Set your Upsun CLI token as a protected variable
# UPSUN_CLI_TOKEN: your-api-token

.setup_ssh: &setup_ssh
- echo "Setup SSH"
- mkdir -p ~/.ssh
- echo "$UPSUN_SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ssh-keyscan -H git.$UPSUN_REGION.platform.sh >> ~/.ssh/known_hosts

.access_token: &access_token
- |
export UPSUN_ACCESS_TOKEN=$(curl -u platform-api-user: \
-d "grant_type=api_token&api_token=$UPSUN_API_TOKEN" \
https://auth.upsun.com/oauth2/token | jq -r .access_token)
.upsun-cli:
image: pjcdawkins/platformsh-cli
before_script:
- curl -fsSL https://raw.githubusercontent.com/platformsh/cli/refs/heads/main/internal/config/upsun-cli.yaml > cli-config.yaml
- echo > upsun 'CLI_CONFIG_FILE=cli-config.yaml platform "$@"'
- chmod +x upsun
variables:
UPSUN_CLI_COMMAND: ./upsun

# Deploy on push to branches and new merge requests
deploy_to_upsun:
# Push to production on default branch
push-production:
extends: .upsun-cli
stage: deploy
image: alpine:latest
before_script:
- apk add --no-cache curl jq git openssh
- *setup_ssh
- *access_token
variables:
UPSUN_PARENT_ENV: $CI_DEFAULT_BRANCH
UPSUN_TARGET_BRANCH: $CI_DEFAULT_BRANCH
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
script:
- |
echo "Configure Git"
git config --global user.email "gitlab-ci@example.com"
git config --global user.name "GitLab CI"

echo "Add Upsun remote"
git remote add upsun $UPSUN_GIT_REMOTE

echo "Checkout branch and push to Upsun"
git checkout -B $CI_COMMIT_REF_NAME
git push upsun $CI_COMMIT_REF_NAME
- bash examples/gitlab-ci/scripts/push.sh
environment:
name: production
url: $PRIMARY_URL
artifacts:
reports:
dotenv: environment.env

echo "Activate environment"
echo "UPSUN_ACCESS_TOKEN: $UPSUN_ACCESS_TOKEN"
curl -s -X POST \
-H "Authorization: Bearer $UPSUN_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
"https://api.upsun.com/projects/$UPSUN_PROJECT_ID/environments/main/activate"

only:
- merge_requests
except:
- main # Adjust based on your default branch

# Deploy to production
deploy_production:
# Push to review environment for merge requests
push-review-env:
extends: .upsun-cli
stage: deploy
image: alpine:latest
before_script:
- apk add --no-cache curl jq git openssh
- *setup_ssh
when: manual
variables:
UPSUN_PARENT_ENV: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
UPSUN_TARGET_BRANCH: $CI_COMMIT_REF_SLUG
UPSUN_NO_CLONE_PARENT: "true"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- |
git config --global user.email "gitlab-ci@example.com"
git config --global user.name "GitLab CI"
git remote add upsun $UPSUN_GIT_REMOTE || git remote set-url upsun $UPSUN_GIT_REMOTE
git push upsun main --force
only:
- main # Adjust based on your default branch
- bash examples/gitlab-ci/scripts/push.sh
environment:
name: review/$CI_COMMIT_REF_SLUG
url: $PRIMARY_URL
auto_stop_in: 7 day
on_stop: delete-review-env
artifacts:
reports:
dotenv: environment.env

# Cleanup environments when branches are deleted or MRs are merged
cleanup_environment:
# Cleanup merged environments
cleanup-review-envs:
extends: .upsun-cli
stage: cleanup
image: alpine:latest
before_script:
- apk add --no-cache curl jq git openssh
- *setup_ssh
- *access_token
script:
- |
# Get the source branch name from the merge request
BRANCH_NAME="${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}"

if [ -z "$BRANCH_NAME" ]; then
echo "No branch name found, skipping cleanup"
exit 0
fi

echo "Cleaning up Upsun environment: $BRANCH_NAME"

# Delete the branch from Upsun remote
git push upsun --delete "$BRANCH_NAME" || echo "Branch already deleted from remote"

# Deactivate the environment via API
curl -s -X POST \
-H "Authorization: Bearer $UPSUN_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
"https://api.upsun.com/projects/$UPSUN_PROJECT_ID/environments/$BRANCH_NAME/deactivate" || echo "Environment deactivation failed"

# Optionally delete the environment completely
curl -s -X DELETE \
-H "Authorization: Bearer $UPSUN_ACCESS_TOKEN" \
"https://api.upsun.com/projects/$UPSUN_PROJECT_ID/environments/$BRANCH_NAME" || echo "Environment deletion failed"
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: manual
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- bash examples/gitlab-ci/scripts/cleanup.sh
allow_failure: true

# Delete specific review environment when stopped
delete-review-env:
extends: .upsun-cli
stage: cleanup
when: manual
variables:
UPSUN_TARGET_BRANCH: $CI_COMMIT_REF_SLUG
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- bash examples/gitlab-ci/scripts/delete.sh
environment:
name: review/$CI_COMMIT_REF_SLUG
action: stop
19 changes: 19 additions & 0 deletions examples/gitlab-ci/scripts/cleanup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env bash

# This script cleans up Upsun environments that have been merged with their parent.

set -e -o pipefail

# Config.
if [ -z "$UPSUN_PROJECT_ID" ]; then
echo >&2 '$UPSUN_PROJECT_ID is required'
exit 1
fi
if [ -z "$UPSUN_PARENT_ENV" ]; then
UPSUN_PARENT_ENV=${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH:-main}}
fi

CLI_COMMAND=${UPSUN_CLI_COMMAND:-upsun}

# Clean up environments if they are merged with their parent.
$CLI_COMMAND environment:delete --no-interaction --project="$UPSUN_PROJECT_ID" --merged --no-wait --exclude-type production,staging --exclude "$UPSUN_PARENT_ENV"
20 changes: 20 additions & 0 deletions examples/gitlab-ci/scripts/delete.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env bash

# This script deletes a specific Upsun environment.

set -e -o pipefail

# Config.
if [ -z "$UPSUN_PROJECT_ID" ]; then
echo >&2 '$UPSUN_PROJECT_ID is required'
exit 1
fi
BRANCH=${UPSUN_TARGET_BRANCH:-$CI_COMMIT_REF_SLUG}
if [ -z "$BRANCH" ]; then
echo >&2 'Branch name ($UPSUN_TARGET_BRANCH or $CI_COMMIT_REF_SLUG) not defined'
exit 1
fi

CLI_COMMAND=${UPSUN_CLI_COMMAND:-upsun}

$CLI_COMMAND environment:delete --no-interaction --no-wait --project="$UPSUN_PROJECT_ID" --environment="$BRANCH"
43 changes: 43 additions & 0 deletions examples/gitlab-ci/scripts/push.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash

# This script can be used from GitLab CI to push code to an Upsun environment.
# It always force-pushes and activates the environment.

set -e -o pipefail

# Config.
if [ -z "$UPSUN_PROJECT_ID" ]; then
echo >&2 '$UPSUN_PROJECT_ID is required'
exit 1
fi
BRANCH=${UPSUN_TARGET_BRANCH:-$CI_COMMIT_REF_SLUG}
if [ -z "$BRANCH" ]; then
echo >&2 'Target branch ($UPSUN_TARGET_BRANCH or $CI_COMMIT_REF_SLUG) not defined'
exit 1
fi
UPSUN_PARENT_ENV=${UPSUN_PARENT_ENV:-$CI_MERGE_REQUEST_TARGET_BRANCH_NAME}
if [ -z "$UPSUN_PARENT_ENV" ]; then
UPSUN_PARENT_ENV=${CI_DEFAULT_BRANCH:-main}
fi

CLI_COMMAND=${UPSUN_CLI_COMMAND:-upsun}

$CLI_COMMAND project:set-remote --no-interaction "$UPSUN_PROJECT_ID"

# Build and run the push command.
push_command="$CLI_COMMAND push --no-interaction --force --target=${BRANCH}"
if [ "$UPSUN_PARENT_ENV" != "$BRANCH" ]; then
push_command="$push_command --activate --parent=${UPSUN_PARENT_ENV}"
if [ "$BRANCH" != main ]; then
push_command="$push_command --resources-init=default"
fi
fi
if [ -n "$UPSUN_NO_CLONE_PARENT" ]; then
push_command="$push_command --no-clone-parent"
fi

$push_command

# Write the environment's primary URL to a dotenv file.
# This can be used by a GitLab job via the "dotenv" artifact type.
echo "PRIMARY_URL=$($CLI_COMMAND url --primary --pipe --no-interaction --environment="$BRANCH")" > environment.env