diff --git a/.github/workflows/check-update.yml b/.github/workflows/check-update.yml index 5195636..f85b883 100644 --- a/.github/workflows/check-update.yml +++ b/.github/workflows/check-update.yml @@ -1,14 +1,18 @@ name: Check Deployed Version on: - schedule: - - cron: '0 8 * * 1' # Weekly on Monday at 8 AM UTC workflow_dispatch: + inputs: + environment: + description: 'Target environment' + type: environment + required: true jobs: check: - name: 'Check deployed version' + name: 'Check version (${{ inputs.environment }})' runs-on: ubuntu-latest + environment: ${{ inputs.environment }} steps: - name: Check current deployed version @@ -22,8 +26,9 @@ jobs: BASE_DIR="${{ vars.BASE_DIR || './sfp-server' }}" if [ -z "$SSH_HOST" ] || [ -z "$SSH_PRIVATE_KEY" ]; then - echo "SSH not configured, cannot check deployed version" + echo "SSH not configured for environment '${{ inputs.environment }}'" echo "current_tag=unknown" >> $GITHUB_OUTPUT + echo "current_fqdn=unknown" >> $GITHUB_OUTPUT exit 0 fi @@ -51,7 +56,7 @@ jobs: CONFIGURED_TAG="${{ vars.IMAGE_TAG || 'latest' }}" CONFIGURED_FQDN="${{ vars.IMAGE_FQDN }}" - echo "## SFP Server Version Status" >> $GITHUB_STEP_SUMMARY + echo "## SFP Server Version Status (${{ inputs.environment }})" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "| | Image | Tag |" >> $GITHUB_STEP_SUMMARY echo "|---|-------|-----|" >> $GITHUB_STEP_SUMMARY @@ -60,7 +65,7 @@ jobs: if [ "$CURRENT_TAG" != "$CONFIGURED_TAG" ] && [ "$CURRENT_TAG" != "unknown" ]; then echo "" >> $GITHUB_STEP_SUMMARY - echo "Deployed version differs from configured version. Run the **Update SFP Server** workflow to update." >> $GITHUB_STEP_SUMMARY + echo "Deployed version differs from configured. Run **Update SFP Server** to update." >> $GITHUB_STEP_SUMMARY elif [ "$CURRENT_TAG" = "unknown" ]; then echo "" >> $GITHUB_STEP_SUMMARY echo "Could not determine currently deployed version." >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/init.yml b/.github/workflows/init.yml index 5e60e0d..e17d737 100644 --- a/.github/workflows/init.yml +++ b/.github/workflows/init.yml @@ -3,6 +3,10 @@ name: Initialize SFP Server on: workflow_dispatch: inputs: + environment: + description: 'Target environment' + type: environment + required: true force: description: 'Force re-initialization (destroys existing data)' type: boolean @@ -17,8 +21,9 @@ on: jobs: init: - name: 'Initialize server' + name: 'Initialize server (${{ inputs.environment }})' runs-on: ubuntu-latest + environment: ${{ inputs.environment }} steps: - name: Checkout repository @@ -34,9 +39,9 @@ jobs: [ -z "${{ vars.IMAGE_FQDN }}" ] && MISSING="$MISSING IMAGE_FQDN" if [ -n "$MISSING" ]; then - echo "Missing required GitHub Variables:$MISSING" + echo "Missing required variables in environment '${{ inputs.environment }}':$MISSING" echo "" - echo "Configure these in: Settings > Secrets and variables > Actions > Variables" + echo "Configure these in: Settings > Environments > ${{ inputs.environment }} > Variables" exit 1 fi @@ -70,14 +75,14 @@ jobs: IMAGE_TAG="${{ vars.IMAGE_TAG || 'latest' }}" echo "Initializing SFP Server" - echo " Tenant: $TENANT" - echo " Domain: $DOMAIN" - echo " Host: $SSH_HOST" - echo " TLS Mode: $TLS_MODE" - echo " Workers: $WORKERS" - echo " Image: $SFP_IMAGE" + echo " Environment: ${{ inputs.environment }}" + echo " Tenant: $TENANT" + echo " Domain: $DOMAIN" + echo " Host: $SSH_HOST" + echo " TLS Mode: $TLS_MODE" + echo " Workers: $WORKERS" + echo " Image: $SFP_IMAGE" - # Build the init command INIT_CMD="sfp server init" INIT_CMD="$INIT_CMD --tenant \"$TENANT\"" INIT_CMD="$INIT_CMD --mode prod" @@ -96,8 +101,6 @@ jobs: INIT_CMD="$INIT_CMD --force" fi - # Run sfp CLI from inside the Docker image - # Copy SSH key into a temp dir with correct permissions (container may not run as root) SSH_DIR=$(mktemp -d) cp ~/.ssh/deploy_key "$SSH_DIR/deploy_key" cp ~/.ssh/known_hosts "$SSH_DIR/known_hosts" @@ -120,20 +123,13 @@ jobs: - name: Output init results if: always() run: | - TENANT="${{ vars.TENANT_NAME }}" - echo "## SFP Server Initialization" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "### Configuration" >> $GITHUB_STEP_SUMMARY echo "| Setting | Value |" >> $GITHUB_STEP_SUMMARY echo "|---------|-------|" >> $GITHUB_STEP_SUMMARY - echo "| Tenant | $TENANT |" >> $GITHUB_STEP_SUMMARY + echo "| Environment | ${{ inputs.environment }} |" >> $GITHUB_STEP_SUMMARY + echo "| Tenant | ${{ vars.TENANT_NAME }} |" >> $GITHUB_STEP_SUMMARY echo "| Domain | ${{ vars.DOMAIN }} |" >> $GITHUB_STEP_SUMMARY echo "| Host | ${{ vars.SSH_HOST }} |" >> $GITHUB_STEP_SUMMARY echo "| TLS Mode | ${{ inputs.tls_mode }} |" >> $GITHUB_STEP_SUMMARY echo "| Image | ${{ steps.setup.outputs.sfp-image }} |" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "### Next Steps" >> $GITHUB_STEP_SUMMARY - echo "1. Verify the server is accessible at \`https://${{ vars.DOMAIN }}\`" >> $GITHUB_STEP_SUMMARY - echo "2. Configure integrations (GitHub OAuth, GitHub App, Slack) via the integration API or by editing \`.env\` on the server" >> $GITHUB_STEP_SUMMARY - echo "3. Use the **Update SFP Server** workflow for future updates" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/start.yml b/.github/workflows/start.yml new file mode 100644 index 0000000..4c84215 --- /dev/null +++ b/.github/workflows/start.yml @@ -0,0 +1,72 @@ +name: Start SFP Server + +on: + workflow_dispatch: + inputs: + environment: + description: 'Target environment' + type: environment + required: true + +jobs: + start: + name: 'Start server (${{ inputs.environment }})' + runs-on: ubuntu-latest + environment: ${{ inputs.environment }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup SFP CLI and SSH + id: setup + uses: ./.github/actions/setup-sfp + with: + docker-registry: ${{ vars.DOCKER_REGISTRY }} + docker-registry-token: ${{ secrets.DOCKER_REGISTRY_TOKEN }} + image-fqdn: ${{ vars.IMAGE_FQDN }} + image-tag: ${{ vars.IMAGE_TAG || 'latest' }} + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + ssh-host: ${{ vars.SSH_HOST }} + + - name: Start server + env: + DOCKER_REGISTRY: ${{ vars.DOCKER_REGISTRY }} + DOCKER_REGISTRY_TOKEN: ${{ secrets.DOCKER_REGISTRY_TOKEN }} + SFP_IMAGE: ${{ steps.setup.outputs.sfp-image }} + run: | + TENANT="${{ vars.TENANT_NAME }}" + SSH_USER="${{ vars.SSH_USER || 'root' }}" + SSH_HOST="${{ vars.SSH_HOST }}" + BASE_DIR="${{ vars.BASE_DIR || './sfp-server' }}" + + echo "Starting SFP Server" + echo " Environment: ${{ inputs.environment }}" + echo " Tenant: $TENANT" + echo " Host: $SSH_HOST" + + START_CMD="sfp server start" + START_CMD="$START_CMD --tenant \"$TENANT\"" + START_CMD="$START_CMD --base-dir \"$BASE_DIR\"" + START_CMD="$START_CMD --secrets-provider custom" + START_CMD="$START_CMD --ssh-connection \"$SSH_USER@$SSH_HOST\"" + START_CMD="$START_CMD --identity-file /root/.ssh/deploy_key" + START_CMD="$START_CMD --no-browser" + + SSH_DIR=$(mktemp -d) + cp ~/.ssh/deploy_key "$SSH_DIR/deploy_key" + cp ~/.ssh/known_hosts "$SSH_DIR/known_hosts" + chmod 600 "$SSH_DIR/deploy_key" + chmod 644 "$SSH_DIR/known_hosts" + + docker run --rm \ + --user root \ + -v "$SSH_DIR/deploy_key":/root/.ssh/deploy_key \ + -v "$SSH_DIR/known_hosts":/root/.ssh/known_hosts \ + -e DOCKER_REGISTRY \ + -e DOCKER_REGISTRY_TOKEN \ + "$SFP_IMAGE" \ + bash -c "chmod 600 /root/.ssh/deploy_key && $START_CMD" + + rm -rf "$SSH_DIR" + echo "Server started successfully" diff --git a/.github/workflows/stop.yml b/.github/workflows/stop.yml new file mode 100644 index 0000000..05f4fcd --- /dev/null +++ b/.github/workflows/stop.yml @@ -0,0 +1,72 @@ +name: Stop SFP Server + +on: + workflow_dispatch: + inputs: + environment: + description: 'Target environment' + type: environment + required: true + force: + description: 'Force stop (do not wait for graceful shutdown)' + type: boolean + default: false + +jobs: + stop: + name: 'Stop server (${{ inputs.environment }})' + runs-on: ubuntu-latest + environment: ${{ inputs.environment }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup SFP CLI and SSH + id: setup + uses: ./.github/actions/setup-sfp + with: + docker-registry: ${{ vars.DOCKER_REGISTRY }} + docker-registry-token: ${{ secrets.DOCKER_REGISTRY_TOKEN }} + image-fqdn: ${{ vars.IMAGE_FQDN }} + image-tag: ${{ vars.IMAGE_TAG || 'latest' }} + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + ssh-host: ${{ vars.SSH_HOST }} + + - name: Stop server + env: + SFP_IMAGE: ${{ steps.setup.outputs.sfp-image }} + run: | + TENANT="${{ vars.TENANT_NAME }}" + SSH_USER="${{ vars.SSH_USER || 'root' }}" + SSH_HOST="${{ vars.SSH_HOST }}" + + echo "Stopping SFP Server" + echo " Environment: ${{ inputs.environment }}" + echo " Tenant: $TENANT" + echo " Host: $SSH_HOST" + + STOP_CMD="sfp server stop" + STOP_CMD="$STOP_CMD --tenant \"$TENANT\"" + STOP_CMD="$STOP_CMD --ssh-connection \"$SSH_USER@$SSH_HOST\"" + STOP_CMD="$STOP_CMD --identity-file /root/.ssh/deploy_key" + + if [ "${{ inputs.force }}" = "true" ]; then + STOP_CMD="$STOP_CMD --force" + fi + + SSH_DIR=$(mktemp -d) + cp ~/.ssh/deploy_key "$SSH_DIR/deploy_key" + cp ~/.ssh/known_hosts "$SSH_DIR/known_hosts" + chmod 600 "$SSH_DIR/deploy_key" + chmod 644 "$SSH_DIR/known_hosts" + + docker run --rm \ + --user root \ + -v "$SSH_DIR/deploy_key":/root/.ssh/deploy_key \ + -v "$SSH_DIR/known_hosts":/root/.ssh/known_hosts \ + "$SFP_IMAGE" \ + bash -c "chmod 600 /root/.ssh/deploy_key && $STOP_CMD" + + rm -rf "$SSH_DIR" + echo "Server stopped successfully" diff --git a/.github/workflows/update.yml b/.github/workflows/update.yml index 9e0600f..dccb0d5 100644 --- a/.github/workflows/update.yml +++ b/.github/workflows/update.yml @@ -3,6 +3,10 @@ name: Update SFP Server on: workflow_dispatch: inputs: + environment: + description: 'Target environment' + type: environment + required: true docker_tag: description: 'Docker image tag to deploy (leave empty to use IMAGE_TAG variable or "latest")' required: false @@ -22,28 +26,14 @@ on: jobs: update: - name: 'Update server' + name: 'Update server (${{ inputs.environment }})' runs-on: ubuntu-latest + environment: ${{ inputs.environment }} steps: - name: Checkout repository uses: actions/checkout@v4 - - name: Validate required variables - run: | - MISSING="" - [ -z "${{ vars.SSH_HOST }}" ] && MISSING="$MISSING SSH_HOST" - [ -z "${{ vars.TENANT_NAME }}" ] && MISSING="$MISSING TENANT_NAME" - [ -z "${{ vars.DOCKER_REGISTRY }}" ] && MISSING="$MISSING DOCKER_REGISTRY" - [ -z "${{ vars.IMAGE_FQDN }}" ] && MISSING="$MISSING IMAGE_FQDN" - - if [ -n "$MISSING" ]; then - echo "Missing required GitHub Variables:$MISSING" - echo "" - echo "Configure these in: Settings > Secrets and variables > Actions > Variables" - exit 1 - fi - - name: Resolve image tag id: resolve run: | @@ -77,12 +67,12 @@ jobs: TAG="${{ steps.resolve.outputs.tag }}" echo "Updating SFP Server" - echo " Tenant: $TENANT" - echo " Host: $SSH_HOST" - echo " Tag: $TAG" - echo " Image: $SFP_IMAGE" + echo " Environment: ${{ inputs.environment }}" + echo " Tenant: $TENANT" + echo " Host: $SSH_HOST" + echo " Tag: $TAG" + echo " Image: $SFP_IMAGE" - # Build the update command UPDATE_CMD="sfp server update" UPDATE_CMD="$UPDATE_CMD --tenant \"$TENANT\"" UPDATE_CMD="$UPDATE_CMD --base-dir \"$BASE_DIR\"" @@ -101,8 +91,6 @@ jobs: UPDATE_CMD="$UPDATE_CMD --skip-backup" fi - # Run sfp CLI from inside the Docker image - # Copy SSH key into a temp dir with correct permissions SSH_DIR=$(mktemp -d) cp ~/.ssh/deploy_key "$SSH_DIR/deploy_key" cp ~/.ssh/known_hosts "$SSH_DIR/known_hosts" @@ -123,12 +111,11 @@ jobs: - name: Output update results if: always() run: | - TAG="${{ steps.resolve.outputs.tag }}" - echo "## SFP Server Update" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "| Setting | Value |" >> $GITHUB_STEP_SUMMARY echo "|---------|-------|" >> $GITHUB_STEP_SUMMARY + echo "| Environment | ${{ inputs.environment }} |" >> $GITHUB_STEP_SUMMARY echo "| Tenant | ${{ vars.TENANT_NAME }} |" >> $GITHUB_STEP_SUMMARY echo "| Host | ${{ vars.SSH_HOST }} |" >> $GITHUB_STEP_SUMMARY echo "| Image | ${{ steps.setup.outputs.sfp-image }} |" >> $GITHUB_STEP_SUMMARY