image: docker:19.03.0

# disable TLS just for the docker daemon running locally, TLS is still used to deploy built images!
variables:
    DOCKER_TLS_CERTDIR: ""
    DOCKER_DRIVER: overlay2

services:
    - docker:19.03.0-dind

stages:
    - pica-ci-base
    - metabuild
    - build
    - static_tests
    - dynamic_tests
    - deployment

# build the base image used for all further steps : this is done only when pica-ci's Dockerfile is modified
pica-ci-base:
    stage: pica-ci-base
    before_script:
        - echo $REGISTRY_PROD_PASSWORD | docker login $REGISTRY_PROD -u $REGISTRY_PROD_USERNAME --password-stdin
    script:
        - docker build -f pica-ci-base/Dockerfile . -t $REGISTRY_PROD/pica-ci-base:latest
        - docker push $REGISTRY_PROD/pica-ci-base:latest
    after_script:
        - docker logout $REGISTRY_PROD
    tags: [build]
    only:
        changes:
            - "pica-ci-base/*"
        refs:
            - master
            - dev-ci
            - tx-services-p19-test
            - dev-sympa

# create a image based on pica-ci with only a few environment variables added (which Dockerfile has been modified...)
metabuid:
    stage: metabuild
    before_script:
        - echo $REGISTRY_PROD_PASSWORD | docker login $REGISTRY_PROD -u $REGISTRY_PROD_USERNAME --password-stdin
    script:
        - docker build -f pica-ci/Dockerfile . -t $REGISTRY/pica-ci:$CI_COMMIT_SHA
        - echo $REGISTRY_PASSWORD | docker login $REGISTRY -u $REGISTRY_USERNAME --password-stdin
        - docker push $REGISTRY/pica-ci:$CI_COMMIT_SHA
    after_script:
        - docker logout $REGISTRY
    tags: [build]
    only:
        changes:
            - "pica-dokuwiki/*"
            - "pica-etherpad/*"
            - "pica-tellform/*"
            - "pica-wekan/*"
            - "pica-sympa/*"
        refs:
            - master
            - dev-ci
            - tx-services-p19-test
            - dev-sympa

# build the container that was modified
build:
    stage: build
    image: $REGISTRY/pica-ci:$CI_COMMIT_SHA
    before_script:
        - echo $REGISTRY_PASSWORD | docker login $REGISTRY -u $REGISTRY_USERNAME --password-stdin
        - source /etc/profile.d/ci-variables
    script:
        - docker build -f $MODIFIED_IMAGE/Dockerfile $MODIFIED_IMAGE -t $REGISTRY/ci-builds/$MODIFIED_IMAGE:$CI_COMMIT_SHA
        - docker push $REGISTRY/ci-builds/$MODIFIED_IMAGE:$CI_COMMIT_SHA
    after_script:
        - docker logout $REGISTRY
    tags: [build]
    only:
        changes:
            - "pica-dokuwiki/*"
            - "pica-etherpad/*"
            - "pica-tellform/*"
            - "pica-wekan/*"
            - "pica-sympa/*"
        refs:
            - master
            - dev-ci
            - tx-services-p19-test
            - dev-sympa

