Commit 62c1a962 authored by Yann D'Isanto's avatar Yann D'Isanto
Browse files

feat: allow to keep old version on deploy

parent e3d8949e
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -120,6 +120,7 @@ Here are variables supported to configure review environments:
| `CF_REVIEW_ZERODOWNTIME` | Enables zero-downtime deployment on `review` env| `false` |
| `CF_REVIEW_ENVIRONMENT_SCHEME` | The review environment protocol scheme | `https` |
| `CF_REVIEW_ENVIRONMENT_DOMAIN` | The review environment domain | _none_ |
| `CF_REVIEW_RETIRED_APP_SUFFIX` | If set, the app old version is not deleted/overriden but renamed with this suffix | _none_ |

Note: By default review `environment.url` will be built as `${CF_REVIEW_ENVIRONMENT_SCHEME}://${$CI_PROJECT_NAME}-${CI_ENVIRONMENT_SLUG}.${CF_REVIEW_ENVIRONMENT_DOMAIN}`

@@ -142,7 +143,8 @@ Here are variables supported to configure the integration environment:
| `CF_INTEG_DOMAIN`     | CF domain for `integration` env        | `$CF_DEFAULT_DOMAIN` |
| `CF_INTEG_HOST_NAME`  | application host name for `integration` env| `"${CF_BASE_APP_NAME}-integration"` |
| `CF_INTEG_ZERODOWNTIME`  | Enables zero-downtime deployment on `integration` env| `false` |
| `CF_INTEG_ENVIRONMENT_URL`     | The integration environment url **including scheme** (ex: `https://my-application-integration.nonpublic.domain.com`). Do not use variable inside variable definition as it will result in a two level cascade variable and gitlab does not allow that. | _none_ |
| `CF_INTEG_ENVIRONMENT_URL`     | The integration environment url **including scheme** (ex: `https://my-application-integration.nonpublic.domain.com`). Do not use variable inside variable definition as it will result in a two level cascade variable and gitlab does not allow that. | _none_ |
| `CF_INTEG_RETIRED_APP_SUFFIX` | If set, the app old version is not deleted/overriden but renamed with this suffix | _none_ |

#### Staging environment

@@ -165,6 +167,7 @@ Here are variables supported to configure the staging environment:
| `CF_STAGING_HOST_NAME`| application host name for `staging` env| `"${CF_BASE_APP_NAME}-staging"` |
| `CF_STAGING_ZERODOWNTIME` | Enables zero-downtime deployment on `staging` env| `false` |
| `CF_STAGING_ENVIRONMENT_URL`   | The staging environment url **including scheme** (ex: `https://my-application-staging.nonpublic.domain.com`). Do not use variable inside variable definition as it will result in a two level cascade variable and gitlab does not allow that. | _none_ |
| `CF_STAGING_RETIRED_APP_SUFFIX` | If set, the app old version is not deleted/overriden but renamed with this suffix | _none_ |

#### Production environment

@@ -187,6 +190,7 @@ Here are variables supported to configure the production environment:
| `AUTODEPLOY_TO_PROD`     | Determines the production deployment policy. When set, deployment to production is automatic (_continuous deployment_). When not set (default), deployment to production is manual (_continuous delivery_). | _none_ (_continuous delivery_) |
| `CF_PROD_ZERODOWNTIME`| Enables zero-downtime deployment on `production` env | `true` |
| `CF_PROD_ENVIRONMENT_URL`      | The production environment url **including scheme** (ex: `https://my-application.public.domain.com`) Do not use variable inside variable definition as it will result in a two level cascade variable and gitlab does not allow that. | _none_ |
| `CF_PROD_RETIRED_APP_SUFFIX` | If set, the app old version is not deleted/overriden but renamed with this suffix | _none_ |


