Auto-DevOps.gitlab-ci.yml 24.0 KB
Newer Older
A
Alessio Caiazza 已提交
1 2 3 4 5 6 7 8 9
# Auto DevOps
# This CI/CD configuration provides a standard pipeline for
# * building a Docker image (using a buildpack if necessary),
# * storing the image in the container registry,
# * running tests from a buildpack,
# * running code quality analysis,
# * creating a review app for each topic branch,
# * and continuous deployment to production
#
O
Olivier Gonzalez 已提交
10 11 12
# Test jobs may be disabled by setting environment variables:
# * test: TEST_DISABLED
# * code_quality: CODE_QUALITY_DISABLED
13
# * license_management: LICENSE_MANAGEMENT_DISABLED
O
Olivier Gonzalez 已提交
14 15 16 17 18 19 20 21
# * performance: PERFORMANCE_DISABLED
# * sast: SAST_DISABLED
# * dependency_scanning: DEPENDENCY_SCANNING_DISABLED
# * container_scanning: CONTAINER_SCANNING_DISABLED
# * dast: DAST_DISABLED
# * review: REVIEW_DISABLED
# * stop_review: REVIEW_DISABLED
#
A
Alessio Caiazza 已提交
22 23 24 25 26
# In order to deploy, you must have a Kubernetes cluster configured either
# via a project integration, or via group/project variables.
# AUTO_DEVOPS_DOMAIN must also be set as a variable at the group or project
# level, or manually added below.
#
F
Fabio Busatto 已提交
27 28 29
# Continuous deployment to production is enabled by default.
# If you want to deploy to staging first, or enable incremental rollouts,
# set STAGING_ENABLED or INCREMENTAL_ROLLOUT_ENABLED environment variables.
O
Olivier Gonzalez 已提交
30
# If you want to use canary deployments, set CANARY_ENABLED environment variable.
A
Alessio Caiazza 已提交
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
#
# If Auto DevOps fails to detect the proper buildpack, or if you want to
# specify a custom buildpack, set a project variable `BUILDPACK_URL` to the
# repository URL of the buildpack.
# e.g. BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-ruby.git#v142
# If you need multiple buildpacks, add a file to your project called
# `.buildpacks` that contains the URLs, one on each line, in order.
# Note: Auto CI does not work with multiple buildpacks yet

image: alpine:latest

variables:
  # AUTO_DEVOPS_DOMAIN is the application deployment domain and should be set as a variable at the group or project level.
  # AUTO_DEVOPS_DOMAIN: domain.example.com

  POSTGRES_USER: user
  POSTGRES_PASSWORD: testing-password
  POSTGRES_ENABLED: "true"
  POSTGRES_DB: $CI_ENVIRONMENT_SLUG

51
  KUBERNETES_VERSION: 1.8.6
T
Thong Kuah 已提交
52
  HELM_VERSION: 2.11.0
53

54 55
  DOCKER_DRIVER: overlay2

A
Alessio Caiazza 已提交
56 57 58 59
stages:
  - build
  - test
  - review
60
  - dast
A
Alessio Caiazza 已提交
61 62 63
  - staging
  - canary
  - production
J
Joshua Lambert 已提交
64
  - performance
A
Alessio Caiazza 已提交
65 66 67 68
  - cleanup

build:
  stage: build
69
  image: docker:stable-git
A
Alessio Caiazza 已提交
70
  services:
71
  - docker:stable-dind
A
Alessio Caiazza 已提交
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
  script:
    - setup_docker
    - build
  only:
    - branches

test:
  services:
    - postgres:latest
  variables:
    POSTGRES_DB: test
  stage: test
  image: gliderlabs/herokuish:latest
  script:
    - setup_test_db
    - cp -R . /tmp/app
    - /bin/herokuish buildpack test
  only:
    - branches
O
Olivier Gonzalez 已提交
91 92 93
  except:
    variables:
      - $TEST_DISABLED
A
Alessio Caiazza 已提交
94

95
code_quality:
O
Olivier Gonzalez 已提交
96
  stage: test
97
  image: docker:stable
A
Alessio Caiazza 已提交
98 99
  allow_failure: true
  services:
100
    - docker:stable-dind
A
Alessio Caiazza 已提交
101 102
  script:
    - setup_docker
103
    - code_quality
A
Alessio Caiazza 已提交
104
  artifacts:
105
    paths: [gl-code-quality-report.json]
106 107
  only:
    - branches
