Auto-DevOps.gitlab-ci.yml 24.7 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
# Continuous deployment to production is enabled by default.
28 29 30
# If you want to deploy to staging first, set STAGING_ENABLED environment variable.
# If you want to enable incremental rollout, either manual or time based,
# set INCREMENTAL_ROLLOUT_TYPE environment variable to "manual" or "timed".
O
Olivier Gonzalez 已提交
31
# If you want to use canary deployments, set CANARY_ENABLED environment variable.
A
Alessio Caiazza 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
#
# 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

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

55 56
  DOCKER_DRIVER: overlay2

A
Alessio Caiazza 已提交
57 58 59 60
stages:
  - build
  - test
  - review
61
  - dast
A
Alessio Caiazza 已提交
62 63 64
  - staging
  - canary
  - production
65 66 67 68
  - incremental rollout 10%
  - incremental rollout 25%
  - incremental rollout 50%
  - incremental rollout 100%
J
Joshua Lambert 已提交
69
  - performance
A
Alessio Caiazza 已提交
70 71 72 73
  - cleanup

build:
  stage: build
74
  image: docker:stable-git
A
Alessio Caiazza 已提交
75
  services:
76
  - docker:stable-dind
A
Alessio Caiazza 已提交
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
  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 已提交
96 97 98
  except:
    variables:
      - $TEST_DISABLED
A
Alessio Caiazza 已提交
99

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

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

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

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

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

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

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

A
Alessio Caiazza 已提交
240 241 242 243 244 245 246
review:
  stage: review
  script:
    - check_kube_domain
    - install_dependencies
    - download_chart
    - ensure_namespace
T
Thong Kuah 已提交
247
    - initialize_tiller
A
Alessio Caiazza 已提交
248 249
    - create_secret
    - deploy
J
Joshua Lambert 已提交
250
    - persist_environment_url
A
Alessio Caiazza 已提交
251 252 253 254
  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 已提交
255 256
  artifacts:
    paths: [environment_url.txt]
A
Alessio Caiazza 已提交
257 258 259 260 261
  only:
    refs:
      - branches
    kubernetes: active
  except:
O
Olivier Gonzalez 已提交
262 263 264 265
    refs:
      - master
    variables:
      - $REVIEW_DISABLED
A
Alessio Caiazza 已提交
266 267 268 269 270 271 272

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

# 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
      - $INCREMENTAL_ROLLOUT_ENABLED
371
      - $INCREMENTAL_ROLLOUT_MODE
F
Fabio Busatto 已提交
372 373 374 375

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

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

.rollout: &rollout_template
  script:
    - check_kube_domain
    - install_dependencies
    - download_chart
    - ensure_namespace
T
Thong Kuah 已提交
397
    - initialize_tiller
F
Fabio Busatto 已提交
398 399 400 401 402 403 404 405 406 407 408
    - 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]

409
.manual_rollout_template: &manual_rollout_template
F
Fabio Busatto 已提交
410
  <<: *rollout_template
411
  stage: production
F
Fabio Busatto 已提交
412
  when: manual
413
  # This selectors are backward compatible mode with $INCREMENTAL_ROLLOUT_ENABLED (before 11.4)
F
Fabio Busatto 已提交
414 415 416 417 418
  only:
    refs:
      - master
    kubernetes: active
    variables:
419
      - $INCREMENTAL_ROLLOUT_MODE == "manual"
F
Fabio Busatto 已提交
420
      - $INCREMENTAL_ROLLOUT_ENABLED
421 422 423
  except:
    variables:
      - $INCREMENTAL_ROLLOUT_MODE == "timed"
F
Fabio Busatto 已提交
424

425
.timed_rollout_template: &timed_rollout_template
F
Fabio Busatto 已提交
426
  <<: *rollout_template
427 428
  when: delayed
  start_in: 5 minutes
F
Fabio Busatto 已提交
429 430 431 432 433
  only:
    refs:
      - master
    kubernetes: active
    variables:
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469
      - $INCREMENTAL_ROLLOUT_MODE == "timed"

timed rollout 10%:
  <<: *timed_rollout_template
  stage: incremental rollout 10%
  variables:
    ROLLOUT_PERCENTAGE: 10

timed rollout 25%:
  <<: *timed_rollout_template
  stage: incremental rollout 25%
  variables:
    ROLLOUT_PERCENTAGE: 25

timed rollout 50%:
  <<: *timed_rollout_template
  stage: incremental rollout 50%
  variables:
    ROLLOUT_PERCENTAGE: 50

timed rollout 100%:
  <<: *timed_rollout_template
  <<: *production_template
  stage: incremental rollout 100%
  variables:
    ROLLOUT_PERCENTAGE: 100

