diff --git a/.github/workflows/GitHub-Workflow-Validation-Checks_DOCKER.yml b/.github/workflows/GitHub-Workflow-Validation-Checks_DOCKER.yml new file mode 100644 index 0000000..1ae5b07 --- /dev/null +++ b/.github/workflows/GitHub-Workflow-Validation-Checks_DOCKER.yml @@ -0,0 +1,152 @@ +# =========================== +# Pipeline Name: GitHub-Workflow-Validation-Checks_DOCKER.yml +# Version: 1.0.2 +# Author: Chris Hawkins (Redgate Software Ltd) +# Last Updated: 2025-11-04 +# Description: GitHub Pipeline Validation Workflow (Use Case - To validate all future changes to the Autopilot repository in an automated way) +# =========================== + +name: GitHub - FastTrack Pipeline Validation Workflow (Docker) +on: + workflow_dispatch: # Allows manual triggering + repository_dispatch: + types: [trigger-validation] # Listens for dispatch events, which can trigger this workflow automatically on regular schedules + pull_request: + branches: + - release # Triggers on PRs to release + - 'feature/*' # Triggers on PRs to any feature branch + # schedule: + # - cron: "0 2 * * *" # Runs at 3 AM UTC + +### + ### Navigate to Settings > Secrets & Variables > Actions + # IMAGE_NAME: Enter the name of the RGClone Image to be used + # CONTAINER_NAME: Enter the name of the container to be created + # CONTAINER_PORT: Enter the local port number to be used by the proxy command +### End of Environment Variables ### + +jobs: + setup-validation-environment: + name: Spin Up SQL Server Container + runs-on: "self-hosted" + env: + IMAGE_NAME: "${{ vars.IMAGE_NAME }}" + SA_PASSWORD: "DatabaseDevOps!" + HOST_PORT: "${{ vars.CONTAINER_PORT }}" + BASE_CONTAINER_NAME: "${{ vars.RGCLONE_CONTAINER_NAME }}" + CONTAINER_NAME: "${{ vars.CONTAINER_NAME }}-${{ github.run_number }}" + DB_INIT_SCRIPT: "${{ github.workspace }}/Scripts/CreateAutopilotDatabases.sql" + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Verify Docker availability + run: docker version || echo "Docker not found, please install before running this workflow." + + - name: Check if port is in use and free it + run: | + echo "Checking if port $HOST_PORT is in use..." + if lsof -i :$HOST_PORT &>/dev/null; then + echo "Port $HOST_PORT is in use. Checking for container..." + EXISTING_CONTAINER=$(docker ps --filter "publish=$HOST_PORT" --format "{{.Names}}") + if [ -n "$EXISTING_CONTAINER" ]; then + echo "Stopping and removing container using port $HOST_PORT ($EXISTING_CONTAINER)..." + docker stop "$EXISTING_CONTAINER" || true + docker rm "$EXISTING_CONTAINER" || true + else + echo "No Docker container found using port $HOST_PORT, killing any process..." + PID=$(lsof -ti :$HOST_PORT) + kill -9 $PID || true + fi + else + echo "Port $HOST_PORT is free." + fi + + - name: Pull Docker Image (if not local) + run: | + if [[ "$IMAGE_NAME" == local/* ]]; then + echo "Skipping pull for local image: $IMAGE_NAME" + else + docker pull "$IMAGE_NAME" + fi + + - name: Start Docker Container + run: | + echo "Starting container on port $HOST_PORT..." + docker run -d --rm \ + --name $CONTAINER_NAME \ + -e "ACCEPT_EULA=Y" \ + -e "SA_PASSWORD=$SA_PASSWORD" \ + -p $HOST_PORT:1433 \ + $IMAGE_NAME + + - name: Wait for container startup + run: | + echo "Waiting 10 seconds for container to finish starting..." + sleep 15 + + - name: Check or install sqlcmd + run: | + if docker exec $CONTAINER_NAME bash -c "[ -x /opt/mssql-tools/bin/sqlcmd ]"; then + echo "sqlcmd already installed." + else + echo "sqlcmd missing — installing..." + docker exec -u root $CONTAINER_NAME bash -c "\ + apt-get update && \ + apt-get install -y curl gnupg2 apt-transport-https && \ + curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && \ + curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-tools.list && \ + apt-get update && \ + ACCEPT_EULA=Y apt-get install -y mssql-tools unixodbc-dev && \ + echo 'export PATH=$PATH:/opt/mssql-tools/bin' >> /root/.bashrc \ + " + fi + + - name: Copy database creation script into container + run: | + docker cp "${GITHUB_WORKSPACE}/Scripts/CreateAutopilotDatabases.sql" $CONTAINER_NAME:/tmp/CreateAutopilotDatabases.sql + + - name: Initialize databases + run: | + echo "Running database initialization script..." + for i in {1..10}; do + if docker exec $CONTAINER_NAME /opt/mssql-tools/bin/sqlcmd \ + -S localhost -U sa -P "$SA_PASSWORD" \ + -i /tmp/CreateAutopilotDatabases.sql; then + echo "Database initialization succeeded." + exit 0 + fi + echo "Initialization failed, retrying ($i/10)..." + sleep 10 + done + + echo "Database initialization failed after retries" + docker logs $CONTAINER_NAME + exit 1 + + - name: Export connection info for Flyway + run: | + echo "dbUser=sa" >> "$GITHUB_ENV" + echo "dbPassword=$SA_PASSWORD" >> "$GITHUB_ENV" + echo "instance=localhost,$HOST_PORT" >> "$GITHUB_ENV" + + Validate-Flyway-Pipeline: + if: github.repository_owner == 'RG-AutoPilot' # Only runs if the repo is in a specific organisation + name: Run Flyway Pipeline + needs: setup-validation-environment + uses: ./.github/workflows/GitHub-Flyway-CICD-Pipeline_Linux.yml + secrets: inherit # Inherit existing secrets but allow environment overrides + + cleanup: + name: Cleanup SQL Server Container + runs-on: "self-hosted" + needs: Validate-Flyway-Pipeline + if: always() + env: + CONTAINER_NAME: "${{ vars.CONTAINER_NAME }}-${{ github.run_number }}" + steps: + - name: Stop and remove container + run: | + echo "Cleaning up container $CONTAINER_NAME" + docker stop $CONTAINER_NAME || true + docker rm $CONTAINER_NAME || true diff --git a/.github/workflows/GitHub-Workflow-Validation-Checks_RGCLONE.yml b/.github/workflows/GitHub-Workflow-Validation-Checks_RGCLONE.yml deleted file mode 100644 index 66e6f50..0000000 --- a/.github/workflows/GitHub-Workflow-Validation-Checks_RGCLONE.yml +++ /dev/null @@ -1,179 +0,0 @@ -# =========================== -# Pipeline Name: GitHub-Workflow-Validation-Checks_RGCLONE.yml -# Version: 1.0.0 -# Author: Chris Hawkins (Redgate Software Ltd) -# Last Updated: 2025-03-17 -# Description: GitHub Pipeline Validation Workflow (Use Case - To validate all future changes to the Autopilot repository in an automated way) -# =========================== - -name: GitHub - FastTrack Pipeline Validation Workflow -on: - workflow_dispatch: # Allows manual triggering - repository_dispatch: - types: [trigger-validation] # Listens for dispatch events, which can trigger this workflow automatically on regular schedules - pull_request: - branches: - - release # Triggers on PRs to release - - 'feature/*' # Triggers on PRs to any feature branch - # schedule: - # - cron: "0 2 * * *" # Runs at 3 AM UTC - - ### Step 1: Define Repository Secrets ### - ### Environment Secrets - Create Environment Secrets ### - ### Navigate to Settings > Secrets & Variables > Actions - # RGCLONE_API_ENDPOINT: Enter the RGClone API Endpoint Address - # RGCLONE_ACCESS_TOKEN: Enter the Access Token for connecting to the above endpoint - ### Step 2: Define REpository Variables ### - ### Environment Secrets - Create Environment Secrets ### - ### Navigate to Settings > Secrets & Variables > Actions - # RGCLONE_IMAGE_NAME: Enter the name of the RGClone Image to be used - # RGCLONE_CONTAINER_NAME: Enter the name of the container to be created - # RGCLONE_PROXY_PORT: Enter the local port number to be used by the proxy command -### End of Environment Variables ### - -jobs: - setup-validation-environment: - if: github.repository_owner == 'RG-AutoPilot' # Only runs if the repo is in a specific organisation - name: Spin Up RGClone Validation Container - runs-on: "self-hosted" - env: - DATA_IMAGE_NAME: "${{ vars.RGCLONE_IMAGE_NAME }}" - DATA_CONTAINER_NAME: "${{ vars.RGCLONE_CONTAINER_NAME }}-${{ github.run_number }}" - PROXY_PORT: "${{ vars.RGCLONE_PROXY_PORT }}" - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Install rgclone CLI - id: installCLI - env: - RGCLONE_API_ENDPOINT: ${{ secrets.RGCLONE_API_ENDPOINT }} - RGCLONE_ACCESS_TOKEN: ${{ secrets.RGCLONE_ACCESS_TOKEN }} - run: | - # Check if rgclone is already installed - if command -v rgclone &> /dev/null; then - echo "rgclone is already installed. Skipping installation." - rgclone version - exit 0 - fi - - echo "rgclone not found. Installing..." - - # Define install location - INSTALL_DIR="/usr/local/bin" - TEMP_DIR=$(mktemp -d) - - # Download and extract rgclone - curl $RGCLONE_API_ENDPOINT/cloning-api/download/cli/linux-amd64 | tar xz -C "$TEMP_DIR" - - # Move rgclone to the install directory - sudo mv "$TEMP_DIR/rgclone" "$INSTALL_DIR/" - sudo chmod +x "$INSTALL_DIR/rgclone" - - # Verify installation - echo "rgclone installed successfully." - rgclone version - - - name: Validate Data Image - id: createDataImage - env: - RGCLONE_API_ENDPOINT: ${{ secrets.RGCLONE_API_ENDPOINT }} - RGCLONE_ACCESS_TOKEN: ${{ secrets.RGCLONE_ACCESS_TOKEN }} - run: | - output=$(rgclone get di "$DATA_IMAGE_NAME" --ignore-not-found -o json) - - if [[ -z "$output" ]]; then - echo "Image does not exist. Creating image..." - rgclone create data-image -f /home/flywayap/rgclone/yaml/AutoPilot_MSSQL-databases-from-script.yaml - else - echo "Image already exists. Moving on..." - fi - - - name: Create data container - id: createDc - env: - RGCLONE_API_ENDPOINT: ${{ secrets.RGCLONE_API_ENDPOINT }} - RGCLONE_ACCESS_TOKEN: ${{ secrets.RGCLONE_ACCESS_TOKEN }} - run: | - # Spin up a Data Container for chosen Image - echo "Check if Data Container Already Exists" - - if ! rgclone get data-container "$DATA_CONTAINER_NAME" &> /dev/null ; then - echo "Creating container for $DATA_CONTAINER_NAME" - output=$(rgclone create dc -n "$DATA_CONTAINER_NAME" -i "$DATA_IMAGE_NAME" -t 20m -o json) - fi - - # Parse JSON output using jq - dbUser=$(echo "$output" | jq -r '.user') - dbPassword=$(echo "$output" | jq -r '.password') - sqlhost=$(echo "$output" | jq -r '.host') - sqlport=$(echo "$output" | jq -r '.port') - instance="${sqlhost},${sqlport}" - - echo "Data container created successfully and available at: $instance" - - # Set output values for use in subsequent steps - echo "dbUser=$dbUser" >> "$GITHUB_ENV" - echo "dbPassword=$dbPassword" >> "$GITHUB_ENV" - echo "instance=$instance" >> "$GITHUB_ENV" - - - name: Create Local Proxy for Container - id: createProxy - env: - RGCLONE_API_ENDPOINT: ${{ secrets.RGCLONE_API_ENDPOINT }} - RGCLONE_ACCESS_TOKEN: ${{ secrets.RGCLONE_ACCESS_TOKEN }} - run: | - echo "Checking if port $PROXY_PORT is in use..." - - # Check if any process is listening on the specified port - if lsof -i :$PROXY_PORT &>/dev/null; then - echo "Port $PROXY_PORT is in use. Killing the active process..." - - # Get the PID of the process using the port and kill it - PID=$(lsof -ti :$PROXY_PORT) - kill -9 $PID - echo "Process $PID using port $PROXY_PORT has been terminated." - else - echo "Port $PROXY_PORT is free. No existing process found." - fi - - # Start the new RGClone proxy - echo "Starting new RGClone Proxy on port $PROXY_PORT" - RUNNER_TRACKING_ID="" && rgclone proxy dc "$DATA_CONTAINER_NAME" -p "$PROXY_PORT" & # Run the proxy in the background - - Validate-Flyway-Pipeline: - if: github.repository_owner == 'RG-AutoPilot' # Only runs if the repo is in a specific organisation - name: Run Flyway Pipeline - needs: setup-validation-environment - uses: ./.github/workflows/GitHub-Flyway-CICD-Pipeline_Linux.yml - secrets: inherit # Inherit existing secrets but allow environment overrides - - cleanup: - name: Clean-up Container - runs-on: "self-hosted" - needs: Validate-Flyway-Pipeline # This ensures cleanup runs after the validation pipeline job - if: always() && github.repository_owner == 'RG-AutoPilot' # Ensures this job runs even if Validate-Flyway-Pipeline fails - steps: - - name: Clean-up Containers - run: | - echo "Cleaning up containers" - # Validate if container exists - echo "Check if Data Container Already Exists" - - if rgclone get data-container "$DATA_CONTAINER_NAME" &> /dev/null ; then - echo "Deleting container for $DATA_CONTAINER_NAME" - rgclone delete dc -n "$DATA_CONTAINER_NAME" - fi - # This step will check if all jobs have complete and if any fail, the whole workflow will be rerun ONCE. This is required for reasons such as multiple PRs running at the same time. - retry-workflow: - name: Retry Entire Workflow If Any Job Fails - runs-on: "self-hosted" - needs: [setup-validation-environment, Validate-Flyway-Pipeline, cleanup] - if: failure() && github.repository_owner == 'RG-AutoPilot' # Triggers only if any previous job failed - steps: - - name: Trigger Workflow Again - env: - GITHUB_TOKEN: ${{ secrets.PAT }} - run: | - echo "Retrying workflow due to failure..." - gh workflow run "${{ github.workflow }}" -f run_id="${{ github.run_id }}" diff --git a/Scripts/Flyway_DownloadAndInstallCLI_Unix.sh b/Scripts/Flyway_DownloadAndInstallCLI_Unix.sh index fc09dee..27a9e2e 100644 --- a/Scripts/Flyway_DownloadAndInstallCLI_Unix.sh +++ b/Scripts/Flyway_DownloadAndInstallCLI_Unix.sh @@ -2,101 +2,255 @@ # =========================== # Script Name: Flyway_DownloadAndInstallCLI.sh -# Version: 1.0.0 +# Version: 1.2.0 # Author: Chris Hawkins (Redgate Software Ltd) -# Last Updated: 2025-03-17 -# Description: Automated Flyway CLI Installation Script +# Last Updated: 2025-12-19 +# Description: Install Flyway CLI on Linux with cleanup of old versions and PATH handling +# Supports both manual execution and CI/CD pipelines (GitHub Actions, etc.) # =========================== -SCRIPT_VERSION="1.0.0" +set -e +SCRIPT_VERSION="1.2.0" echo "Running Flyway Installer Script - Version $SCRIPT_VERSION" +# --------------------------- +# Detect execution context +# --------------------------- +# Check if running in CI/CD environment +if [ -n "$CI" ] || [ -n "$GITHUB_ACTIONS" ] || [ -n "$GITLAB_CI" ] || [ -n "$CIRCLECI" ]; then + IS_CI=true + echo "CI/CD environment detected" +else + IS_CI=false +fi -# Check if FLYWAY_VERSION is set as an environment variable -if [ -z "$FLYWAY_VERSION" ]; then - # If not set, assign a default value to a local variable - FLYWAY_VERSION="Latest" - echo "FLYWAY_VERSION is not set. Using default local variable value of '$FLYWAY_VERSION'." +# Check if we have sudo/root access +if [ "$EUID" -eq 0 ] || sudo -n true 2>/dev/null; then + HAS_SUDO=true else - # If set, echo the environment variable and its value - echo "FLYWAY_VERSION is set. Current value is: $FLYWAY_VERSION" + HAS_SUDO=false + echo "No sudo access detected - using user-space installation" +fi + +# --------------------------- +# Configurable Variables +# --------------------------- +FLYWAY_VERSION="${FLYWAY_VERSION:-Latest}" # Default to Latest if not set + +# Smart default: use user home if no sudo or in CI, otherwise /opt/flyway +if [ -z "$FLYWAY_INSTALL_DIR" ]; then + if [ "$HAS_SUDO" = true ] && [ "$IS_CI" = false ]; then + FLYWAY_INSTALL_DIR="/opt/flyway" + else + FLYWAY_INSTALL_DIR="$HOME/.flyway" + fi fi -# Function to get the currently installed Flyway version +# For CI/CD or non-sudo environments, update user profile instead of system-wide +if [ -z "$GLOBAL_PATH_UPDATE" ]; then + if [ "$HAS_SUDO" = true ] && [ "$IS_CI" = false ]; then + GLOBAL_PATH_UPDATE=true + else + GLOBAL_PATH_UPDATE=false + fi +fi + +echo "Requested Flyway version: $FLYWAY_VERSION" +echo "Flyway install directory: $FLYWAY_INSTALL_DIR" +echo "Global PATH update: $GLOBAL_PATH_UPDATE" + +# --------------------------- +# Helper Functions +# --------------------------- get_installed_version() { - if command -v flyway >/dev/null 2>&1; then - flyway --version | grep -Eo 'Flyway (Community|Pro|Enterprise|Teams) Edition [0-9]+\.[0-9]+\.[0-9]+' | awk '{print $4}' - else - echo "none" # Indicate no version is installed - fi + if command -v flyway >/dev/null 2>&1; then + flyway --version | grep -Eo 'Flyway (Community|Pro|Enterprise|Teams) Edition [0-9]+\.[0-9]+\.[0-9]+' | awk '{print $4}' + else + echo "none" + fi } -# Function to get the latest version from the website get_latest_version_from_website() { - # Fetch the webpage content - content=$(curl -s https://documentation.red-gate.com/flyway/reference/usage/command-line) + content=$(curl -s https://documentation.red-gate.com/flyway/reference/usage/command-line) + echo "$content" | grep -oP 'flyway-commandline-\K\d+\.\d+\.\d+(?=-linux-x64.tar.gz)' | head -n 1 +} - # Extract version number using regex - latest_version=$(echo "$content" | grep -oP 'flyway-commandline-\K\d+\.\d+\.\d+(?=-windows-x64.zip)' | head -n 1) +cleanup_old_versions() { + echo "Cleaning up old Flyway versions..." + for dir in "$FLYWAY_INSTALL_DIR"/flyway-*; do + # Skip current version and non-existent + [ -d "$dir" ] || continue + [[ "$dir" == "$INSTALL_DIR" ]] && continue - echo "$latest_version" + echo "Removing old Flyway version at $dir" + if [ "$HAS_SUDO" = true ] && [[ "$dir" == /opt/* ]]; then + sudo rm -rf "$dir" + else + rm -rf "$dir" + fi + done } -# Get the currently installed Flyway version -CURRENT_VERSION=$(get_installed_version) -echo "Current Flyway Version Is: $CURRENT_VERSION" +cleanup_old_path_entries() { + echo "Cleaning up old PATH entries..." + + if [ "$GLOBAL_PATH_UPDATE" = true ]; then + # Clean up /etc/profile + if [ -f /etc/profile ]; then + # Create temp file without any flyway PATH entries + sudo grep -v 'export PATH=.*flyway-' /etc/profile > /tmp/profile.tmp || true + sudo mv /tmp/profile.tmp /etc/profile + echo "Removed all old Flyway PATH entries from /etc/profile" + fi + else + # Clean up user profile + USER_PROFILE="" + if [ -f "$HOME/.bashrc" ]; then + USER_PROFILE="$HOME/.bashrc" + elif [ -f "$HOME/.bash_profile" ]; then + USER_PROFILE="$HOME/.bash_profile" + elif [ -f "$HOME/.profile" ]; then + USER_PROFILE="$HOME/.profile" + fi + + if [ -n "$USER_PROFILE" ] && [ -f "$USER_PROFILE" ]; then + # Create temp file without any flyway PATH entries + grep -v 'export PATH=.*flyway-' "$USER_PROFILE" > "${USER_PROFILE}.tmp" || true + mv "${USER_PROFILE}.tmp" "$USER_PROFILE" + echo "Removed all old Flyway PATH entries from $USER_PROFILE" + fi + fi +} -# Check if FLYWAY_VERSION required is 'Latest' -if [ "$FLYWAY_VERSION" = "latest" ] || [ "$FLYWAY_VERSION" = "Latest" ]; then - LATEST_VERSION=$(get_latest_version_from_website) - if [ -z "$LATEST_VERSION" ]; then - echo "Could not retrieve the latest version from the website. Exiting." - exit 1 - fi - echo "Latest Flyway Version Is: $LATEST_VERSION" - echo "Setting Flyway Version to be installed to: $LATEST_VERSION" - FLYWAY_VERSION=$LATEST_VERSION +# --------------------------- +# Determine Flyway version +# --------------------------- +if [[ "$FLYWAY_VERSION" =~ [Ll]atest ]]; then + LATEST_VERSION=$(get_latest_version_from_website) + if [ -z "$LATEST_VERSION" ]; then + echo "Could not detect latest Flyway version. Exiting." + exit 1 + fi + echo "Latest Flyway version detected: $LATEST_VERSION" + FLYWAY_VERSION="$LATEST_VERSION" fi +# --------------------------- +# Installation directory +# --------------------------- +INSTALL_DIR="$FLYWAY_INSTALL_DIR/flyway-$FLYWAY_VERSION" - -# Check if the current version matches the latest version -if [ "$CURRENT_VERSION" = "$FLYWAY_VERSION" ]; then - echo "Flyway $CURRENT_VERSION is already installed and up-to-date. No action needed." - exit 0 +# --------------------------- +# Check if already installed +# --------------------------- +if [ -d "$INSTALL_DIR" ]; then + echo "Flyway $FLYWAY_VERSION already installed at $INSTALL_DIR. Skipping download." else - echo "Current version ($CURRENT_VERSION) does not match the required version ($FLYWAY_VERSION). Installing the required version." -fi - -# Proceed with the installation of the latest version -INSTALL_DIR="$HOME/flyway-$FLYWAY_VERSION" # Install directory in the user's home folder + echo "Downloading Flyway $FLYWAY_VERSION from Red Gate..." + echo "Source: https://download.red-gate.com/maven/release/com/redgate/flyway/flyway-commandline/$FLYWAY_VERSION/" + + # Use temp directory for extraction to ensure we have write permissions + TEMP_EXTRACT_DIR=$(mktemp -d) + cd "$TEMP_EXTRACT_DIR" + + wget -qO- "https://download.red-gate.com/maven/release/com/redgate/flyway/flyway-commandline/$FLYWAY_VERSION/flyway-commandline-$FLYWAY_VERSION-linux-x64.tar.gz" \ + | tar -xz --no-same-owner + echo "Download and extraction complete." -# Download and install Flyway -echo "Downloading and installing Flyway version $FLYWAY_VERSION..." -wget -qO- https://download.red-gate.com/maven/release/com/redgate/flyway/flyway-commandline/$FLYWAY_VERSION/flyway-commandline-$FLYWAY_VERSION-linux-x64.tar.gz | tar -xvz - -# Check if the download and extraction were successful -if [[ $? -ne 0 ]]; then - echo "Error: Download failed. Please check that FLYWAY_VERSION '${FLYWAY_VERSION}' is correct and available for download." - exit 1 + echo "Installing Flyway to $INSTALL_DIR..." + # Ensure parent directory exists (with or without sudo) + if [ "$HAS_SUDO" = true ] && [[ "$FLYWAY_INSTALL_DIR" == /opt/* ]]; then + sudo mkdir -p "$FLYWAY_INSTALL_DIR" + sudo mv "$TEMP_EXTRACT_DIR/flyway-$FLYWAY_VERSION" "$INSTALL_DIR" + else + mkdir -p "$FLYWAY_INSTALL_DIR" + mv "$TEMP_EXTRACT_DIR/flyway-$FLYWAY_VERSION" "$INSTALL_DIR" + fi + + # Cleanup temp directory + rm -rf "$TEMP_EXTRACT_DIR" + cd - >/dev/null + + echo "Installation complete." fi -# Move the Flyway folder to the install directory -mv "flyway-$FLYWAY_VERSION" "$INSTALL_DIR" +# --------------------------- +# Update PATH for current session +# --------------------------- +# First, clean up any existing Flyway entries from current PATH to prevent bloat +CLEANED_PATH=$(echo "$PATH" | tr ':' '\n' | grep -v "/flyway-" | tr '\n' ':' | sed 's/:$//') -# Overwrite or create symbolic link to the Flyway executable -sudo ln -sf "$INSTALL_DIR/flyway" /usr/local/bin/flyway +# Now add the new version +export PATH="$INSTALL_DIR:$CLEANED_PATH" +echo "PATH updated for current session (cleaned and updated)" +echo "New PATH: $PATH" -echo "Flyway version $FLYWAY_VERSION is downloaded and installed." +# --------------------------- +# Cleanup old Flyway versions and PATH entries +# --------------------------- +cleanup_old_versions +cleanup_old_path_entries -echo "Updating PATH Variable" -export PATH="/usr/local/bin/flyway-$FLYWAY_VERSION/:$PATH" +# --------------------------- +# Add current version to PATH in profile +# --------------------------- +if [ "$GLOBAL_PATH_UPDATE" = true ]; then + # System-wide update (requires sudo) - add back the current version + if sudo sh -c "echo 'export PATH=\"$INSTALL_DIR:\$PATH\"' >> /etc/profile"; then + echo "Added current Flyway version to /etc/profile" + else + echo "Warning: Could not update global PATH, continuing..." + fi +else + # User-space update (no sudo required) + USER_PROFILE="" + + # Detect which profile file to use + if [ -f "$HOME/.bashrc" ]; then + USER_PROFILE="$HOME/.bashrc" + elif [ -f "$HOME/.bash_profile" ]; then + USER_PROFILE="$HOME/.bash_profile" + elif [ -f "$HOME/.profile" ]; then + USER_PROFILE="$HOME/.profile" + else + USER_PROFILE="$HOME/.profile" + touch "$USER_PROFILE" + fi + + # Add current version to profile + echo "export PATH=\"$INSTALL_DIR:\$PATH\"" >> "$USER_PROFILE" + echo "Added current Flyway version to $USER_PROFILE" + + # For CI/CD: also add to GITHUB_PATH if it exists + if [ -n "$GITHUB_PATH" ]; then + echo "$INSTALL_DIR" >> "$GITHUB_PATH" + echo "Added to GITHUB_PATH for GitHub Actions" + fi +fi -# Validate Flyway installation -if flyway --version; then - echo "Flyway is successfully installed and running version $(flyway --version | grep -Eo 'Flyway (Community|Pro|Enterprise|Teams) Edition [0-9]+\.[0-9]+\.[0-9]+' | awk '{print $4}')." +# --------------------------- +# Verify installation +# --------------------------- +if flyway --version >/dev/null 2>&1; then + echo "Flyway $FLYWAY_VERSION installed successfully and running." + echo "" + echo "===========================================" + echo "IMPORTANT: To use the cleaned PATH in your current terminal:" + if [ "$GLOBAL_PATH_UPDATE" = true ]; then + echo " Run: source /etc/profile" + else + if [ -f "$HOME/.bashrc" ]; then + echo " Run: source ~/.bashrc" + elif [ -f "$HOME/.bash_profile" ]; then + echo " Run: source ~/.bash_profile" + else + echo " Run: source ~/.profile" + fi + fi + echo "Or start a new terminal session." + echo "===========================================" else - echo "Flyway installation failed. Please check for issues." - exit 1 # Exit with failure status (non-zero) if Flyway isn't working + echo "Flyway installation failed!" + exit 1 fi diff --git a/schema-model/Tables/Logistics.Flight.sql b/schema-model/Tables/Logistics.Flight.sql index 0021126..6fff5c8 100644 --- a/schema-model/Tables/Logistics.Flight.sql +++ b/schema-model/Tables/Logistics.Flight.sql @@ -7,7 +7,8 @@ CREATE TABLE [Logistics].[Flight] [DepartureTime] [datetime] NOT NULL, [ArrivalTime] [datetime] NOT NULL, [Price] [decimal] (10, 2) NOT NULL, -[AvailableSeats] [int] NOT NULL +[AvailableSeats] [int] NOT NULL, + Test ) GO ALTER TABLE [Logistics].[Flight] ADD CONSTRAINT [PK__Flight__8A9E148E9A8ED149] PRIMARY KEY CLUSTERED ([FlightID])