# SPDX-FileCopyrightText: 2022-2024 Sarah Vaupel , Gregor Kleen # # SPDX-License-Identifier: AGPL-3.0-or-later ### IMPORTANT NOTICE ### # Our pipeline consists of static and dynamic parts. # # This file only contains the static parts of our pipeline. # Dynamic jobs are defined in .gitlab-ci/frontend.yml and .gitlab-ci/backend.yml. # These are used as a template to generate downstream (child) pipelines during # the runtime of the upstream (parent) pipeline. ### # workflow: # rules: # - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # - if: $CI_MERGE_REQUEST_ID # - if: $CI_COMMIT_TAG =~ /^v/ # - if: $CI_COMMIT_TAG =~ /^t/ # - if: $CI_COMMIT_TAG =~ /^d/ variables: IMAGE_BUILDER: quay.io/buildah/stable:latest FRONTEND_IMAGE_DEPENDENCIES: docker/frontend/Dockerfile package.json package-lock.json webpack.config.js BACKEND_IMAGE_DEPENDENCIES: docker/backend/Dockerfile package.yaml stack.yaml stack.yaml.lock default: image: name: ${CI_REGISTRY}/uniworx/containers/debian:12.5 entrypoint: [""] docker: platform: x86_64 artifacts: name: "${CI_JOB_NAME}-${CI_COMMIT_SHORT_SHA}" expire_in: "1 day" retry: 2 interruptible: true stages: - setup - frontend - backend - release setup:dynamic: stage: setup before_script: - apt-get -y update - apt-get -y install git variables: GIT_DEPTH: 99999 GIT_STRATEGY: clone GIT_LOG_COMMAND: 'git log --max-count=1 --date=format:%Y-%m-%dT%H-%M --pretty=format:%cd' script: - echo "${FRONTEND_IMAGE_DEPENDENCIES}" - echo "${BACKEND_IMAGE_DEPENDENCIES}" - FRONTEND_IMAGE_VERSION=`${GIT_LOG_COMMAND} ${FRONTEND_IMAGE_DEPENDENCIES} | tee frontend-image-version` - BACKEND_IMAGE_VERSION=`${GIT_LOG_COMMAND} ${BACKEND_IMAGE_DEPENDENCIES} | tee backend-image-version` - 'echo "FRONTEND_IMAGE_VERSION: ${FRONTEND_IMAGE_VERSION}, BACKEND_IMAGE_VERSION: ${BACKEND_IMAGE_VERSION}"' - cat .gitlab-ci/frontend.yml | .gitlab-ci/dynamci.pl FRONTEND_IMAGE_VERSION=${FRONTEND_IMAGE_VERSION} > frontend.yml - cat .gitlab-ci/backend.yml | .gitlab-ci/dynamci.pl BACKEND_IMAGE_VERSION=${BACKEND_IMAGE_VERSION} PARENT_PIPELINE_ID=${CI_PIPELINE_ID} > backend.yml artifacts: paths: - frontend-image-version - backend-image-version - frontend.yml - backend.yml rules: - when: always setup:containers:frontend: &setup-container stage: setup needs: - setup:dynamic image: ${IMAGE_BUILDER} variables: IMAGE_TYPE: frontend before_script: &container-before - IMAGE_VERSION=`cat ${IMAGE_TYPE}-image-version` - IMAGE_TAG=${CI_COMMIT_REF_SLUG}/${IMAGE_TYPE}:${IMAGE_VERSION} - REGISTRY_DESTINATION=${CI_REGISTRY_IMAGE}/${CI_COMMIT_REF_SLUG}/${IMAGE_TYPE}:${IMAGE_VERSION} script: - curl --request GET --header "PRIVATE-TOKEN:${REGISTRY_AUTH_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/registry/repositories?tags=true" > .gitlab-ci/.container-registry-contents.json - cat .gitlab-ci/.container-registry-contents.json - IMAGE_EXISTS=`grep \""${REGISTRY_DESTINATION}"\" .gitlab-ci/.container-registry-contents.json || :` - echo "${IMAGE_EXISTS}" - test "${CI_JOB_MANUAL}" = true && echo "Force rebuilding container." - > if [ -z "${IMAGE_EXISTS}" -o "${CI_JOB_MANUAL}" = true ] ; then echo "Building image ${REGISTRY_DESTINATION}..." buildah bud -t ${IMAGE_TAG} --build-arg PROJECT_DIR=${CI_PROJECT_DIR} --build-arg MOUNT_DIR=/mnt/${CI_PROJECT_DIR} --volume ${CI_PROJECT_DIR}:/mnt/${CI_PROJECT_DIR} --file docker/${IMAGE_TYPE}/Dockerfile buildah push --creds "${CI_REGISTRY_USER}:${CI_JOB_TOKEN}" ${IMAGE_TAG} ${REGISTRY_DESTINATION} else echo "Image ${IMAGE_TAG} already exists in the container registry. Skipping build." fi rules: - if: $CI_MERGE_REQUEST_ID when: never - when: always setup:containers:frontend:wait: &setup-container-wait stage: setup needs: - setup:dynamic before_script: *container-before variables: GIT_STRATEGY: none IMAGE_TYPE: frontend script: - apt-get -y update && apt-get -y install curl - > while ! curl --request GET --header "PRIVATE-TOKEN:${REGISTRY_AUTH_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/registry/repositories?tags=true" | grep \""${REGISTRY_DESTINATION}"\" ; do echo "Waiting for container ${IMAGE_TAG} to appear in the container registry..." sleep 5 done - echo "Image ${IMAGE_TAG} has been found in the container registry. Proceeding with the pipeline." rules: - if: $CI_MERGE_REQUEST_ID when: always - when: never retry: 0 interruptible: true timeout: 3h setup:containers:backend: <<: *setup-container variables: IMAGE_TYPE: backend setup:containers:backend:wait: <<: *setup-container-wait variables: GIT_STRATEGY: none IMAGE_TYPE: backend frontend: stage: frontend variables: GIT_STRATEGY: clone needs: - setup:dynamic - job: setup:containers:frontend optional: true trigger: strategy: depend include: - artifact: frontend.yml job: setup:dynamic backend:dev: &backend stage: backend variables: GIT_STRATEGY: clone needs: - setup:dynamic - job: setup:containers:backend optional: true - frontend trigger: strategy: depend include: - artifact: backend.yml job: setup:dynamic backend:prod: <<: *backend variables: PROD_BUILD: -prod release:changelog: stage: release rules: &release-rules - if: $CI_COMMIT_TAG =~ /^v[0-9\.]+$/ - if: $CI_COMMIT_TAG =~ /^v[0-9\.]+-test-.*$/ script: - echo "Preparing release..." - ./.gitlab-ci/version.pl > .current-version - echo "VERSION=$(cat .current-version)" >> build.env - ./.gitlab-ci/version.pl -changelog CHANGELOG.md artifacts: reports: dotenv: build.env paths: - .current-version - .changelog.md name: "changelog-${CI_COMMIT_SHORT_SHA}" expire_in: "1 day" release:container: stage: release rules: *release-rules variables: GIT_STRATEGY: none image: ${IMAGE_BUILDER} script: - echo "Building container for release ${VERSION}..." - buildah bud --tag fradrive:${VERSION} --file docker/fradrive/Dockerfile - buildah add --chown uniworx:uniworx bin/uniworx /bin/uniworx - echo "Pushing container ${VERSION} to container registry..." - buildah push --creds "${CI_REGISTRY_USER}:${CI_JOB_TOKEN}" fradrive:${VERSION} ${CI_REGISTRY_IMAGE}/fradrive:${VERSION} needs: - frontend # sanity - backend:prod # sanity - release:changelog release:release: stage: release rules: *release-rules variables: GIT_STRATEGY: none image: registry.gitlab.com/gitlab-org/release-cli:latest script: - echo "Creating release ${VERSION}" release: name: "${VERSION}" tag_name: "{$CI_COMMIT_TAG}" description: .changelog.md needs: - frontend # sanity - backend:prod # sanity - release:changelog - release:container retry: 0 # frontend dependencies: # stage: setup # cache: # - &npm-cache # key: default-npm # paths: &npm-paths # - node_modules/ # - .npm/ # - .npmrc # script: # - make node_modules # artifacts: # paths: *npm-paths # well-known: # stage: setup # script: # - make well-known # needs: # - job: frontend dependencies # artifacts: true # cache: # - &frontend-cache # key: default-frontend # paths: # - .well-known-cache # artifacts: # paths: # - well-known/ # - .well-known-cache/ # # TODO: cache is always uploaded even if up-to-date; prevent re-upload when up-to-date # backend dependencies: # stage: setup # cache: # - &stack-cache # key: default-stack # paths: # - .stack/ # - .stack-work/ # script: # - make backend-dependencies-prod # artifacts: # paths: # - .stack/ # - .stack-work/ # frontend build: # stage: build # cache: # - *frontend-cache # script: # - make frontend-build # needs: # - job: frontend dependencies # artifacts: true # - job: well-known # artifacts: true # artifacts: # paths: # - static/ # - config/webpack.yml # # TODO: .stack-work cache not working # backend build: # stage: build # cache: # - *stack-cache # script: # - make bin/uniworx # # - find .stack-work # # - cp $(stack path --dist-dir)/build/hlint/hlint bin/test-hlint # # - cp $(stack path --dist-dir)/build/yesod/yesod bin/test-yesod # needs: # - job: frontend dependencies # transitive # artifacts: false # - job: well-known # artifacts: true # - job: backend dependencies # artifacts: true # - job: frontend build # artifacts: true # artifacts: # paths: # - bin/ # resource_group: ram # # TODO: part of backend build; probably deprecated # # uniworxdb: # # stage: build # # script: # # - make bin/uniworxdb # # needs: # # # TODO: no frontend needed # # - job: frontend dependencies # transitive # # artifacts: false # # - job: frontend build # transitive # # artifacts: false # # artifacts: # # paths: # # - bin/uniworxdb # # TODO: part of backend build; probably deprecated # # TODO: rewrite # # uniworx:exe:uniworxload: # # stage: build # # script: # # - xzcat uniworx:lib:uniworx.nar.xz | nix-store --import # # - nix -L build -o result ".#uniworx:exe:uniworxload" # # - nix-store --export $(nix-store -qR result) | xz -T0 -2 > uniworx:exe:uniworxload.nar.xz # # needs: # # - job: frontend dependencies # transitive # # artifacts: false # # - job: frontend build # transitive # # artifacts: false # # artifacts: # # paths: # # - uniworx:exe:uniworxload.nar.xz # frontend lint: # stage: lint # script: # - make frontend-lint # cache: # - *frontend-cache # needs: # - job: frontend dependencies # artifacts: true # - job: well-known # TODO: is this really needed? # artifacts: true # backend lint: # stage: lint # cache: # - *stack-cache # script: # # TODO: - make backend-lint-dev # - make backend-lint-prod # needs: # - job: backend dependencies # artifacts: true # - job: backend build # artifacts: true # - job: frontend build # artifacts: true # - job: well-known # artifacts: true # frontend test: # stage: test # script: # - make frontend-test # cache: *frontend-cache # needs: # - job: frontend dependencies # artifacts: true # # TODO: configure report artifacts # backend test: # stage: test # script: # - make backend-test-prod # cache: *stack-cache # needs: # - job: well-known # artifacts: true # - job: frontend build # artifacts: true # - job: backend dependencies # artifacts: true # - job: backend build # artifacts: true # # TODO: configure report artifacts # # TODO: unify prod and test versions # # TODO: rewrite # container: # stage: container # script: # - xzcat uniworx:exe:uniworx.nar.xz | nix-store --import # - cp -pr --reflink=auto -L $(nix build --print-out-paths ".#uniworxDocker") uniworx.tar.gz # needs: # - job: frontend dependencies # transitive # artifacts: false # - job: frontend build # transitive # artifacts: false # - job: frontend test # sanity # artifacts: false # - job: backend test # sanity # artifacts: false # artifacts: # paths: # - uniworx.tar.gz # rules: &release-rules # - if: $CI_COMMIT_TAG =~ /^v/ # # TODO: rewrite # test container: # stage: container # script: # - xzcat uniworx:exe:uniworx.nar.xz | nix-store --import # - cp -pr --reflink=auto -L $(nix build --print-out-paths ".#uniworxTestDocker") uniworx.tar.gz # needs: # - job: frontend dependencies # transitive # artifacts: false # - job: frontend build # transitive # artifacts: false # - job: frontend test # sanity # artifacts: false # - job: backend test # sanity # artifacts: false # artifacts: # paths: # - uniworx.tar.gz # rules: &test-release-rules # - if: $CI_COMMIT_TAG =~ /^t/ # # TODO: unify prod and test versions # # TODO: rewrite # parse changelog: # stage: prepare release # needs: # - job: frontend dependencies # artifacts: true # rules: *release-rules # script: # - xzcat node-dependencies.nar.xz | nix-store --import # - nix -L run ".#jqChangelogJson" -- -r '.versions[0].version' > .current-version # - nix -L run ".#jqChangelogJson" -- -r '.versions[0].body' > .current-changelog.md # - echo "VERSION=$(cat .current-version)" >> build.env # artifacts: # reports: # dotenv: build.env # paths: # - .current-version # - .current-changelog.md # name: "changelog-${CI_COMMIT_SHORT_SHA}" # expire_in: "1 day" # # TODO: rewrite # parse test changelog: # stage: prepare release # needs: # - job: frontend dependencies # artifacts: true # rules: *test-release-rules # script: # - xzcat node-dependencies.nar.xz | nix-store --import # - nix -L run ".#jqChangelogJson" -- -r '.versions[0].version' > .current-version # - nix -L run ".#jqChangelogJson" -- -r '.versions[0].body' > .current-changelog.md # - echo "VERSION=$(cat .current-version)" >> build.env # artifacts: # reports: # dotenv: build.env # paths: # - .current-version # - .current-changelog.md # name: "changelog-${CI_COMMIT_SHORT_SHA}" # # TODO: unify prod and test versions # # TODO: rewrite # upload container: # variables: # GIT_STRATEGY: none # stage: release # image: quay.io/skopeo/stable:latest # script: # - skopeo --insecure-policy copy --dest-creds "${CI_REGISTRY_USER}:${CI_JOB_TOKEN}" docker-archive://$(pwd)/uniworx.tar.gz docker://${CI_REGISTRY_IMAGE}:${VERSION} # - skopeo --insecure-policy copy --src-creds "${CI_REGISTRY_USER}:${CI_JOB_TOKEN}" --dest-creds "${CI_REGISTRY_USER}:${CI_JOB_TOKEN}" docker://${CI_REGISTRY_IMAGE}:${VERSION} docker://${CI_REGISTRY_IMAGE}:latest # needs: # - job: frontend dependencies # transitive # artifacts: false # - job: frontend build # transitive # artifacts: false # - job: container # artifacts: true # - job: parse changelog # artifacts: true # - job: frontend test # sanity # artifacts: false # - job: backend test # sanity # artifacts: false # rules: *release-rules # # TODO: rewrite # upload test container: # variables: # GIT_STRATEGY: none # stage: release # image: quay.io/skopeo/stable:latest # script: # - skopeo --insecure-policy copy --dest-creds "${CI_REGISTRY_USER}:${CI_JOB_TOKEN}" docker-archive://$(pwd)/uniworx.tar.gz docker://${CI_REGISTRY}/fradrive/fradrive/test:${CI_COMMIT_REF_NAME} # - skopeo --insecure-policy copy --src-creds "${CI_REGISTRY_USER}:${CI_JOB_TOKEN}" --dest-creds "${CI_REGISTRY_USER}:${CI_JOB_TOKEN}" docker://${CI_REGISTRY}/fradrive/fradrive/test:${CI_COMMIT_REF_NAME} docker://${CI_REGISTRY}/fradrive/fradrive/test:latest # needs: # - job: frontend dependencies # transitive # artifacts: false # - job: frontend build # transitive # artifacts: false # - job: test container # artifacts: true # - job: parse test changelog # artifacts: true # - job: frontend test # sanity # artifacts: false # - job: backend test # sanity # artifacts: false # rules: *test-release-rules # # TODO: unify prod and test versions # # TODO: rewrite # release: # variables: # GIT_STRATEGY: none # stage: release # image: registry.gitlab.com/gitlab-org/release-cli:latest # rules: *release-rules # script: # - echo "Will create release ${VERSION}..." # release: # name: '$VERSION' # tag_name: '$CI_COMMIT_TAG' # description: .current-changelog.md # needs: # - job: frontend test # sanity # artifacts: false # - job: backend test # sanity # artifacts: false # - job: parse changelog # artifacts: true # retry: 0 # # TODO: rewrite # test release: # variables: # GIT_STRATEGY: none # stage: release # image: registry.gitlab.com/gitlab-org/release-cli:latest # rules: *test-release-rules # script: # - echo "Will create test release ${VERSION}-test..." # release: # name: "${VERSION}-test" # tag_name: '$CI_COMMIT_TAG' # description: .current-changelog.md # needs: # - job: frontend test # sanity # artifacts: false # - job: backend test # sanity # artifacts: false # - job: parse test changelog # artifacts: true # retry: 0