# SPDX-FileCopyrightText: 2022-2024 Sarah Vaupel <sarah.vaupel@uniworx.de>, Gregor Kleen <gregor@kleen.consulting>
#
# SPDX-License-Identifier: AGPL-3.0-or-later

# 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:
  # TODO: old vars; review and maybe remove
  AWS_SHARED_CREDENTIALS_FILE: "/etc/aws/credentials"
  TRANSFER_METER_FREQUENCY: "2s"

  # Docker
  ENV_USER: fradrive-env

  # Backend
  STACK_ROOT: "${CI_PROJECT_DIR}/.stack"


default:
  image:
    name: registry.uniworx.de/fradrive/fradrive/fradrive-env:latest # Debian 12.5 Bookworm
    entrypoint: [""]
    docker:
      platform: x86_64
      user: ${ENV_USER}
  before_script:
    - chown -R ${ENV_USER} . # Change project directory ownership to (non-root) user inside docker container
  artifacts:
    name: "${CI_JOB_NAME}-${CI_COMMIT_SHORT_SHA}"
    expire_in: "1 day"
  retry: 2
  interruptible: true


stages:
  - setup
  - build
  - lint
  - test
  - container
  - prepare release
  - release


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
