diff --git a/.github/workflows/test-ensure-multidev.yml b/.github/workflows/test-ensure-multidev.yml new file mode 100644 index 0000000..727aa64 --- /dev/null +++ b/.github/workflows/test-ensure-multidev.yml @@ -0,0 +1,48 @@ +name: "Tests: Version" + +on: + workflow_call: + inputs: + php-version: + required: false + type: number + default: 8.2 + terminus-version: + required: false + type: string + default: 3.6.1 + pantheon-machine-token: + required: true + type: string + pantheon-sitename: + required: true + type: string + +jobs: + test-ensure-multidev: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ inputs.php-version }} + + - name: Install dependencies + run: composer install --no-scripts --no-progress --prefer-dist + + - name: Set up Terminus + run: | + curl -O https://raw.githubusercontent.com/pantheon-systems/terminus-installer/master/builds/installer.phar + php installer.phar install + terminus --version + env: + TERMINUS_VERSION: ${{ inputs.terminus-version }} + + - name: Run ensure-multidev action + uses: ./.github/actions/ensure-multidev + with: + pantheon-machine-token: ${{ inputs.pantheon-machine-token }} + pantheon-sitename: ${{ inputs.pantheon-sitename }} diff --git a/.github/workflows/test-terminus-version.yml b/.github/workflows/test-terminus-version.yml index a0c1f0d..766997a 100644 --- a/.github/workflows/test-terminus-version.yml +++ b/.github/workflows/test-terminus-version.yml @@ -6,11 +6,11 @@ on: php-version: required: false type: number - default: 8 + default: 8.2 terminus-version: required: false type: string - default: 3.0.6 + default: 3.6.1 jobs: test_version: diff --git a/.github/workflows/test-terminus.yml b/.github/workflows/test-terminus.yml index 8c6fda3..5a0de46 100644 --- a/.github/workflows/test-terminus.yml +++ b/.github/workflows/test-terminus.yml @@ -6,6 +6,19 @@ on: - main jobs: + check-terminus: + runs-on: ubuntu-latest + outputs: + terminus_version: ${{ steps.get-version.outputs.version }} + + steps: + - name: Get Latest Terminus Version + id: get-version + run: | + TERMINUS_VERSION=$(curl -s https://api.github.com/repos/pantheon-systems/terminus/releases/latest | jq -r .tag_name) + echo "version=${TERMINUS_VERSION}" >> $GITHUB_OUTPUT + echo "Latest Terminus version: ${TERMINUS_VERSION}" + test_terminus: runs-on: ubuntu-latest name: Terminus Setup @@ -32,15 +45,13 @@ jobs: - name: Setup Terminus uses: ./ - test_terminus_version: - name: Terminus Version - uses: ./.github/workflows/test-terminus-version.yml - - test_terminus_version_304: + test_terminus_version_latest: name: Terminus Version uses: ./.github/workflows/test-terminus-version.yml + needs: + check-terminus with: - terminus-version: 3.0.4 + terminus-version: ${{ needs.check-terminus.outputs.terminus_version }} test_terminus_version_266: name: Terminus Version @@ -48,3 +59,13 @@ jobs: with: php-version: 7.4 terminus-version: 2.6.6 + + test_terminus_ensure_multidev: + name: Terminus Ensure Multidev + uses: ./.github/workflows/test-ensure-multidev.yml + needs: + test_terminus_version + with: + php-version: 8.2 + terminus-version: ${{ steps.check-terminus.outputs.terminus_version }} + pantheon-machine-token: ${{ secrets.pantheon-machine-token }} \ No newline at end of file diff --git a/ensure-multidev/README.md b/ensure-multidev/README.md new file mode 100644 index 0000000..8213528 --- /dev/null +++ b/ensure-multidev/README.md @@ -0,0 +1,57 @@ +# Terminus Multidev Manager Action + +This GitHub Action helps manage Pantheon multidev environments by ensuring there are enough available slots for new environments. If needed, it will automatically remove the oldest environments to make room for new ones. + +## Inputs + +### `pantheon-site-name` +**Required** The name of your Pantheon site. + +### `multidev-count` +**Required** The number of multidev environments you need to ensure are available. Default: "1" + +### `pantheon-machine-token` +**Required** Your Pantheon Terminus machine token for authentication. + +### `protected-environments` +**Optional** Comma-separated list of environment names that should never be deleted. Default: "dev,test,live" + +## Example Usage + +```yaml + +steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "8.2" + + - name: Install Terminus + uses: pantheon-systems/terminus-github-actions@v1 + with: + pantheon-machine-token: ${{ secrets.PANTHEON_MACHINE_TOKEN }} + + - uses: pantheon-systems/terminus-github-actions/ensure-multidev@v1 + with: + pantheon-site-name: 'my-pantheon-site' + multidev-count: '2' + pantheon-machine-token: ${{ secrets.PANTHEON_MACHINE_TOKEN }} + protected-environments: 'dev,test,live,some-multidev-environment-thats-important' + +``` + +## How it works + +1. The action authenticates with Terminus using the provided token +2. Checks the current number of multidev environments +3. If there isn't enough room for the requested number of new environments: +- Lists all existing multidev environments +- Filters out protected environments +- Sorts by creation date +- Deletes the oldest environments until there's enough room + +## Important Notes + +- The action will never delete the `dev`, `test`, or `live` environments +- Protected environments specified in `protected-environments` will never be deleted +- The action will fail if it cannot free up enough environments after deleting all eligible ones \ No newline at end of file diff --git a/ensure-multidev/action.yml b/ensure-multidev/action.yml new file mode 100644 index 0000000..6c6e741 --- /dev/null +++ b/ensure-multidev/action.yml @@ -0,0 +1,31 @@ +name: 'Terminus Ensure Multidev' +description: 'Ensures availability of multidev environments by cleaning up old ones if necessary' +inputs: + pantheon-site-name: + description: 'The Pantheon site name' + required: true + pantheon-machine-token: + description: 'Terminus machine token for authentication' + required: true + multidev-count: + description: 'Number of multidev environments needed' + required: true + default: '1' + protected-environments: + description: 'Comma-separated list of environments to never delete' + required: false + default: 'dev,test,live' + +runs: + using: 'composite' + steps: + - name: Set up Terminus token + shell: bash + run: | + mkdir -p ~/.terminus + echo "machine-token: ${{ inputs.pantheon-machine-token }}" > ~/.terminus/cache/tokens.yml + + - name: Run Multidev management script + shell: bash + run: ${{ github.action_path }}/ensure-multidev.sh "${{ inputs.pantheon-site-name }}" "${{ inputs.multidev-count }}" "${{ inputs.protected-environments }}" + diff --git a/ensure-multidev/ensure-multidev.sh b/ensure-multidev/ensure-multidev.sh new file mode 100644 index 0000000..b064042 --- /dev/null +++ b/ensure-multidev/ensure-multidev.sh @@ -0,0 +1,66 @@ +#!/bin/bash +set -euo pipefail +IFS=$'\n\t' + +usage_exit() { + echo "usage: $0 site_name multidev_count [protected_environments]" + exit 1 +} + +SITE_NAME="${1:-}" +if [[ -z "${SITE_NAME}" ]]; then + echo "Missing Site Name" + usage_exit +fi + +NUMBER_OF_CDES_REQUIRED="${2:-}" +if [[ "${NUMBER_OF_CDES_REQUIRED}" == "" ]]; then + echo "No multidev count provided, assuming 1." + NUMBER_OF_CDES_REQUIRED=1 +elif ! [[ $NUMBER_OF_CDES_REQUIRED =~ ^[0-9]+$ ]]; then + echo "The variable is not an integer." + usage_exit +fi + +PROTECTED_ENVIRONMENTS="${3:-drupal10}" +# Convert comma-separated list to regex pattern +PROTECTED_PATTERN=$(echo "$PROTECTED_ENVIRONMENTS" | sed 's/,/\\|/g') + +MAX_CDE_COUNT="$(terminus site:info "${SITE_NAME}" --field='Max Multidevs')" +echo "Max Multidev Count: ${MAX_CDE_COUNT}" + +DOMAINS="$(terminus env:list "${SITE_NAME}" --format=string --fields=ID,Created)" + +# Filter out dev, test, live as they don't count against the Max Multidev count. +CDE_DOMAINS=$(echo "$DOMAINS" | grep -vE '\b(dev|test|live)\b') + +# Count current environments +CDE_COUNT="$(echo "$CDE_DOMAINS" | wc -l)" +# remove whitespace to make the arithmetic work +CDE_COUNT="${CDE_COUNT//[[:blank:]]/}" + +echo "There are currently ${CDE_COUNT}/${MAX_CDE_COUNT} multidevs. I need ${NUMBER_OF_CDES_REQUIRED}." + +POTENTIAL_CDE_COUNT=$((CDE_COUNT + NUMBER_OF_CDES_REQUIRED)) +if [[ "${POTENTIAL_CDE_COUNT}" -le "${MAX_CDE_COUNT}" ]]; then + echo "There are enough multidevs." + exit 0 +fi + +NUMBER_OF_CDES_TO_DELETE=$((POTENTIAL_CDE_COUNT - MAX_CDE_COUNT)) +echo "There are not enough multidevs, deleting the oldest ${NUMBER_OF_CDES_TO_DELETE} environment(s)." + +# Filter out protected environments and sort by timestamps +SORTED_DOMAINS=$(echo "$CDE_DOMAINS" | grep -vE "\b(${PROTECTED_PATTERN})\b" | sort -n -k2) + +# Delete as many multidevs as we need to make room for testing. +for (( i = 1; i<=NUMBER_OF_CDES_TO_DELETE; i++ )); do + ENV_TO_REMOVE="$(echo "$SORTED_DOMAINS" | head -n "$i" | tail -n 1 | cut -f1)" + if [[ -n "${ENV_TO_REMOVE}" ]]; then + echo "Removing '${ENV_TO_REMOVE}'." + terminus multidev:delete --delete-branch "${SITE_NAME}.${ENV_TO_REMOVE}" --yes + else + echo "Warning: No more eligible environments to remove" + exit 1 + fi +done