O
Olivier Gonzalez 已提交
108 109 110
  except:
    variables:
      - $CODE_QUALITY_DISABLED
A
Alessio Caiazza 已提交
111

112
license_management:
113
  stage: test
114 115 116 117 118 119 120 121 122
  image: docker:stable
  allow_failure: true
  services:
    - docker:stable-dind
  script:
    - setup_docker
    - license_management
  artifacts:
    paths: [gl-license-management-report.json]
123 124
  only:
    - branches
125 126 127
  only:
    variables:
      - $GITLAB_FEATURES =~ /\blicense_management\b/
128 129 130 131
  except:
    variables:
      - $LICENSE_MANAGEMENT_DISABLED

J
Joshua Lambert 已提交
132 133
performance:
  stage: performance
134
  image: docker:stable
135 136
  allow_failure: true
  services:
137
    - docker:stable-dind
J
Joshua Lambert 已提交
138
  script:
139
    - setup_docker
J
Joshua Lambert 已提交
140 141 142 143
    - performance
  artifacts:
    paths:
    - performance.json
144
    - sitespeed-results/
J
Joshua Lambert 已提交
145 146 147 148
  only:
    refs:
      - branches
    kubernetes: active
O
Olivier Gonzalez 已提交
149 150 151
  except:
    variables:
      - $PERFORMANCE_DISABLED
J
Joshua Lambert 已提交
152

153
sast:
O
Olivier Gonzalez 已提交
154
  stage: test
155
  image: docker:stable
156
  allow_failure: true
157
  services:
158
    - docker:stable-dind
159
  script:
160 161
    - setup_docker
    - sast
162 163
  artifacts:
    paths: [gl-sast-report.json]
164
  only:
165 166 167 168
    refs:
      - branches
    variables:
      - $GITLAB_FEATURES =~ /\bsast\b/
O
Olivier Gonzalez 已提交
169 170 171
  except:
    variables:
      - $SAST_DISABLED
172

173
dependency_scanning:
O
Olivier Gonzalez 已提交
174
  stage: test
175 176 177 178 179 180 181 182 183
  image: docker:stable
  allow_failure: true
  services:
    - docker:stable-dind
  script:
    - setup_docker
    - dependency_scanning
  artifacts:
    paths: [gl-dependency-scanning-report.json]
184
  only:
185 186 187 188
    refs:
      - branches
    variables:
      - $GITLAB_FEATURES =~ /\bdependency_scanning\b/
O
Olivier Gonzalez 已提交
189 190 191
  except:
    variables:
      - $DEPENDENCY_SCANNING_DISABLED
F
Fabio Busatto 已提交
192

193
container_scanning:
O
Olivier Gonzalez 已提交
194
  stage: test
195
  image: docker:stable
L
Luke Bennett 已提交
196 197
  allow_failure: true
  services:
198
    - docker:stable-dind
L
Luke Bennett 已提交
199 200
  script:
    - setup_docker
201
    - container_scanning
L
Luke Bennett 已提交
202
  artifacts:
203
    paths: [gl-container-scanning-report.json]
204
  only:
205 206 207 208
    refs:
      - branches
    variables:
      - $GITLAB_FEATURES =~ /\bsast_container\b/
O
Olivier Gonzalez 已提交
209 210 211
  except:
    variables:
      - $CONTAINER_SCANNING_DISABLED
212

213 214 215
dast:
  stage: dast
  allow_failure: true
F
Fabien Catteau 已提交
216
  image: registry.gitlab.com/gitlab-org/security-products/zaproxy
217 218 219 220 221 222 223 224 225 226
  variables:
    POSTGRES_DB: "false"
  script:
    - dast
  artifacts:
    paths: [gl-dast-report.json]
  only:
    refs:
      - branches
    kubernetes: active
227 228
    variables:
      - $GITLAB_FEATURES =~ /\bdast\b/
229
  except:
O
Olivier Gonzalez 已提交
230 231 232 233
    refs:
      - master
    variables:
      - $DAST_DISABLED
234

A
Alessio Caiazza 已提交
235 236 237 238 239 240 241
review:
  stage: review
  script:
    - check_kube_domain
    - install_dependencies
    - download_chart
    - ensure_namespace
T
Thong Kuah 已提交
242
    - initialize_tiller
A
Alessio Caiazza 已提交
243 244
    - create_secret
    - deploy
J
Joshua Lambert 已提交
245
    - persist_environment_url
