stages:
  - test
  - upload
  - bump
  - publish
  - review
  - bake
  - deploy

before_script:
    ## Update submodules
  - git submodule sync --recursive
  - git submodule update --init --recursive
    ## Update repository
  - git fetch --prune origin
  - git checkout develop && git pull
  - git checkout master && git pull
  - git checkout production && git pull
  - if [[ -z ${CI_BUILD_TAG} ]]; then
  -         git checkout "${CI_BUILD_REF_NAME}" && git pull
  - else
  -         git checkout tags/"${CI_BUILD_REF_NAME}"
  - fi
    ## Ensure correct Node.js installed
  - source ~/.nvm/nvm.sh
  - required_node_version=$(cat package.json | jq -r '.engines.node' | grep -e [0-9].*$ -o)
  - echo $required_node_version
  - nvm install $required_node_version

units:
  stage: test
  except:
    - tags
  script:
    - export CI_BUILD_ENVIRONMENT=sandbox
    - . opskit/load-deployment-context.sh
      ## Install all dependencies
    - npm install
      ## Run tests and parse coverage
    - npm run lint
    - export CLIO_MONGO_URL=$TEST_MONGO_URL
#    - npm run cover
  artifacts:
    paths:
      - coverage/lcov-report/
  cache:
    key: $CI_BUILD_NAME
    paths:
      - node_modules/

.coverage report:
  stage: upload
  only:
    - develop
  script:
      ## Avoid uploading coverage on new version
    - if [[ ! -z $(git tag -l --points-at HEAD) ]] && [[ -z ${CI_BUILD_TAG} ]]; then exit 0; fi
      ## Login to vault server
    - export VAULT_TOKEN=$(vault write -field=token auth/approle/login role_id=${ROLE_ID})
      ## Retrieve service account credentials
    - vault read -format json secret/io-arisan-ci | jq '.data' > account.json
      ## Activate service account
    - gcloud auth activate-service-account --key-file account.json
      ## Prepare coverage report to be uploaded
    - cd coverage
    - mv lcov-report data-api
      ## Upload coverage report
    - gsutil -m cp -r data-api gs://coverage.arisan.io

version:
  stage: bump
  only:
    - develop
    - master
    - production
  script:
      ## Avoid version bump on new version
    - if [[ ! -z $(git tag -l --points-at HEAD) ]] && [[ -z ${CI_BUILD_TAG} ]]; then exit 0; fi
      ## Setup remote to push back
    - if [[ ! -z $(git remote -v | grep back-to-origin) ]]; then git remote remove back-to-origin; fi
    - git config --global push.default simple
    - git config --global --replace-all user.name \"${BACK_TO_ORIGIN_USERNAME}\"
    - git config --global user.email ${BACK_TO_ORIGIN_EMAIL}
    - git remote add back-to-origin ${BACK_TO_ORIGIN_URL}
      ## Calculate next version
    - . opskit/next-version.sh
      ## Avoid using any version prefix like 'v'
    - npm config set tag-version-prefix ''
      ## Bump, tag and commit next version
    - 'npm version ${NEXT_VERSION} -m "ver: %s"'
      ## Push the updated package.json back to repo
    - git push back-to-origin
      ## Push the new version tag back to repo
    - git push back-to-origin refs/tags/${NEXT_VERSION}

npm package:
  stage: publish
  only:
    - tags
  script:
    - npm install
    - packaged_name=$(node -e "console.log(require('./package.json').name)")
    - packaged_version=$(node -e "console.log(require('./package.json').version)")
    - if [[ -z $(npm info $packaged_name@$packaged_version) ]]; then
    -     npm publish
    - fi
  cache:
    key: $CI_BUILD_NAME
    paths:
      - node_modules/

alpha:
  stage: review
  only:
    - /alpha/
  except:
    - branches
  variables:
    CI_BUILD_ENVIRONMENT: 'sandbox'
  environment:
    name: 'sandbox'
  script:
      ## Load deployment context
    - . opskit/load-deployment-context.sh
      ## Use current commit revision as version
    - export VERSION=${CI_BUILD_TAG}
      ## Configure deployment variables
    - ./iac/configure-variables
      ## Create an iac tarball
    - tar -zcf iac.tar.gz iac
      ## Compose an appropriate instance name
    - instance_name='data-api'
      ## Check if review instance is already up
    - instance_count=$(gcloud compute instances list
              --filter="name=${instance_name}"
              --format='(name)' | tail -n -1 | wc -l)
      ## Create an instance if review instance is not already up
    - if [[ "${instance_count}" -lt "1" ]]; then
    -         gcloud compute instances create ${instance_name}
                  --machine-type=${DATA_API_MACHINE_TYPE}
                  --image-project=ubuntu-os-cloud
                  --image-family=ubuntu-1404-lts
                  --tags=http-server
    -         sleep 30
    - fi
      ## Cleanup staging area before installation
    - gcloud compute ssh ubuntu@${instance_name} --command "sudo rm -rf /tmp/*"
      ## Copy iac tarballs and setup script to instance
    - gcloud compute copy-files iac.tar.gz iac/setup ${instance_name}:/tmp/
      ## Run setup script
    - gcloud compute ssh ubuntu@${instance_name} --command "sudo /tmp/setup"

