stages:
  - ci_image
  - test
  - coverage
  - upload
  - release
  - publish

variables:
  PACKAGE_VERSION: "${CI_COMMIT_TAG}"
  PACKAGE_REGISTRY_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/crates/${PACKAGE_VERSION}"
  CI_IMAGE_TAG: "latest"

workflow:
  rules:
    # 0) 1st MR commit safeguard
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      variables:
        CI_IMAGE_TAG: "latest"

    # 1) Always run merge request pipelines
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      changes:
        - Dockerfile
      variables:
        CI_IMAGE_TAG: "${CI_COMMIT_SHORT_SHA}"

    # 2) If there's an open MR for this branch, skip the push/branch pipeline
    - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
      when: never

    # 3) Tags: build on latest
    - if: $CI_COMMIT_TAG
      variables:
        CI_IMAGE_TAG: "latest"

    # 4) Branch pipeline default
    - if: $CI_COMMIT_BRANCH
      variables:
        CI_IMAGE_TAG: "latest"

    # 5) Branch pipelines: if image inputs changed, use freshly built SHA-tag
    - if: $CI_COMMIT_BRANCH
      changes:
        - Dockerfile
      variables:
        CI_IMAGE_TAG: "${CI_COMMIT_SHORT_SHA}"

    # 6) Master: build on latest
    - if: $CI_COMMIT_BRANCH == "master"
      variables:
        CI_IMAGE_TAG: "latest"

default:
  image: "$CI_REGISTRY_IMAGE:$CI_IMAGE_TAG"

ci_image:
  stage: ci_image
  rules:
    - if: $CI_IMAGE_TAG != "latest"
      when: on_success
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  image: docker:27.4.1-cli
  services:
    - name: docker:27.4.1-dind
      alias: docker
  before_script:
    - echo "${CI_REGISTRY_PASSWORD}" | docker login -u "${CI_REGISTRY_USER}" --password-stdin "${CI_REGISTRY}"
  script:
    - IMAGE="${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}"
    - LATEST="${CI_REGISTRY_IMAGE}:latest"
    - echo "Building new CI image..."
    - |
      docker buildx build -f "Dockerfile" -t "${IMAGE}" --load \
      --label "org.opencontainers.image.source=${CI_PROJECT_URL}" \
      --label "org.opencontainers.image.revision=${CI_COMMIT_SHA}" \
      --label "org.opencontainers.image.created=${CI_PIPELINE_CREATED_AT}" \
      --label "org.opencontainers.image.version=${CI_COMMIT_SHORT_SHA}" \
      .
    - docker push "${IMAGE}"
    - |
      if [ "${CI_PIPELINE_SOURCE}" = "merge_request_event" ] && [ "${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}" = "master" ]; then
        docker tag "${IMAGE}" "${LATEST}"
        docker push "${LATEST}"
      fi

test:
  stage: test
  needs:
    - job: ci_image
      optional: true
  artifacts:
    paths:
      - coverage/
      - release/package/
  script:
    - echo "Running tests..."
    - mkdir -p release/package
    - just ci
    - |
      if [ -n "${CI_COMMIT_TAG}" ]; then
        echo "Packaging nishikaze..."
        just package
        rm -rf releases/package/tmp-crate
      fi

coverage:
  stage: coverage
  image: curlimages/curl:latest
  needs:
    - job: test
  dependencies:
    - test
  script:
    - echo "Uploading coverage reports"
    - curl -L https://github.com/coverallsapp/coverage-reporter/releases/latest/download/coveralls-linux-x86_64.tar.gz | tar -xz
    - chmod +x ./coveralls
    - ./coveralls report coverage/lcov.info --repo-token "${COVERALLS_TOKEN}"

.generate_package_name:
  before_script:
    - PACKAGE_PATH=$(find release/package -name "nishikaze*.crate" | tail -1)
    - PACKAGE_NAME=$(basename "${PACKAGE_PATH}")

upload:
  stage: upload
  image: curlimages/curl:latest
  needs:
    - job: coverage
    - job: test
  dependencies:
    - test
  extends: .generate_package_name
  only:
    - tags
  artifacts:
    paths:
      - release/package/
  script:
    - echo "Uploading crate package to Gitlab Package Registry..."
    - |
      curl --fail-with-body --location \
      --header "JOB-TOKEN: ${CI_JOB_TOKEN}" \
      --upload-file "${PACKAGE_PATH}" "${PACKAGE_REGISTRY_URL}/${PACKAGE_NAME}"

release:
  stage: release
  image: curlimages/curl:latest
  needs:
    - job: upload
    - job: test
  dependencies:
    - test
  extends: .generate_package_name
  only:
    - tags
  script:
    - echo "Creating Gitlab release..."
    - curl --location --output ./release-cli "https://gitlab.com/api/v4/projects/gitlab-org%2Frelease-cli/packages/generic/release-cli/latest/release-cli-linux-amd64"
    - chmod +x ./release-cli
    - |
      ./release-cli create \
      --name "Release ${CI_COMMIT_TAG}" \
      --tag-name "${CI_COMMIT_TAG}" \
      --description "nishikaze release ${CI_COMMIT_TAG}" \
      --assets-link "{\"name\":\"${PACKAGE_NAME}\", \"url\":\"${PACKAGE_REGISTRY_URL}/${PACKAGE_NAME}\", \"link_type\":\"package\"}"

publish:
  stage: publish
  needs:
    - job: release
  only:
    - tags
  script:
  - echo "Publishing nishikaze to crates.io..."
  - cargo publish --workspace --token "${CI_API_KEY}"