A
Alessio Caiazza 已提交
246 247 248 249
  environment:
    name: review/$CI_COMMIT_REF_NAME
    url: http://$CI_PROJECT_PATH_SLUG-$CI_ENVIRONMENT_SLUG.$AUTO_DEVOPS_DOMAIN
    on_stop: stop_review
J
Joshua Lambert 已提交
250 251
  artifacts:
    paths: [environment_url.txt]
A
Alessio Caiazza 已提交
252 253 254 255 256
  only:
    refs:
      - branches
    kubernetes: active
  except:
O
Olivier Gonzalez 已提交
257 258 259 260
    refs:
      - master
    variables:
      - $REVIEW_DISABLED
A
Alessio Caiazza 已提交
261 262 263 264 265 266 267

stop_review:
  stage: cleanup
  variables:
    GIT_STRATEGY: none
  script:
    - install_dependencies
T
Thong Kuah 已提交
268
    - initialize_tiller
A
Alessio Caiazza 已提交
269 270 271 272 273 274 275 276 277 278 279
    - delete
  environment:
    name: review/$CI_COMMIT_REF_NAME
    action: stop
  when: manual
  allow_failure: true
  only:
    refs:
      - branches
    kubernetes: active
  except:
O
Olivier Gonzalez 已提交
280 281 282 283
    refs:
      - master
    variables:
      - $REVIEW_DISABLED
A
Alessio Caiazza 已提交
284 285 286 287 288 289 290 291 292

# Keys that start with a dot (.) will not be processed by GitLab CI.
# Staging and canary jobs are disabled by default, to enable them
# remove the dot (.) before the job name.
# https://docs.gitlab.com/ee/ci/yaml/README.html#hidden-keys

# Staging deploys are disabled by default since
# continuous deployment to production is enabled by default
# If you prefer to automatically deploy to staging and
F
Fabio Busatto 已提交
293 294
# only manually promote to production, enable this job by setting
# STAGING_ENABLED.
A
Alessio Caiazza 已提交
295

F
Fabio Busatto 已提交
296
staging:
A
Alessio Caiazza 已提交
297 298 299 300 301 302
  stage: staging
  script:
    - check_kube_domain
    - install_dependencies
    - download_chart
    - ensure_namespace
T
Thong Kuah 已提交
303
    - initialize_tiller
A
Alessio Caiazza 已提交
304 305 306 307 308 309 310 311 312
    - create_secret
    - deploy
  environment:
    name: staging
    url: http://$CI_PROJECT_PATH_SLUG-staging.$AUTO_DEVOPS_DOMAIN
  only:
    refs:
      - master
    kubernetes: active
F
Fabio Busatto 已提交
313 314
    variables:
      - $STAGING_ENABLED
A
Alessio Caiazza 已提交
315

O
Olivier Gonzalez 已提交
316 317 318
# Canaries are also disabled by default, but if you want them,
# and know what the downsides are, you can enable this by setting
# CANARY_ENABLED.
A
Alessio Caiazza 已提交
319

O
Olivier Gonzalez 已提交
320
canary:
A
Alessio Caiazza 已提交
321 322 323 324 325 326
  stage: canary
  script:
    - check_kube_domain
    - install_dependencies
    - download_chart
    - ensure_namespace
T
Thong Kuah 已提交
327
    - initialize_tiller
A
Alessio Caiazza 已提交
328 329 330 331 332 333 334 335 336 337
    - create_secret
    - deploy canary
  environment:
    name: production
    url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
  when: manual
  only:
    refs:
      - master
    kubernetes: active
O
Olivier Gonzalez 已提交
338 339
    variables:
      - $CANARY_ENABLED
A
Alessio Caiazza 已提交
340

F
Fabio Busatto 已提交
341
.production: &production_template
A
Alessio Caiazza 已提交
342 343 344 345 346 347
  stage: production
  script:
    - check_kube_domain
    - install_dependencies
    - download_chart
    - ensure_namespace
T
Thong Kuah 已提交
348
    - initialize_tiller
A
Alessio Caiazza 已提交
349 350 351
    - create_secret
    - deploy
    - delete canary
F
Fabio Busatto 已提交
352
    - delete rollout
J
Joshua Lambert 已提交
353
    - persist_environment_url
A
Alessio Caiazza 已提交
354 355 356
  environment:
    name: production
    url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
J
Joshua Lambert 已提交
357 358
  artifacts:
    paths: [environment_url.txt]