# run CoreOS' Clair and make the CI failed if a critical vulnerability isn't in the whitelist
clair:
    stage: static_tests
    image: $REGISTRY/pica-ci:$CI_COMMIT_SHA
    before_script:
        - echo $REGISTRY_PASSWORD | docker login $REGISTRY -u $REGISTRY_USERNAME --password-stdin
        - docker pull $REGISTRY/ci-builds/$MODIFIED_IMAGE:$CI_COMMIT_SHA
        - docker logout $REGISTRY
        - source /etc/profile.d/ci-variables
    script:
        - docker run -d --name db arminc/clair-db:latest
        - docker run -p 6060:6060 -d --link db:postgres --name clair --restart on-failure arminc/clair-local-scan:latest
        - wget https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64
        - mv clair-scanner_linux_amd64 clair-scanner
        - chmod +x clair-scanner
        - while( ! wget -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; done
        - ./clair-scanner -c http://docker:6060 --ip $(hostname -i) -r clair-report.json -l clair.log -w $MODIFIED_IMAGE/clair-whitelist.yml --threshold="High" $REGISTRY/ci-builds/$MODIFIED_IMAGE:$CI_COMMIT_SHA
    artifacts:
        paths:
            - clair-report.json
            - clair.log
    tags: [build]
    only:
        changes:
            - "pica-dokuwiki/*"
            - "pica-etherpad/*"
            - "pica-tellform/*"
            - "pica-wekan/*"
            - "pica-sympa/*"
        refs:
            - master
            - dev-ci
            - tx-services-p19-test
            - dev-sympa

# run docker-bench-security and upload the results
docker-bench-security:
    stage: dynamic_tests
    image: $REGISTRY/pica-ci:$CI_COMMIT_SHA
    before_script:
        - echo $REGISTRY_PASSWORD | docker login $REGISTRY -u $REGISTRY_USERNAME --password-stdin
        - docker pull $REGISTRY/ci-builds/$MODIFIED_IMAGE:$CI_COMMIT_SHA
        - docker logout $REGISTRY
        - source /etc/profile.d/ci-variables
        - sed -i -e "s/$MODIFIED_IMAGE_FULL/$REGISTRY\/ci-builds\/$MODIFIED_IMAGE:$CI_COMMIT_SHA/g" $MODIFIED_IMAGE/docker-compose.yml
        # if secrets.example files exist, remove the .example extension to be able to start the container
        - if [[ -d $MODIFIED_IMAGE/secrets ]]; then for i in $MODIFIED_IMAGE/secrets/*.example ; do cp $i $(echo $i| cut -d '.' -f1,2); done; fi;
        # let docker-compose create the required volumes and networks
        - "sed -i -e 's/external: true/external: false/g' $MODIFIED_IMAGE/docker-compose.yml"
        - cat $MODIFIED_IMAGE/docker-compose.yml
    script:
        - cd $MODIFIED_IMAGE
        - docker-compose up -d
        - git clone https://github.com/docker/docker-bench-security.git
        - cd docker-bench-security
        - sh docker-bench-security.sh -c container_images,container_runtime,docker_security_operations -e check_5_12,check_4_1 -l ../../report.txt
    artifacts:
        paths:
            - report.txt
    after_script:
        - docker logout $REGISTRY
    tags: [build]
    only:
        changes:
            - "pica-dokuwiki/*"
            - "pica-etherpad/*"
            - "pica-tellform/*"
            - "pica-wekan/*"
            - "pica-sympa/*"
        refs:
            - master
            - dev-ci
            - tx-services-p19-test
            - dev-sympa

# automatically deploy the container on pica01-test
deployment-test:
    stage: deployment
    image: $REGISTRY/pica-ci:$CI_COMMIT_SHA
    variables:
        PICA_ENVIRONMENT: "TEST"
    before_script:
        - source /etc/profile.d/ci-variables
        - export DOCKER_HOST=tcp://pica01-test.picasoft.net:2376
        - export DOCKER_TLS_VERIFY=1
        - export DOCKER_CERT_PATH=/tmp/certs
        - mkdir -p $DOCKER_CERT_PATH
        - echo "$DEV_DOCKER_CA_CERT" > $DOCKER_CERT_PATH/ca.pem
        - echo "$DEV_DOCKER_CLIENT_CERT" > $DOCKER_CERT_PATH/cert.pem
        - echo "$DEV_DOCKER_CLIENT_KEY" > $DOCKER_CERT_PATH/key.pem
        - chmod +x decrypt-secrets.sh
        - if [[ -d "$MODIFIED_IMAGE/secrets" ]]; then eval $(cat /etc/profile.d/ci-variables) ./decrypt-secrets.sh; fi
        - echo $REGISTRY_PASSWORD | docker login $REGISTRY -u $REGISTRY_USERNAME --password-stdin
        - docker pull $REGISTRY/ci-builds/$MODIFIED_IMAGE:$CI_COMMIT_SHA
        - docker tag $REGISTRY/ci-builds/$MODIFIED_IMAGE:$CI_COMMIT_SHA $MODIFIED_IMAGE_FULL
    script:
        - cd $MODIFIED_IMAGE
        - sed -i -e  s/picasoft.net/test.picasoft.net/g docker-compose.yml
        - for VOLUME in $(docker-compose config --volumes | sed 's/-volume//g'); do if [[ ! $(docker volume ls -q | grep "^$VOLUME\$") ]]; then docker volume create --name=$VOLUME; fi; done
        - for SERVICE in $(docker-compose config --services); do if [[ $(docker container ls --format "{{.Names}}" | grep $SERVICE) ]]; then docker stop $SERVICE | xargs docker rm; fi; done
        - docker-compose up -d --force-recreate --remove-orphans $CONTAINER_NAME
    after_script:
        - rm -rf $DOCKER_CERT_PATH
        - docker logout $REGISTRY
    tags: [build]
    only:
        changes:
            - "pica-dokuwiki/*"
            - "pica-etherpad/*"
            - "pica-tellform/*"
            - "pica-wekan/*"
            - "pica-sympa/*"
        refs:
            - master
            - dev-ci
            - tx-services-p19-test
            - dev-sympa

# automatically deploy the container on the production host associated with the modified image
# this will only happen after manually triggering the deployment
deployment-prod:
    stage: deployment
    image: $REGISTRY/pica-ci:$CI_COMMIT_SHA
    variables:
        PICA_ENVIRONMENT: "PRODUCTION"
    before_script:
        - source /etc/profile.d/ci-variables
        - TMP_DOCKER_CA_CERT="${HOST}_DOCKER_CA_CERT" && eval DOCKER_CA_CERT_VARIABLE=\$$TMP_DOCKER_CA_CERT
        - TMP_DOCKER_CLIENT_CERT="${HOST}_DOCKER_CLIENT_CERT" && eval DOCKER_CLIENT_CERT_VARIABLE=\$$TMP_DOCKER_CLIENT_CERT
        - TMP_DOCKER_CLIENT_KEY="${HOST}_DOCKER_CLIENT_KEY" && eval DOCKER_CLIENT_KEY_VARIABLE=\$$TMP_DOCKER_CLIENT_KEY
        - export DOCKER_HOST=tcp://$HOST.picasoft.net:2376
        - export DOCKER_TLS_VERIFY=1
        - export DOCKER_CERT_PATH=/tmp/certs
        - mkdir -p $DOCKER_CERT_PATH
        - echo "$DOCKER_CA_CERT_VARIABLE" > $DOCKER_CERT_PATH/ca.pem
        - echo "$DOCKER_CLIENT_CERT_VARIABLE" > $DOCKER_CERT_PATH/cert.pem
        - echo "$DOCKER_CLIENT_KEY_VARIABLE" > $DOCKER_CERT_PATH/key.pem
        - chmod +x decrypt-secrets.sh
        - if [[ -d "$MODIFIED_IMAGE/secrets" ]]; then eval $(cat /etc/profile.d/ci-variables) ./decrypt-secrets.sh; fi
        - echo $REGISTRY_PASSWORD | docker login $REGISTRY -u $REGISTRY_USERNAME --password-stdin
        - docker pull $REGISTRY/ci-builds/$MODIFIED_IMAGE:$CI_COMMIT_SHA
        - docker logout $REGISTRY
        - docker tag $REGISTRY/ci-builds/$MODIFIED_IMAGE:$CI_COMMIT_SHA $MODIFIED_IMAGE_FULL
    script:
        - cd $MODIFIED_IMAGE
        - for SERVICE in $(docker-compose config --services); do if [[ $(docker container ls --format "{{.Names}}" | grep $SERVICE) ]]; then docker stop $SERVICE | xargs docker rm; fi; done
        - docker-compose up -d --force-recreate --remove-orphans $CONTAINER_NAME
        - docker tag $REGISTRY/ci-builds/$MODIFIED_IMAGE:$CI_COMMIT_SHA $REGISTRY_PROD/$MODIFIED_IMAGE_FULL
        - echo $REGISTRY_PROD_PASSWORD | docker login $REGISTRY_PROD -u $REGISTRY_PROD_USERNAME --password-stdin
        - docker push $REGISTRY_PROD/$MODIFIED_IMAGE_FULL
        - rm -rf $DOCKER_CERT_PATH
        - docker logout $REGISTRY_PROD
    tags: [build]
    only:
        changes:
            - "pica-dokuwiki/*"
            - "pica-etherpad/*"
            - "pica-tellform/*"
            - "pica-wekan/*"
        refs:
            - master
    when: manual
