stages:
  - test
  - deploy_tags
  - deploy

variables:
  POSTGRES_PASSWORD: "postgres"
  POSTGRES_USER: "postgres"
  DATABASE_URL: "postgres"
  MIX_ENV: "test"
  DOCKER_TLS_CERTDIR: "/certs"
  DOCKER_HOST: tcp://docker:2376
  # fetch & clean the repo rather than completely cloning (faster)
  GIT_STRATEGY: fetch

# Test stage. Runs various tests and speculatively builds docker image in
#   parallel, in case the build passes.
.test_template: &test_template
  stage: test
  cache:
    key: $CI_JOB_NAME
    paths:
      - _build/
      - deps/
  services:
  - name: postgres:12
  script: script/cibuild

test:
  <<: *test_template
  image: "elixir:1.10.4-alpine"

test_1.11.4:
  <<: *test_template
  image: "elixir:1.11.4-alpine"

test_1.12.1:
  <<: *test_template
  image: "elixir:1.12.1-alpine"

credo:
  stage: test
  image: "elixir:1.12.1-alpine"
  cache:
    key: "test_1.12.1"
    paths:
      - _build/
      - deps/
  script:
    - mix local.hex --force
    - mix local.rebar --force
    - mix deps.get
    - mix credo --all

stylelint:
  stage: test
  image: "node:16"
  script:
    - cd apps/app/assets/
    - npx stylelint **/*.css

prettier:
  stage: test
  image: "node:16"
  script:
    - cd apps/app/assets/
    - npx prettier --check **/*.js

build_image_for_commit:
  stage: test
  image: "docker:20.10"
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
      when: on_success
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      changes:
        - Dockerfile
      when: on_success
  services:
    - name: docker:20.10-dind
  before_script:
    - apk add git
    - script/ci-docker-prebuild
  script:
    - script/ci-docker-build

# If tests pass, tag the commit and update package versions
deploy_to_tags:
  stage: deploy_tags
  needs: ['test', 'build_image_for_commit']
  image: "node:16"
  only:
    - master
  cache:
    key:
      files:
        - package-lock.json
        - package.json
    paths:
      - node_modules/
  script:
    - export GIT_AUTHOR_NAME=$GITLAB_USER_NAME
    - export GIT_AUTHOR_EMAIL=$GITLAB_USER_EMAIL
    - export GIT_COMMITTER_NAME=$GITLAB_USER_NAME
    - export GIT_COMMITTER_EMAIL=$GITLAB_USER_EMAIL
    - export GIT_BRANCH=$CI_COMMIT_REF_NAME
    - git config user.email $GITLAB_USER_EMAIL
    - git config user.name $GITLAB_USER_NAME
    - npm install --no-save
    - npx semantic-release --repository-url=$CI_REPOSITORY_URL
    - script/generate-build-version
  artifacts:
    reports:
      dotenv: build.env

# If the tests passed, we take the image for this SHA and tag it with the version
#   and latest, so we can signal that it is ready for prod
deploy_commit_image_to_tag:
  stage: deploy
  needs:
    - build_image_for_commit
    - job: deploy_to_tags
      artifacts: true
  only:
    - master
  image: "docker:19.03.12"
  services:
    - name: docker:19.03.12-dind
  variables:
    GIT_STRATEGY: none # this job does not need the project files, only docker
  parallel:
    matrix:
      - IMAGE_TYPE: ["", "-elixir-builder", "-asset-builder"]
  script:
    - echo "BUILD_VERSION is ${BUILD_VERSION}"
    - docker login "https://${CI_REGISTRY}" -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
    # Run the docker pull, but retry if it doesn't work at first because layers may be
    # still be loading to storage
    - for i in 1 2 3 4 5; do docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA$IMAGE_TYPE && break || sleep 15; done
    - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA$IMAGE_TYPE $CI_REGISTRY_IMAGE:$BUILD_VERSION$IMAGE_TYPE
    - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA$IMAGE_TYPE $CI_REGISTRY_IMAGE:latest$IMAGE_TYPE
    - docker push $CI_REGISTRY_IMAGE:$BUILD_VERSION$IMAGE_TYPE
    - docker push $CI_REGISTRY_IMAGE:latest$IMAGE_TYPE

.dependabot_gitlab: &dependabot_gitlab
  image:
    name: docker.io/andrcuns/dependabot-gitlab:0.4.3
    entrypoint: [""]
  variables:
    GIT_STRATEGY: none
    RAILS_ENV: production
    SETTINGS__STANDALONE: "true"
    SETTINGS__GITLAB_URL: $CI_SERVER_URL
    SETTINGS__GITLAB_ACCESS_TOKEN: $GITLAB_TOKEN
  before_script:
    - cd /home/dependabot/app
  script:
    - bundle exec rake "dependabot:update[$CI_PROJECT_PATH,$PACKAGE_MANAGER,$DIRECTORY]"
  only:
    - schedules

npm-release-tools:
  extends: .dependabot_gitlab
  variables:
    DIRECTORY: "/"
    PACKAGE_MANAGER: npm
  only:
    variables:
      - $PACKAGE_MANAGER_SET =~ /(\bnpm|yarn\b)/

npm-assets:
  extends: .dependabot_gitlab
  variables:
    DIRECTORY: "/apps/app/assets"
    PACKAGE_MANAGER: npm
  only:
    variables:
      - $PACKAGE_MANAGER_SET =~ /(\bnpm|yarn\b)/

mix-admin:
  extends: .dependabot_gitlab
  variables:
    DIRECTORY: "/apps/admin"
    PACKAGE_MANAGER: mix
  only:
    variables:
      - $PACKAGE_MANAGER_SET =~ /\bmix\b/

mix-app:
  extends: .dependabot_gitlab
  variables:
    DIRECTORY: "/apps/app"
    PACKAGE_MANAGER: mix
  only:
    variables:
      - $PACKAGE_MANAGER_SET =~ /\bmix\b/

mix-core:
  extends: .dependabot_gitlab
  variables:
    DIRECTORY: "/apps/core"
    PACKAGE_MANAGER: mix
  only:
    variables:
      - $PACKAGE_MANAGER_SET =~ /\bmix\b/

mix-content:
  extends: .dependabot_gitlab
  variables:
    DIRECTORY: "/apps/content"
    PACKAGE_MANAGER: mix
  only:
    variables:
      - $PACKAGE_MANAGER_SET =~ /\bmix\b/

docker:
  extends: .dependabot_gitlab
  variables:
    DIRECTORY: "/"
    PACKAGE_MANAGER: docker
  only:
    variables:
      - $PACKAGE_MANAGER_SET =~ /\bdocker\b/