F
Fabio Busatto 已提交
359 360 361

production:
  <<: *production_template
A
Alessio Caiazza 已提交
362 363 364 365
  only:
    refs:
      - master
    kubernetes: active
F
Fabio Busatto 已提交
366 367 368
  except:
    variables:
      - $STAGING_ENABLED
O
Olivier Gonzalez 已提交
369
      - $CANARY_ENABLED
F
Fabio Busatto 已提交
370 371 372 373 374
      - $INCREMENTAL_ROLLOUT_ENABLED

production_manual:
  <<: *production_template
  when: manual
F
Fabio Busatto 已提交
375
  allow_failure: false
F
Fabio Busatto 已提交
376 377 378 379 380 381
  only:
    refs:
      - master
    kubernetes: active
    variables:
      - $STAGING_ENABLED
382
      - $CANARY_ENABLED
F
Fabio Busatto 已提交
383 384 385 386 387 388 389 390 391 392 393 394 395
  except:
    variables:
      - $INCREMENTAL_ROLLOUT_ENABLED

# This job implements incremental rollout on for every push to `master`.

.rollout: &rollout_template
  stage: production
  script:
    - check_kube_domain
    - install_dependencies
    - download_chart
    - ensure_namespace
T
Thong Kuah 已提交
396
    - initialize_tiller
F
Fabio Busatto 已提交
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
    - create_secret
    - deploy rollout $ROLLOUT_PERCENTAGE
    - scale stable $((100-ROLLOUT_PERCENTAGE))
    - delete canary
    - persist_environment_url
  environment:
    name: production
    url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
  artifacts:
    paths: [environment_url.txt]

rollout 10%:
  <<: *rollout_template
  variables:
    ROLLOUT_PERCENTAGE: 10
F
Fabio Busatto 已提交
412
  when: manual
F
Fabio Busatto 已提交
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
  only:
    refs:
      - master
    kubernetes: active
    variables:
      - $INCREMENTAL_ROLLOUT_ENABLED

rollout 25%:
  <<: *rollout_template
  variables:
    ROLLOUT_PERCENTAGE: 25
  when: manual
  only:
    refs:
      - master
    kubernetes: active
    variables:
      - $INCREMENTAL_ROLLOUT_ENABLED

rollout 50%:
  <<: *rollout_template
  variables:
    ROLLOUT_PERCENTAGE: 50
  when: manual
  only:
    refs:
      - master
    kubernetes: active
    variables:
      - $INCREMENTAL_ROLLOUT_ENABLED

rollout 100%:
  <<: *production_template
  when: manual
F
Fabio Busatto 已提交
447
  allow_failure: false
F
Fabio Busatto 已提交
448 449 450 451 452 453
  only:
    refs:
      - master
    kubernetes: active
    variables:
      - $INCREMENTAL_ROLLOUT_ENABLED
A
Alessio Caiazza 已提交
454 455 456 457 458 459 460 461 462 463 464 465

# ---------------------------------------------------------------------------

.auto_devops: &auto_devops |
  # Auto DevOps variables and functions
  [[ "$TRACE" ]] && set -x
  auto_database_url=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${CI_ENVIRONMENT_SLUG}-postgres:5432/${POSTGRES_DB}
  export DATABASE_URL=${DATABASE_URL-$auto_database_url}
  export CI_APPLICATION_REPOSITORY=$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
  export CI_APPLICATION_TAG=$CI_COMMIT_SHA
  export CI_CONTAINER_NAME=ci_job_build_${CI_JOB_ID}
  export TILLER_NAMESPACE=$KUBE_NAMESPACE
466 467
  # Extract "MAJOR.MINOR" from CI_SERVER_VERSION and generate "MAJOR-MINOR-stable" for Security Products
  export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
468

469
  function registry_login() {
470 471 472 473 474
    if [[ -n "$CI_REGISTRY_USER" ]]; then
      echo "Logging to GitLab Container Registry with CI credentials..."
      docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
      echo ""
    fi
475 476 477 478
  }

  function container_scanning() {
    registry_login
479

L
Luke Bennett 已提交
480
    docker run -d --name db arminc/clair-db:latest
F
Fabio Busatto 已提交
481
    docker run -p 6060:6060 --link db:postgres -d --name clair --restart on-failure arminc/clair-local-scan:v2.0.1
L
Luke Bennett 已提交
482 483
    apk add -U wget ca-certificates
    docker pull ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG}