### Hook scripts
+20 −0
Original line number Diff line number Diff line
@@ -109,6 +109,11 @@
          "name": "CLEANUP_ALL_REVIEW",
          "description": "Enables a **manual** job to cleanup all review envs at once.\n\nYou may also use it to [schedule](https://docs.gitlab.com/ee/ci/pipelines/schedules.html) cloud resources cleanup. See documentation.",
          "type": "boolean"
        },
        {
          "name": "CF_REVIEW_RETIRED_APP_SUFFIX",
          "description": "If set, the app old version is not deleted/overriden but renamed with this suffix",
          "advanced": true
        }
      ]
    },
@@ -154,6 +159,11 @@
          "name": "CF_INTEG_PASSWORD",
          "description": "Cloud Foundry API password for integration env (only define if different from global)",
          "secret": true
        },
        {
          "name": "CF_INTEG_RETIRED_APP_SUFFIX",
          "description": "If set, the app old version is not deleted/overriden but renamed with this suffix",
          "advanced": true
        }
      ]
    },
@@ -199,6 +209,11 @@
          "name": "CF_STAGING_PASSWORD",
          "description": "Cloud Foundry API password for staging env (only define if different from global)",
          "secret": true
        },
        {
          "name": "CF_STAGING_RETIRED_APP_SUFFIX",
          "description": "If set, the app old version is not deleted/overriden but renamed with this suffix",
          "advanced": true
        }
      ]
    },
@@ -249,6 +264,11 @@
          "name": "CF_PROD_PASSWORD",
          "description": "Cloud Foundry API password for production env (only define if different from global)",
          "secret": true
        },
        {
          "name": "CF_PROD_RETIRED_APP_SUFFIX",
          "description": "If set, the app old version is not deleted/overriden but renamed with this suffix",
          "advanced": true
        }
      ]
    }
+44 −3
Original line number Diff line number Diff line
@@ -319,6 +319,17 @@ stages:
    fi
    cf_push_args+=("-f" "$manifestfile")

    if [[ "$appname" == "$tmpappname" && -n "$ENV_RETIRED_APP_SUFFIX" ]]
    then
      # keep retired version for non blue/green deployment
      app_retired_ver="${appname}-$ENV_RETIRED_APP_SUFFIX"
      log_info "--- delete previous retired version \\e[33;1m${app_retired_ver}\\e[0m..."
      cf delete "$app_retired_ver" -f
      log_info "--- retiring current app (rename \\e[33;1m${appname}\\e[0m to \\e[33;1m${app_retired_ver}\\e[0m)..."
      cf rename "$appname" "$app_retired_ver"
      unmap_app_routes "$app_retired_ver"
    fi

    pre_start="$CF_SCRIPTS_DIR/cf-pre-start.sh"
    if [[ -f "$pre_start" ]]
    then
@@ -478,9 +489,21 @@ stages:
    cf delete-route "$domain_tmp" --hostname "$hostname_tmp" -f
    echo

    # delete "blue"
    
    # delete "blue" or rename it with configured suffix
    if [[ -z "$ENV_RETIRED_APP_SUFFIX" ]]
    then
      log_info "--- \\e[32mblue-green [4/5]\\e[0m: delete \\e[33;1m${app_target}\\e[0m..."
      cf delete "$app_target" -f
    else
      app_retired_ver="${app_target}-$ENV_RETIRED_APP_SUFFIX"
      log_info "--- \\e[32mblue-green [4/5]\\e[0m: retiring current app..."
      log_info "--- delete previous retired app \\e[33;1m${app_retired_ver}\\e[0m..."
      cf delete "$app_retired_ver" -f
      log_info "--- rename \\e[33;1m${app_target}\\e[0m as \\e[33;1m${app_retired_ver}\\e[0m..."
      cf rename "$app_target" "$app_retired_ver"
      unmap_app_routes "$app_retired_ver"
    fi
    echo

    # rename "green"