.bake_template: &apply_bake_template
  stage: bake
  except:
    - branches
  script:
      ## Load deployment context
    - . opskit/load-deployment-context.sh
    - export ACCOUNT_FILE='account.json'
    - export PACKER_TEMPLATE='iac/packer.json'
    - export TARGET_IMAGE_NAME=data-api-${CI_PIPELINE_ID}
    - export VERSION=$CI_BUILD_TAG
      ## Configure deployment variables
    - ./iac/configure-variables
      ## Create an iac tarball
    - tar -zcf iac.tar.gz iac
      ## Bake image
    - ./opskit/create-image
    - ./opskit/deprecate-old-images ${CI_PROJECT_NAME}

image on demo:
  <<: *apply_bake_template
  only:
    - /beta/
  variables:
    CI_BUILD_ENVIRONMENT: 'demo'

image on production:
  <<: *apply_bake_template
  only:
    - tags
  except:
    - /alpha/
    - /beta/
  variables:
    CI_BUILD_ENVIRONMENT: 'production'

.deploy_template: &apply_deploy_template
  stage: deploy
  script:
      ## Load deployment context
    - . opskit/load-deployment-context.sh
    - it_name=data-api-it-$CI_PIPELINE_ID
      ## Create instance template
    - existing_template=$(gcloud compute instance-templates list
          --filter="name=${it_name}"
          --format='value(name)')
    - if [[ -z $existing_template ]]; then
    -         gcloud compute instance-templates create $it_name
                  --machine-type "$DATA_API_MACHINE_TYPE"
                  --image data-api-$CI_PIPELINE_ID
                  --boot-disk-type pd-ssd
    - fi
      ## Update instance groups with newly created instance template
    - groups=$(gcloud compute instance-groups managed list
          --filter="name~^${CI_PROJECT_NAME}-ig-.*$"
          --format='csv[no-heading](name,zone)')
    - echo ${groups}
    - echo "${groups}"
    - while read -r group; do
    -         IFS=',' ig_desc=($group)
    -         ig_name=${ig_desc[0]}
    -         ig_zone=${ig_desc[1]}
              ## Set new instance template
    -         gcloud compute instance-groups managed set-instance-template $ig_name
                  --template=$it_name
                  --zone=$ig_zone
              ## Stop auto scaling for instance recreation
    -         set +e
    -         gcloud compute instance-groups managed stop-autoscaling $ig_name --zone=$ig_zone
    -         set -e
              ## Recreate instances to use latest template
    -         instances=$(gcloud compute instance-groups managed list-instances ${ig_name}
                  --zone=${ig_zone}
                  --format='value(instance)')
    -         echo ${instances}
    -         echo "${instances}"
    -         while read -r instance; do
    -                 echo "${instance}";
    -                 gcloud compute instance-groups managed recreate-instances $ig_name
                          --instances="${instance}"
                          --zone=$ig_zone
    -                 gcloud compute instance-groups managed wait-until-stable $ig_name
                          --zone=$ig_zone
    -         done <<< ${instances}
              ## Enable autoscaling after instance recreation
    -         gcloud compute instance-groups managed set-autoscaling $ig_name --zone=$ig_zone
                  --max-num-replicas=3
                  --min-num-replicas=1
                  --scale-based-on-cpu
                  --target-cpu-utilization=0.8
    - done <<< "${groups}"

demo:
  <<: *apply_deploy_template
  only:
    - /beta/
  except:
    - branches
  variables:
    CI_BUILD_ENVIRONMENT: 'demo'
    MODULE_NAME: $CI_PROJECT_NAME
  environment:
    name: demo

production:
  <<: *apply_deploy_template
  except:
    - branches
    - /alpha/
    - /beta/
  variables:
    CI_BUILD_ENVIRONMENT: 'production'
    MODULE_NAME: $CI_PROJECT_NAME
  environment:
    name: production