484 485
    wget https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64
    mv clair-scanner_linux_amd64 clair-scanner
L
Luke Bennett 已提交
486 487
    chmod +x clair-scanner
    touch clair-whitelist.yml
488 489 490
    retries=0
    echo "Waiting for clair daemon to start"
    while( ! wget -T 10 -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; echo -n "." ; if [ $retries -eq 10 ] ; then echo " Timeout, aborting." ; exit 1 ; fi ; retries=$(($retries+1)) ; done
491
    ./clair-scanner -c http://docker:6060 --ip $(hostname -i) -r gl-container-scanning-report.json -l clair.log -w clair-whitelist.yml ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG} || true
L
Luke Bennett 已提交
492
  }
A
Alessio Caiazza 已提交
493

494
  function code_quality() {
495
    docker run --env SOURCE_CODE="$PWD" \
J
James Lopez 已提交
496 497
               --volume "$PWD":/code \
               --volume /var/run/docker.sock:/var/run/docker.sock \
498
               "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
A
Alessio Caiazza 已提交
499 500
  }

501
  function license_management() {
502 503 504 505 506
    # Extract "MAJOR.MINOR" from CI_SERVER_VERSION and generate "MAJOR-MINOR-stable"
    LICENSE_MANAGEMENT_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')

    docker run --volume "$PWD:/code" \
                                    "registry.gitlab.com/gitlab-org/security-products/license-management:$LICENSE_MANAGEMENT_VERSION" analyze /code
507 508
  }

509 510 511
  function sast() {
    case "$CI_SERVER_VERSION" in
      *-ee)
512

513 514 515 516 517 518 519 520
        # Deprecation notice for CONFIDENCE_LEVEL variable
        if [ -z "$SAST_CONFIDENCE_LEVEL" -a "$CONFIDENCE_LEVEL" ]; then
          SAST_CONFIDENCE_LEVEL="$CONFIDENCE_LEVEL"
          echo "WARNING: CONFIDENCE_LEVEL is deprecated and MUST be replaced with SAST_CONFIDENCE_LEVEL"
        fi

        docker run --env SAST_CONFIDENCE_LEVEL="${SAST_CONFIDENCE_LEVEL:-3}" \
                   --volume "$PWD:/code" \
521
                   --volume /var/run/docker.sock:/var/run/docker.sock \
522
                   "registry.gitlab.com/gitlab-org/security-products/sast:$SP_VERSION" /app/bin/run /code
523 524 525 526 527 528 529
        ;;
      *)
        echo "GitLab EE is required"
        ;;
    esac
  }

530 531 532 533 534 535 536 537 538 539 540 541 542 543
  function dependency_scanning() {
    case "$CI_SERVER_VERSION" in
      *-ee)
        docker run --env DEP_SCAN_DISABLE_REMOTE_CHECKS="${DEP_SCAN_DISABLE_REMOTE_CHECKS:-false}" \
                   --volume "$PWD:/code" \
                   --volume /var/run/docker.sock:/var/run/docker.sock \
                   "registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$SP_VERSION" /code
        ;;
      *)
        echo "GitLab EE is required"
        ;;
    esac
  }