@@ -612,6 +635,17 @@ stages:
    cf domains | awk '/ shared/ && !/ tcp/ && !/ internal/ {print $1}' | head -n 1 || true
  }

  function unmap_app_routes() {
    app_name="$1"
    app_routes=$(cf app "$app_name" | awk -F ":" '/routes:/ {print $2}' | tr "," " ")
    for route in $app_routes
    do
      route_hostname=$(echo "$route" | cut -d '.' -f1)
      route_domain=$(echo "$route" | cut -d '.' -f2-)
      cf unmap-route "$app_name" "$route_domain" --hostname="$route_hostname"
    done
  }

  function get_latest_template_version() {
    tag_json=$(wget -T 5 -q -O - "$CI_API_V4_URL/projects/to-be-continuous%2F$1/repository/tags?per_page=1" || echo "")
    echo "$tag_json" | sed -rn 's/^.*"name":"([^"]*)".*$/\1/p'
@@ -643,6 +677,8 @@ stages:
    - name: "$CI_REGISTRY/to-be-continuous/tools/tracking:master"
      command: ["--service", "cloudfoundry", "1.2.1" ]
  before_script:
    # forcing en-US locale so we can parse cf commands output if necessary
    - cf config --locale "en-US"
    - *cf-scripts
    - install_ca_certs "${CUSTOM_CA_CERTS:-$DEFAULT_CA_CERTS}"

@@ -660,6 +696,7 @@ stages:
# @arg ENV_ZERODOWNTIME: whether or not zero downtime deployment shall be used
# @arg ENV_DOMAIN    : env-specific domain
# @arg ENV_HOST_NAME : env-specific application hostname to use
# @arg ENV_RETIRED_APP_SUFFIX : If set, the app old version is not deleted/overriden but renamed with this suffix
.cf-deploy:
  extends: .cf-base
  stage: deploy
@@ -735,6 +772,7 @@ cf-review:
    ENV_ZERODOWNTIME: "$CF_REVIEW_ZERODOWNTIME"
    ENV_DOMAIN: "$CF_REVIEW_DOMAIN"
    ENV_HOST_NAME: "$CF_REVIEW_HOST_NAME"
    ENV_RETIRED_APP_SUFFIX: "$CF_REVIEW_RETIRED_APP_SUFFIX"
  environment:
    name: review/$CI_COMMIT_REF_NAME
    url: "${CF_REVIEW_ENVIRONMENT_SCHEME}://${CI_PROJECT_NAME}-${CI_ENVIRONMENT_SLUG}.${CF_REVIEW_ENVIRONMENT_DOMAIN}"
@@ -830,6 +868,7 @@ cf-integration:
    ENV_ZERODOWNTIME: "$CF_INTEG_ZERODOWNTIME"
    ENV_DOMAIN: "$CF_INTEG_DOMAIN"
    ENV_HOST_NAME: "$CF_INTEG_HOST_NAME"
    ENV_RETIRED_APP_SUFFIX: "$CF_INTEG_RETIRED_APP_SUFFIX"
  environment:
    name: integration
    url: "${CF_INTEG_ENVIRONMENT_URL}"
@@ -859,6 +898,7 @@ cf-staging:
    ENV_ZERODOWNTIME: "$CF_STAGING_ZERODOWNTIME"
    ENV_DOMAIN: "$CF_STAGING_DOMAIN"
    ENV_HOST_NAME: "$CF_STAGING_HOST_NAME"
    ENV_RETIRED_APP_SUFFIX: "$CF_STAGING_RETIRED_APP_SUFFIX"
  environment:
    name: staging
    url: "${CF_STAGING_ENVIRONMENT_URL}"
@@ -889,6 +929,7 @@ cf-production:
    ENV_ZERODOWNTIME: "$CF_PROD_ZERODOWNTIME"
    ENV_DOMAIN: "$CF_PROD_DOMAIN"
    ENV_HOST_NAME: "$CF_PROD_HOST_NAME"
    ENV_RETIRED_APP_SUFFIX: "$CF_PROD_RETIRED_APP_SUFFIX"
  environment:
    name: production
    url: "${CF_PROD_ENVIRONMENT_URL}"