rollout 10%:
  <<: *manual_rollout_template
  variables:
    ROLLOUT_PERCENTAGE: 10

rollout 25%:
  <<: *manual_rollout_template
  variables:
    ROLLOUT_PERCENTAGE: 25
F
Fabio Busatto 已提交
470 471

rollout 50%:
472
  <<: *manual_rollout_template
F
Fabio Busatto 已提交
473 474 475 476
  variables:
    ROLLOUT_PERCENTAGE: 50

rollout 100%:
477
  <<: *manual_rollout_template
F
Fabio Busatto 已提交
478
  <<: *production_template
F
Fabio Busatto 已提交
479
  allow_failure: false
A
Alessio Caiazza 已提交
480 481 482 483 484 485 486 487 488 489 490 491

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

.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
492 493
  # 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/')
494

495
  function registry_login() {
496 497 498 499 500
    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
501 502 503 504
  }

  function container_scanning() {
    registry_login
505

L
Luke Bennett 已提交
506
    docker run -d --name db arminc/clair-db:latest
F
Fabio Busatto 已提交
507
    docker run -p 6060:6060 --link db:postgres -d --name clair --restart on-failure arminc/clair-local-scan:v2.0.1
L
Luke Bennett 已提交
508 509
    apk add -U wget ca-certificates
    docker pull ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG}
510 511
    wget https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64
    mv clair-scanner_linux_amd64 clair-scanner
L
Luke Bennett 已提交
512 513
    chmod +x clair-scanner
    touch clair-whitelist.yml
514 515 516
    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
517
    ./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 已提交
518
  }
A
Alessio Caiazza 已提交
519

520
  function code_quality() {
521
    docker run --env SOURCE_CODE="$PWD" \
J
James Lopez 已提交
522 523
               --volume "$PWD":/code \
               --volume /var/run/docker.sock:/var/run/docker.sock \
524
               "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
A
Alessio Caiazza 已提交
525 526
  }

527
  function license_management() {
528 529 530 531 532
    # 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
533 534
  }

535 536 537
  function sast() {
    case "$CI_SERVER_VERSION" in
      *-ee)
538

539 540 541 542 543 544 545 546
        # 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" \
547
                   --volume /var/run/docker.sock:/var/run/docker.sock \
548
                   "registry.gitlab.com/gitlab-org/security-products/sast:$SP_VERSION" /app/bin/run /code
549 550 551 552 553 554 555
        ;;
      *)
        echo "GitLab EE is required"
        ;;
    esac
  }

556 557 558 559 560 561 562 563 564 565 566 567 568 569
  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 已提交
570 571 572
  function get_replicas() {
    track="${1:-stable}"
    percentage="${2:-100}"
A
Alessio Caiazza 已提交
573 574 575 576

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

F
Fabio Busatto 已提交
577
    if [[ "$track" == "stable" ]] || [[ "$track" == "rollout" ]]; then
A
Alessio Caiazza 已提交
578 579
      # for stable track get number of replicas from `PRODUCTION_REPLICAS`
      eval new_replicas=\$${env_slug}_REPLICAS
580 581 582
      if [[ -z "$new_replicas" ]]; then
        new_replicas=$REPLICAS
      fi
A
Alessio Caiazza 已提交
583 584 585
    else
      # for all tracks get number of replicas from `CANARY_PRODUCTION_REPLICAS`
      eval new_replicas=\$${env_track}_${env_slug}_REPLICAS
586 587 588
      if [[ -z "$new_replicas" ]]; then
        eval new_replicas=\${env_track}_REPLICAS
      fi
A
Alessio Caiazza 已提交
589
    fi
F
Fabio Busatto 已提交
590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616

    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 已提交
617 618
    fi

F
Fabio Busatto 已提交
619 620
    replicas=$(get_replicas "$track" "$percentage")

621 622 623 624 625 626
    if [[ "$CI_PROJECT_VISIBILITY" != "public" ]]; then
      secret_name='gitlab-registry'
    else
      secret_name=''
    fi

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 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
    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
680 681

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

F
Fabio Busatto 已提交
684 685 686 687 688 689 690 691 692 693 694
  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 已提交
695 696 697 698 699 700 701 702
    if [[ -n "$(helm ls -q "^$name$")" ]]; then
      helm upgrade --reuse-values \
        --wait \
        --set replicaCount="$replicas" \
        --namespace="$KUBE_NAMESPACE" \
        "$name" \
        chart/
    fi
F
Fabio Busatto 已提交
703 704
  }