F
Fabio Busatto 已提交
544 545 546
  function get_replicas() {
    track="${1:-stable}"
    percentage="${2:-100}"
A
Alessio Caiazza 已提交
547 548 549 550

    env_track=$( echo $track | tr -s  '[:lower:]'  '[:upper:]' )
    env_slug=$( echo ${CI_ENVIRONMENT_SLUG//-/_} | tr -s  '[:lower:]'  '[:upper:]' )

F
Fabio Busatto 已提交
551
    if [[ "$track" == "stable" ]] || [[ "$track" == "rollout" ]]; then
A
Alessio Caiazza 已提交
552 553
      # for stable track get number of replicas from `PRODUCTION_REPLICAS`
      eval new_replicas=\$${env_slug}_REPLICAS
554 555 556
      if [[ -z "$new_replicas" ]]; then
        new_replicas=$REPLICAS
      fi
A
Alessio Caiazza 已提交
557 558 559
    else
      # for all tracks get number of replicas from `CANARY_PRODUCTION_REPLICAS`
      eval new_replicas=\$${env_track}_${env_slug}_REPLICAS
560 561 562
      if [[ -z "$new_replicas" ]]; then
        eval new_replicas=\${env_track}_REPLICAS
      fi
A
Alessio Caiazza 已提交
563
    fi
F
Fabio Busatto 已提交
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590

    replicas="${new_replicas:-1}"
    replicas="$(($replicas * $percentage / 100))"

    # always return at least one replicas
    if [[ $replicas -gt 0 ]]; then
      echo "$replicas"
    else
      echo 1
    fi
  }

  function deploy() {
    track="${1-stable}"
    percentage="${2:-100}"
    name="$CI_ENVIRONMENT_SLUG"

    replicas="1"
    service_enabled="true"
    postgres_enabled="$POSTGRES_ENABLED"

    # if track is different than stable,
    # re-use all attached resources
    if [[ "$track" != "stable" ]]; then
      name="$name-$track"
      service_enabled="false"
      postgres_enabled="false"
A
Alessio Caiazza 已提交
591 592
    fi

F
Fabio Busatto 已提交
593 594
    replicas=$(get_replicas "$track" "$percentage")

595 596 597 598 599 600
    if [[ "$CI_PROJECT_VISIBILITY" != "public" ]]; then
      secret_name='gitlab-registry'
    else
      secret_name=''
    fi

601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653
    if [[ -n "$DB_INITIALIZE" && -z "$(helm ls -q "^$name$")" ]]; then
      helm upgrade --install \
        --wait \
        --set service.enabled="$service_enabled" \
        --set releaseOverride="$CI_ENVIRONMENT_SLUG" \
        --set image.repository="$CI_APPLICATION_REPOSITORY" \
        --set image.tag="$CI_APPLICATION_TAG" \
        --set image.pullPolicy=IfNotPresent \
        --set image.secrets[0].name="$secret_name" \
        --set application.track="$track" \
        --set application.database_url="$DATABASE_URL" \
        --set service.url="$CI_ENVIRONMENT_URL" \
        --set replicaCount="$replicas" \
        --set postgresql.enabled="$postgres_enabled" \
        --set postgresql.nameOverride="postgres" \
        --set postgresql.postgresUser="$POSTGRES_USER" \
        --set postgresql.postgresPassword="$POSTGRES_PASSWORD" \
        --set postgresql.postgresDatabase="$POSTGRES_DB" \
        --set application.initializeCommand="$DB_INITIALIZE" \
        --namespace="$KUBE_NAMESPACE" \
        "$name" \
        chart/

      helm upgrade --reuse-values \
        --wait \
        --set application.initializeCommand="" \
        --set application.migrateCommand="$DB_MIGRATE" \
        --namespace="$KUBE_NAMESPACE" \
        "$name" \
        chart/
    else
      helm upgrade --install \
        --wait \
        --set service.enabled="$service_enabled" \
        --set releaseOverride="$CI_ENVIRONMENT_SLUG" \
        --set image.repository="$CI_APPLICATION_REPOSITORY" \
        --set image.tag="$CI_APPLICATION_TAG" \
        --set image.pullPolicy=IfNotPresent \
        --set image.secrets[0].name="$secret_name" \
        --set application.track="$track" \
        --set application.database_url="$DATABASE_URL" \
        --set service.url="$CI_ENVIRONMENT_URL" \
        --set replicaCount="$replicas" \
        --set postgresql.enabled="$postgres_enabled" \
        --set postgresql.nameOverride="postgres" \
        --set postgresql.postgresUser="$POSTGRES_USER" \
        --set postgresql.postgresPassword="$POSTGRES_PASSWORD" \
        --set postgresql.postgresDatabase="$POSTGRES_DB" \
        --set application.migrateCommand="$DB_MIGRATE" \
        --namespace="$KUBE_NAMESPACE" \
        "$name" \
        chart/
    fi
654 655

    kubectl rollout status -n "$KUBE_NAMESPACE" -w "deployment/$name"
A
Alessio Caiazza 已提交
656 657
  }

F
Fabio Busatto 已提交
658 659 660 661 662 663 664 665 666 667 668
  function scale() {
    track="${1-stable}"
    percentage="${2-100}"
    name="$CI_ENVIRONMENT_SLUG"

    if [[ "$track" != "stable" ]]; then
      name="$name-$track"
    fi

    replicas=$(get_replicas "$track" "$percentage")

F
Fabio Busatto 已提交
669 670 671 672 673 674 675 676
    if [[ -n "$(helm ls -q "^$name$")" ]]; then
      helm upgrade --reuse-values \
        --wait \
        --set replicaCount="$replicas" \
        --namespace="$KUBE_NAMESPACE" \
        "$name" \
        chart/
    fi
F
Fabio Busatto 已提交
677 678
  }

A
Alessio Caiazza 已提交
679 680
  function install_dependencies() {
    apk add -U openssl curl tar gzip bash ca-certificates git
681 682
    curl -L -o /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub
    curl -L -O https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.28-r0/glibc-2.28-r0.apk
683 684
    apk add glibc-2.28-r0.apk
    rm glibc-2.28-r0.apk
A
Alessio Caiazza 已提交
685

686
    curl "https://kubernetes-helm.storage.googleapis.com/helm-v${HELM_VERSION}-linux-amd64.tar.gz" | tar zx
A
Alessio Caiazza 已提交
687
    mv linux-amd64/helm /usr/bin/
T
Thong Kuah 已提交
688
    mv linux-amd64/tiller /usr/bin/
A
Alessio Caiazza 已提交
689
    helm version --client
T
Thong Kuah 已提交
690 691 692 693
    tiller -version

    helm init --client-only
    helm plugin install https://github.com/adamreese/helm-local
A
Alessio Caiazza 已提交
694

695
    curl -L -o /usr/bin/kubectl "https://storage.googleapis.com/kubernetes-release/release/v${KUBERNETES_VERSION}/bin/linux/amd64/kubectl"
A
Alessio Caiazza 已提交
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
    chmod +x /usr/bin/kubectl
    kubectl version --client
  }

  function setup_docker() {
    if ! docker info &>/dev/null; then
      if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then
        export DOCKER_HOST='tcp://localhost:2375'
      fi
    fi
  }

  function setup_test_db() {
    if [ -z ${KUBERNETES_PORT+x} ]; then
      DB_HOST=postgres
    else
      DB_HOST=localhost
    fi
    export DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${DB_HOST}:5432/${POSTGRES_DB}"
  }

  function download_chart() {
    if [[ ! -d chart ]]; then
      auto_chart=${AUTO_DEVOPS_CHART:-gitlab/auto-deploy-app}
      auto_chart_name=$(basename $auto_chart)
      auto_chart_name=${auto_chart_name%.tgz}
722
      auto_chart_name=${auto_chart_name%.tar.gz}
A
Alessio Caiazza 已提交
723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
    else
      auto_chart="chart"
      auto_chart_name="chart"
    fi

    helm init --client-only
    helm repo add gitlab https://charts.gitlab.io
    if [[ ! -d "$auto_chart" ]]; then
      helm fetch ${auto_chart} --untar
    fi
    if [ "$auto_chart_name" != "chart" ]; then
      mv ${auto_chart_name} chart
    fi

    helm dependency update chart/
    helm dependency build chart/
  }

  function ensure_namespace() {
    kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE"
  }

  function check_kube_domain() {
    if [ -z ${AUTO_DEVOPS_DOMAIN+x} ]; then
A
Alessio Caiazza 已提交
747
      echo "In order to deploy or use Review Apps, AUTO_DEVOPS_DOMAIN variable must be set"
O
Olivier Gonzalez 已提交
748
      echo "You can do it in Auto DevOps project settings or defining a variable at group or project level"
A
Alessio Caiazza 已提交
749
      echo "You can also manually add it in .gitlab-ci.yml"
A
Alessio Caiazza 已提交
750 751 752 753 754 755 756
      false
    else
      true
    fi
  }

  function build() {
757
    registry_login
758

A
Alessio Caiazza 已提交
759 760
    if [[ -f Dockerfile ]]; then
      echo "Building Dockerfile-based application..."
761 762 763 764 765 766 767 768 769 770
      docker build \
        --build-arg HTTP_PROXY="$HTTP_PROXY" \
        --build-arg http_proxy="$http_proxy" \
        --build-arg HTTPS_PROXY="$HTTPS_PROXY" \
        --build-arg https_proxy="$https_proxy" \
        --build-arg FTP_PROXY="$FTP_PROXY" \
        --build-arg ftp_proxy="$ftp_proxy" \
        --build-arg NO_PROXY="$NO_PROXY" \
        --build-arg no_proxy="$no_proxy" \
        -t "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" .
A
Alessio Caiazza 已提交
771 772
    else
      echo "Building Heroku-based application using gliderlabs/herokuish docker image..."
773 774 775 776 777 778 779 780 781 782 783
      docker run -i \
        -e BUILDPACK_URL \
        -e HTTP_PROXY \
        -e http_proxy \
        -e HTTPS_PROXY \
        -e https_proxy \
        -e FTP_PROXY \
        -e ftp_proxy \
        -e NO_PROXY \
        -e no_proxy \
        --name="$CI_CONTAINER_NAME" -v "$(pwd):/tmp/app:ro" gliderlabs/herokuish /bin/herokuish buildpack build
A
Alessio Caiazza 已提交
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799
      docker commit "$CI_CONTAINER_NAME" "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG"
      docker rm "$CI_CONTAINER_NAME" >/dev/null
      echo ""

      echo "Configuring $CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG docker image..."
      docker create --expose 5000 --env PORT=5000 --name="$CI_CONTAINER_NAME" "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" /bin/herokuish procfile start web
      docker commit "$CI_CONTAINER_NAME" "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG"
      docker rm "$CI_CONTAINER_NAME" >/dev/null
      echo ""
    fi

    echo "Pushing to GitLab Container Registry..."
    docker push "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG"
    echo ""
  }

T
Thong Kuah 已提交
800
  function initialize_tiller() {
A
Alessio Caiazza 已提交
801
    echo "Checking Tiller..."
T
Thong Kuah 已提交
802 803 804 805 806

    helm local start
    helm local status
    export HELM_HOST=":44134"

A
Alessio Caiazza 已提交
807 808 809 810 811 812 813 814
    if ! helm version --debug; then
      echo "Failed to init Tiller."
      return 1
    fi
    echo ""
  }

  function create_secret() {
815
    echo "Create secret..."
816 817 818
    if [[ "$CI_PROJECT_VISIBILITY" == "public" ]]; then
      return
    fi
819

A
Alessio Caiazza 已提交
820 821 822
    kubectl create secret -n "$KUBE_NAMESPACE" \
      docker-registry gitlab-registry \
      --docker-server="$CI_REGISTRY" \
F
Fabio Busatto 已提交
823 824
      --docker-username="${CI_DEPLOY_USER:-$CI_REGISTRY_USER}" \
      --docker-password="${CI_DEPLOY_PASSWORD:-$CI_REGISTRY_PASSWORD}" \
A
Alessio Caiazza 已提交
825 826 827
      --docker-email="$GITLAB_USER_EMAIL" \
      -o yaml --dry-run | kubectl replace -n "$KUBE_NAMESPACE" --force -f -
  }
828

829 830 831 832 833 834 835 836
  function dast() {
    export CI_ENVIRONMENT_URL=$(cat environment_url.txt)

    mkdir /zap/wrk/
    /zap/zap-baseline.py -J gl-dast-report.json -t "$CI_ENVIRONMENT_URL" || true
    cp /zap/wrk/gl-dast-report.json .
  }

J
Joshua Lambert 已提交
837 838
  function performance() {
    export CI_ENVIRONMENT_URL=$(cat environment_url.txt)
839

J
Joshua Lambert 已提交
840
    mkdir gitlab-exporter
841
    wget -O gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/10-5/index.js
842

J
Joshua Lambert 已提交
843
    mkdir sitespeed-results
844

J
Joshua Lambert 已提交
845 846 847
    if [ -f .gitlab-urls.txt ]
    then
      sed -i -e 's@^@'"$CI_ENVIRONMENT_URL"'@' .gitlab-urls.txt
848
      docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:6.3.1 --plugins.add ./gitlab-exporter --outputFolder sitespeed-results .gitlab-urls.txt
J
Joshua Lambert 已提交
849
    else
850
      docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:6.3.1 --plugins.add ./gitlab-exporter --outputFolder sitespeed-results "$CI_ENVIRONMENT_URL"
J
Joshua Lambert 已提交
851
    fi
852

J
Joshua Lambert 已提交
853 854
    mv sitespeed-results/data/performance.json performance.json
  }
855

J
Joshua Lambert 已提交
856 857 858
  function persist_environment_url() {
      echo $CI_ENVIRONMENT_URL > environment_url.txt
  }
A
Alessio Caiazza 已提交
859 860 861 862 863 864 865 866 867

  function delete() {
    track="${1-stable}"
    name="$CI_ENVIRONMENT_SLUG"

    if [[ "$track" != "stable" ]]; then
      name="$name-$track"
    fi

868
    if [[ -n "$(helm ls -q "^$name$")" ]]; then
869
      helm delete --purge "$name"
870
    fi
A
Alessio Caiazza 已提交
871 872 873 874
  }

before_script:
  - *auto_devops