# publish npm package, docker image, linux appimage and windows exe
stages:
  - build
  - publish

# ─── NPM Package ───────────────────────────────────────────────────────────────
# Publish npm package if commit has a version tag or is production branch.
# Publish only if version changed.
# Publish tagged "beta" if version contains beta (e.g. v2.0.0-beta.0)
#
# The original template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/npm.gitlab-ci.yml

npm-publish:
  image: node:latest
  stage: publish
  dependencies: [] # don't download bundle artifacts
  id_tokens:
    NPM_ID_TOKEN:
      aud: "npm:registry.npmjs.org"
    SIGSTORE_ID_TOKEN:
      aud: sigstore
  rules:
    - if: $CI_COMMIT_REF_NAME =~ /^v\d+\.\d+\.\d+.*$/
    - if: $API_JOB_NAME == $CI_JOB_NAME
  script:
    # Fetch latest client build artifact and unzip
    - apt update && apt install -y unzip
    - curl --location --output artifacts.zip "https://gitlab.com/machina_ex/adaptor_ex/adaptor_ex_client/-/jobs/artifacts/production/download?job=build-site"
    - unzip artifacts.zip
    - mv dist/* public
    - rm artifacts.zip

    # Extract version from package.json
    - NPM_PACKAGE_VERSION=$(node -p "require('./package.json').version")

    # If package version is "beta" prerelease publish with "beta" tag otherwise publish latest
    - |
      if [[ "$NPM_PACKAGE_VERSION" =~ -beta* ]]; then
        npm publish --tag=beta
      else
        npm publish
      fi
      echo "Successfully published version ${NPM_PACKAGE_VERSION} to GitLab's NPM registry: ${CI_PROJECT_URL}/-/packages"

# ─── Docker image ─────────────────────────────────────────────────────────────
# Build a Docker image with CI/CD and push to the GitLab registry.
# Docker-in-Docker documentation: https://docs.gitlab.com/ee/ci/docker/using_docker_build.html
#
# This template uses one generic job with conditional builds
# for the default branch and all other (MR) branches.

docker-build:
  # Use the official docker image.
  image: docker:latest
  stage: publish
  dependencies: [] # don't download bundle artifacts — Docker builds from source only
  # Run this job for tags only. If tag is version number, build 'latest' container also (tag like v0.0.0)
  only:
    - tags
  services:
    - docker:dind
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
  # tagged with production version number (commit tag)
  script:
    - docker build --pull -t "$CI_REGISTRY_IMAGE" -t "$CI_REGISTRY_IMAGE:${CI_COMMIT_TAG}" .
    - VERSION_PATTERN="^v([0-9]+\.){0,2}(\*|[0-9]+)$"
    - |
      if [[ "$CI_COMMIT_TAG" =~ $VERSION_PATTERN ]]; then
        docker push "$CI_REGISTRY_IMAGE"
        echo "Tag is version number. Build also with tag 'latest'"
      else
        echo "Tag '$CI_COMMIT_TAG' is not a valid version number. Push with tag '$CI_COMMIT_TAG' only"
      fi
    - docker push "$CI_REGISTRY_IMAGE:${CI_COMMIT_TAG}"

# ─── Linux AppImage ───────────────────────────────────────────────────────────
# Runs npm run bundle:linux (build:linux + bundle-linux-appimage.js) and
# publishes the resulting AppImage to the GitLab Generic Packages registry.
# Stable download URL for docs:
#   <CI_API_V4_URL>/projects/<CI_PROJECT_ID>/packages/generic/adaptorex/<version>/adaptorex-<version>-x86_64.AppImage

bundle-linux:
  image: node:22
  stage: build
  rules:
    - if: $CI_COMMIT_TAG
  before_script:
    - apt-get update && apt-get install -y unzip libfuse2
    # Allow appimagetool (itself an AppImage) to run via FUSE
    - modprobe fuse || true
  script:
    - VERSION=$(node -p "require('./package.json').version")
    - APPIMAGE_NAME="adaptorex-${VERSION}-x86_64.AppImage"

    # Fetch latest client build
    - curl --location --output artifacts.zip "https://gitlab.com/machina_ex/adaptor_ex/adaptor_ex_client/-/jobs/artifacts/production/download?job=build-site"
    - unzip artifacts.zip
    - mv dist/* public
    - rm artifacts.zip

    # Install deps (needed for pkg and build scripts)
    - npm ci

    # Build pkg binary + wrap in AppImage
    # appimagetool is downloaded and cached by bundle-linux-appimage.js itself
    - npm run build:linux
    - npm run bundle:linux

      # Publish to Generic Packages registry
    - |
      curl --fail --header "JOB-TOKEN: $CI_JOB_TOKEN" \
           --upload-file "dist/${APPIMAGE_NAME}" \
           "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/${VERSION}/${APPIMAGE_NAME}"
      echo "Versioned: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/${VERSION}/${APPIMAGE_NAME}"
      curl --fail --header "JOB-TOKEN: $CI_JOB_TOKEN" \
           --upload-file "dist/${APPIMAGE_NAME}" \
           "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/latest/adaptorex-x86_64.AppImage"
      echo "Latest:    ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/latest/adaptorex-x86_64.AppImage"

  artifacts:
    name: "adaptorex-linux-${VERSION}"
    paths:
      - dist/*x86_64*.AppImage
    expire_in: 30 days

bundle-linux-arm:
  image: node:22
  stage: build
  tags:
    - saas-linux-small-arm64
  cache:
    key: pkg-cache-linux-arm64
    paths:
      - /root/.pkg-cache
  before_script:
    - apt-get update && apt-get install -y unzip libfuse2
    - modprobe fuse || true
  rules:
    - if: $CI_COMMIT_TAG
  script:
    - VERSION=$(node -p "require('./package.json').version")
    - APPIMAGE_NAME="adaptorex-${VERSION}-arm64.AppImage"

    # Fetch latest client build
    - curl --location --output artifacts.zip "https://gitlab.com/machina_ex/adaptor_ex/adaptor_ex_client/-/jobs/artifacts/production/download?job=build-site"
    - unzip artifacts.zip
    - mv dist/* public
    - rm artifacts.zip

    # install node modules
    - npm ci

    # Build the binary
    - npm run build:linux-arm

    # bundle script
    - npm run bundle:linux-arm

    # Publish to Generic Packages registry
    - |
      curl --fail --header "JOB-TOKEN: $CI_JOB_TOKEN" \
           --upload-file "dist/${APPIMAGE_NAME}" \
           "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/${VERSION}/${APPIMAGE_NAME}"
      echo "Versioned: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/${VERSION}/${APPIMAGE_NAME}"
      curl --fail --header "JOB-TOKEN: $CI_JOB_TOKEN" \
           --upload-file "dist/${APPIMAGE_NAME}" \
           "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/latest/adaptorex-arm64.AppImage"
      echo "Latest:    ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/latest/adaptorex-arm64.AppImage"

  artifacts:
    name: "adaptorex-linux-arm-${CI_COMMIT_TAG}"
    paths:
      - dist/*arm64*.AppImage
    expire_in: 30 days

# ─── Windows Executable ───────────────────────────────────────────────────────
# Runs npm run bundle:windows (bundle-windows-exe.js) which uses resedit to
# embed the icon and version info, then calls yao-pkg to produce the .exe.
# Output: dist/adaptorex-win-<version>.exe

bundle-windows:
  image: node:22
  stage: build
  rules:
    - if: $CI_COMMIT_TAG
  script:
    - VERSION=$(node -p "require('./package.json').version")
    - EXE_NAME="adaptorex-win-${VERSION}.exe"

    # Fetch latest client build
    - apt-get update && apt-get install -y unzip
    - curl --location --output artifacts.zip "https://gitlab.com/machina_ex/adaptor_ex/adaptor_ex_client/-/jobs/artifacts/production/download?job=build-site"
    - unzip artifacts.zip
    - mv dist/* public
    - rm artifacts.zip

    # Install deps (resedit and yao-pkg are devDependencies)
    - npm ci

    # Build the Windows exe (cross-compiles from Linux via yao-pkg)
    - npm run bundle:windows

    # Publish to Generic Packages registry
    - |
      curl --fail --header "JOB-TOKEN: $CI_JOB_TOKEN" \
           --upload-file "dist/${EXE_NAME}" \
           "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/${VERSION}/${EXE_NAME}"
      echo "Versioned: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/${VERSION}/${EXE_NAME}"
      curl --fail --header "JOB-TOKEN: $CI_JOB_TOKEN" \
           --upload-file "dist/${EXE_NAME}" \
           "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/latest/adaptorex-win-x64.exe"
      echo "Latest:    ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/latest/adaptorex-win-x64.exe"

  artifacts:
    name: "adaptorex-windows-${VERSION}"
    paths:
      - dist/*win*.exe
    expire_in: 30 days

# ─── macOS App Bundle ─────────────────────────────────────────────────────────
# Runs npm run bundle:macos (build:macos + bundle-macos-app.js) on a macOS
# runner — required because the script uses sips, iconutil, and codesign which
# are macOS-only tools.
# The resulting adaptorex.app directory is turned into a dm using npm package create-dmg
bundle-macos:
  stage: build
  tags:
    - macos # requires a GitLab Runner registered with the 'macos' tag
  rules:
    - if: $CI_COMMIT_TAG
  script:
    - VERSION=$(node -p "require('./package.json').version")
    - DMG_NAME="adaptorex-${VERSION}-macos-x86_64.dmg"

    # Fetch latest client build
    - curl --location --output artifacts.zip "https://gitlab.com/machina_ex/adaptor_ex/adaptor_ex_client/-/jobs/artifacts/production/download?job=build-site"
    - unzip artifacts.zip
    - mv dist/* public
    - rm artifacts.zip

    # Install deps
    - npm ci
    - npm install -g create-dmg # macOS runner only, not in package.json

    # Build pkg binary
    - npm run build:macos
    # assemble .app bundle (sips/iconutil/codesign run here) and create .dmg
    - npm run bundle:macos

    # Publish to Generic Packages registry
    - |
      curl --fail --header "JOB-TOKEN: $CI_JOB_TOKEN" \
           --upload-file "dist/${DMG_NAME}" \
           "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/${VERSION}/${DMG_NAME}"
      echo "Versioned: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/${VERSION}/${DMG_NAME}"
      curl --fail --header "JOB-TOKEN: $CI_JOB_TOKEN" \
           --upload-file "dist/${DMG_NAME}" \
           "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/latest/adaptorex-macos-x86_64.dmg"
      echo "Latest:    ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/latest/adaptorex-macos-x86_64.dmg"

  artifacts:
    name: "adaptorex-macos-${VERSION}"
    paths:
      - dist/*x86_64*.dmg
    expire_in: 30 days

bundle-macos-arm:
  stage: build
  tags:
    - macos # requires a GitLab Runner registered with the 'macos' tag
  rules:
    - if: $CI_COMMIT_TAG
  script:
    - VERSION=$(node -p "require('./package.json').version")
    - DMG_NAME="adaptorex-${VERSION}-macos-arm64.dmg"

    # Fetch latest client build
    - curl --location --output artifacts.zip "https://gitlab.com/machina_ex/adaptor_ex/adaptor_ex_client/-/jobs/artifacts/production/download?job=build-site"
    - unzip artifacts.zip
    - mv dist/* public
    - rm artifacts.zip

    # Install deps
    - npm ci
    - npm install -g create-dmg # macOS runner only, not in package.json

    # Build pkg binary
    - npm run build:macos-arm
    # assemble .app bundle (sips/iconutil/codesign run here) and create .dmg
    - npm run bundle:macos-arm

    # Publish to Generic Packages registry
    - |
      curl --fail --header "JOB-TOKEN: $CI_JOB_TOKEN" \
           --upload-file "dist/${DMG_NAME}" \
           "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/${VERSION}/${DMG_NAME}"
      echo "Versioned: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/${VERSION}/${DMG_NAME}"
      curl --fail --header "JOB-TOKEN: $CI_JOB_TOKEN" \
           --upload-file "dist/${DMG_NAME}" \
           "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/latest/adaptorex-macos-arm64.dmg"
      echo "Latest:    ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/adaptorex/latest/adaptorex-macos-arm64.dmg"

  artifacts:
    name: "adaptorex-macos-${VERSION}"
    paths:
      - dist/*arm64*.dmg
    expire_in: 30 days