A
Alessio Caiazza 已提交
705 706
  function install_dependencies() {
    apk add -U openssl curl tar gzip bash ca-certificates git
707 708
    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
709 710
    apk add glibc-2.28-r0.apk
    rm glibc-2.28-r0.apk
A
Alessio Caiazza 已提交
711

712
    curl "https://kubernetes-helm.storage.googleapis.com/helm-v${HELM_VERSION}-linux-amd64.tar.gz" | tar zx
A
Alessio Caiazza 已提交
713
    mv linux-amd64/helm /usr/bin/
T
Thong Kuah 已提交
714
    mv linux-amd64/tiller /usr/bin/
A
Alessio Caiazza 已提交
715
    helm version --client
T
Thong Kuah 已提交
716 717
    tiller -version

718
    curl -L -o /usr/bin/kubectl "https://storage.googleapis.com/kubernetes-release/release/v${KUBERNETES_VERSION}/bin/linux/amd64/kubectl"
A
Alessio Caiazza 已提交
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
    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}
745
      auto_chart_name=${auto_chart_name%.tar.gz}
A
Alessio Caiazza 已提交
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
    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 已提交
770
      echo "In order to deploy or use Review Apps, AUTO_DEVOPS_DOMAIN variable must be set"
O
Olivier Gonzalez 已提交
771
      echo "You can do it in Auto DevOps project settings or defining a variable at group or project level"
A
Alessio Caiazza 已提交
772
      echo "You can also manually add it in .gitlab-ci.yml"
A
Alessio Caiazza 已提交
773 774 775 776 777 778 779
      false
    else
      true
    fi
  }

  function build() {
780
    registry_login
781

A
Alessio Caiazza 已提交
782 783
    if [[ -f Dockerfile ]]; then
      echo "Building Dockerfile-based application..."
784 785 786 787 788 789 790 791 792 793
      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 已提交
794 795
    else
      echo "Building Heroku-based application using gliderlabs/herokuish docker image..."
796 797 798 799 800 801 802 803 804 805 806
      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 已提交
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822
      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 已提交
823
  function initialize_tiller() {
A
Alessio Caiazza 已提交
824
    echo "Checking Tiller..."
T
Thong Kuah 已提交
825

826
    export HELM_HOST="localhost:44134"
827
    tiller -listen ${HELM_HOST} -alsologtostderr > /dev/null 2>&1 &
T
Thong Kuah 已提交
828
    echo "Tiller is listening on ${HELM_HOST}"
T
Thong Kuah 已提交
829

A
Alessio Caiazza 已提交
830 831 832 833 834 835 836 837
    if ! helm version --debug; then
      echo "Failed to init Tiller."
      return 1
    fi
    echo ""
  }

  function create_secret() {
838
    echo "Create secret..."
839 840 841
    if [[ "$CI_PROJECT_VISIBILITY" == "public" ]]; then
      return
    fi
842

A
Alessio Caiazza 已提交
843 844 845
    kubectl create secret -n "$KUBE_NAMESPACE" \
      docker-registry gitlab-registry \
      --docker-server="$CI_REGISTRY" \
F
Fabio Busatto 已提交
846 847
      --docker-username="${CI_DEPLOY_USER:-$CI_REGISTRY_USER}" \
      --docker-password="${CI_DEPLOY_PASSWORD:-$CI_REGISTRY_PASSWORD}" \
A
Alessio Caiazza 已提交
848 849 850
      --docker-email="$GITLAB_USER_EMAIL" \
      -o yaml --dry-run | kubectl replace -n "$KUBE_NAMESPACE" --force -f -
  }
851

852 853 854 855 856 857 858 859
  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 已提交
860 861
  function performance() {
    export CI_ENVIRONMENT_URL=$(cat environment_url.txt)
862

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

J
Joshua Lambert 已提交
866
    mkdir sitespeed-results
867

J
Joshua Lambert 已提交
868 869 870
    if [ -f .gitlab-urls.txt ]
    then
      sed -i -e 's@^@'"$CI_ENVIRONMENT_URL"'@' .gitlab-urls.txt
871
      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 已提交
872
    else
873
      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 已提交
874
    fi
875

J
Joshua Lambert 已提交
876 877
    mv sitespeed-results/data/performance.json performance.json
  }
878

J
Joshua Lambert 已提交
879 880 881
  function persist_environment_url() {
      echo $CI_ENVIRONMENT_URL > environment_url.txt
  }
A
Alessio Caiazza 已提交
882 883 884 885 886 887 888 889 890

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

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

891
    if [[ -n "$(helm ls -q "^$name$")" ]]; then
892
      helm delete --purge "$name"
893
    fi
A
Alessio Caiazza 已提交
894 895 896 897
  }

before_script:
  - *auto_devops