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
# 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,
T
Tripple Moon 已提交
30
# set INCREMENTAL_ROLLOUT_MODE 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.10.9
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
  image: 
    name: "registry.gitlab.com/gitlab-org/security-products/license-management:$CI_SERVER_VERSION_MAJOR-$CI_SERVER_VERSION_MINOR-stable"
    entrypoint: [""]
122 123 124 125 126
  allow_failure: true
  script:
    - license_management
  artifacts:
    paths: [gl-license-management-report.json]
127
  only:
128 129
    refs:
      - branches
130 131
    variables:
      - $GITLAB_FEATURES =~ /\blicense_management\b/
132 133 134 135
  except:
    variables:
      - $LICENSE_MANAGEMENT_DISABLED

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

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

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

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

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

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

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

# 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 已提交
292 293
# only manually promote to production, enable this job by setting
# STAGING_ENABLED.
A
Alessio Caiazza 已提交
294

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

O
Olivier Gonzalez 已提交
317 318 319
# 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 已提交
320

O
Olivier Gonzalez 已提交
321
canary:
A
Alessio Caiazza 已提交
322 323 324 325 326 327
  stage: canary
  script:
    - check_kube_domain
    - install_dependencies
    - download_chart
    - ensure_namespace
T
Thong Kuah 已提交
328
    - initialize_tiller
A
Alessio Caiazza 已提交
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
O
Olivier Gonzalez 已提交
338 339
    variables:
      - $CANARY_ENABLED
340 341 342
  except:
    variables:
      - $KUBECONFIG == null
A
Alessio Caiazza 已提交
343

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

production:
  <<: *production_template
A
Alessio Caiazza 已提交
365 366 367
  only:
    refs:
      - master
F
Fabio Busatto 已提交
368 369 370
  except:
    variables:
      - $STAGING_ENABLED
O
Olivier Gonzalez 已提交
371
      - $CANARY_ENABLED
F
Fabio Busatto 已提交
372
      - $INCREMENTAL_ROLLOUT_ENABLED
373
      - $INCREMENTAL_ROLLOUT_MODE
374
      - $KUBECONFIG == null
F
Fabio Busatto 已提交
375 376 377 378

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

# 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 已提交
400
    - initialize_tiller
F
Fabio Busatto 已提交
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]

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

428
.timed_rollout_template: &timed_rollout_template
F
Fabio Busatto 已提交
429
  <<: *rollout_template
430 431
  when: delayed
  start_in: 5 minutes
F
Fabio Busatto 已提交
432 433 434 435
  only:
    refs:
      - master
    variables:
436
      - $INCREMENTAL_ROLLOUT_MODE == "timed"
437 438 439
  except:
    variables:
      - $KUBECONFIG == null
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 470 471 472 473 474

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 已提交
475 476

rollout 50%:
477
  <<: *manual_rollout_template
F
Fabio Busatto 已提交
478 479 480 481
  variables:
    ROLLOUT_PERCENTAGE: 50

rollout 100%:
482
  <<: *manual_rollout_template
F
Fabio Busatto 已提交
483
  <<: *production_template
F
Fabio Busatto 已提交
484
  allow_failure: false
A
Alessio Caiazza 已提交
485 486 487 488 489 490 491 492 493 494 495 496

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

.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
497 498
  # 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/')
499

500
  function registry_login() {
501 502 503 504 505
    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
506 507 508 509
  }

  function container_scanning() {
    registry_login
510

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

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

532
  function license_management() {
533
    /run.sh analyze .
534 535
  }

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

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

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

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

F
Fabio Busatto 已提交
578
    if [[ "$track" == "stable" ]] || [[ "$track" == "rollout" ]]; then
A
Alessio Caiazza 已提交
579 580
      # for stable track get number of replicas from `PRODUCTION_REPLICAS`
      eval new_replicas=\$${env_slug}_REPLICAS
581 582 583
      if [[ -z "$new_replicas" ]]; then
        new_replicas=$REPLICAS
      fi
A
Alessio Caiazza 已提交
584 585 586
    else
      # for all tracks get number of replicas from `CANARY_PRODUCTION_REPLICAS`
      eval new_replicas=\$${env_track}_${env_slug}_REPLICAS
587 588 589
      if [[ -z "$new_replicas" ]]; then
        eval new_replicas=\${env_track}_REPLICAS
      fi
A
Alessio Caiazza 已提交
590
    fi
F
Fabio Busatto 已提交
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 617

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

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

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

628
    if [[ -n "$DB_INITIALIZE" && -z "$(helm ls -q "^$name$")" ]]; then
629
      echo "Deploying first release with database initialization..."
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
      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/

652
      echo "Deploying second release..."
653 654 655 656 657 658 659 660
      helm upgrade --reuse-values \
        --wait \
        --set application.initializeCommand="" \
        --set application.migrateCommand="$DB_MIGRATE" \
        --namespace="$KUBE_NAMESPACE" \
        "$name" \
        chart/
    else
661
      echo "Deploying new release..."
662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
      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
684 685

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

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

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

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

722
    curl -L -o /usr/bin/kubectl "https://storage.googleapis.com/kubernetes-release/release/v${KUBERNETES_VERSION}/bin/linux/amd64/kubectl"
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 747 748
    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}
749
      auto_chart_name=${auto_chart_name%.tar.gz}
A
Alessio Caiazza 已提交
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773
    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 已提交
774
      echo "In order to deploy or use Review Apps, AUTO_DEVOPS_DOMAIN variable must be set"
O
Olivier Gonzalez 已提交
775
      echo "You can do it in Auto DevOps project settings or defining a variable at group or project level"
A
Alessio Caiazza 已提交
776
      echo "You can also manually add it in .gitlab-ci.yml"
A
Alessio Caiazza 已提交
777 778 779 780 781 782 783
      false
    else
      true
    fi
  }

  function build() {
784
    registry_login
785

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

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

A
Alessio Caiazza 已提交
834 835 836 837 838 839 840 841
    if ! helm version --debug; then
      echo "Failed to init Tiller."
      return 1
    fi
    echo ""
  }

  function create_secret() {
842
    echo "Create secret..."
843 844 845
    if [[ "$CI_PROJECT_VISIBILITY" == "public" ]]; then
      return
    fi
846

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

856 857 858 859 860 861 862 863
  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 已提交
864 865
  function performance() {
    export CI_ENVIRONMENT_URL=$(cat environment_url.txt)
866

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

J
Joshua Lambert 已提交
870
    mkdir sitespeed-results
871

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

J
Joshua Lambert 已提交
880 881
    mv sitespeed-results/data/performance.json performance.json
  }
882

J
Joshua Lambert 已提交
883 884 885
  function persist_environment_url() {
      echo $CI_ENVIRONMENT_URL > environment_url.txt
  }
A
Alessio Caiazza 已提交
886 887 888 889 890 891 892 893 894

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

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

895
    if [[ -n "$(helm ls -q "^$name$")" ]]; then
896
      helm delete --purge "$name"
897
    fi
A
Alessio Caiazza 已提交
898 899 900 901
  }

before_script:
  - *auto_devops