spec:
  inputs:
    # Stages
    stage_validate:
      default: 'validate'
      description: 'Defines the validate stage. This stage includes the `fmt` and `validate` jobs.'
    stage_build:
      default: 'build'
      description: 'Defines the build stage. This stage includes the `plan` job.'
    stage_cleanup:
      default: 'cleanup'
      description: 'Defines the cleanup stage. This stage includes the `destroy` and `delete-state` jobs.'

    # Versions
    # This version is only required, because we cannot access the context of the component,
    # see https://gitlab.com/gitlab-org/gitlab/-/issues/438275
    version:
      default: 'latest'
      description: 'Version of this component. Has to be the same as the one in the component include entry.'

    base_os:
      default: 'alpine'
      options:
        - 'alpine'
        - 'debian'
        - '$GITLAB_OPENTOFU_BASE_IMAGE_OS'
      description: 'Base OS of GitLab OpenTofu image.'

    opentofu_version:
      default: '1.8.5'
      options:
        - '1.8.5'
        - '1.8.4'
        - '1.8.3'
        - '1.8.2'
        - '1.8.1'
        - '1.8.0'
        - '1.7.3'
        - '1.6.2'
        - '$OPENTOFU_VERSION'
      description: 'OpenTofu version that should be used.'

    # Images
    image_registry_base:
      default: '$CI_TEMPLATE_REGISTRY_HOST/components/opentofu'
      description: 'Host URI to the job images. Will be combined with `image_name` to construct the actual image URI.'
    # FIXME: not yet possible because of https://gitlab.com/gitlab-org/gitlab/-/issues/438722
    # gitlab_opentofu_image:
    #   # FIXME: This should reference the component tag that is used.
    #   #        Currently, blocked by https://gitlab.com/gitlab-org/gitlab/-/issues/438275
    #   # default: '$CI_TEMPLATE_REGISTRY_HOST/components/opentofu/gitlab-opentofu:$[[ inputs.opentofu_version ]]'
    #   default: '$CI_TEMPLATE_REGISTRY_HOST/components/opentofu/gitlab-opentofu:$[[ inputs.version ]]-opentofu$[[ inputs.opentofu_version ]]'
    #   description: 'Tag of the gitlab-opentofu image.'

    image_name:
      default: 'gitlab-opentofu'
      description: 'Image name for the job images. Hosted under `image_registry_base`.'

    image_digest:
      default: ''
      # FIXME: we cannot use regex yet because of a bug that rejects
      # empty strings from ever being checked against the regex.
      # see https://gitlab.com/gitlab-org/gitlab/-/issues/477707
      # regex: '^(@sha256:[a-z0-9]{64})?$'
      description: 'Image digest of the image you want to use. The format must be `@<image_digest>`, e.g. `@sha256:abc..`, see regex of this input. Please consult the release page at https://gitlab.com/components/opentofu/-/releases to obtain the image digests.'

    # Configuration
    job_name_prefix:
      default: ''
      description: 'Prefix for all job names. Jobs will be hidden if leading with a dot `.`.'
    root_dir:
      default: ${CI_PROJECT_DIR}
      description: 'Root directory for the OpenTofu project.'
    state_name:
      default: default
      description: 'Remote OpenTofu state name.'
    plan_name:
      default: 'destroy-plan'
      description: 'Destroy plan file name.'
    plan_artifacts_access:
      default: 'none'
      description: 'Access level for the plan artifact. See https://docs.gitlab.com/ee/ci/yaml/#artifactsaccess for possible values.'
    auto_destroy:
      default: false
      type: boolean
      description: 'Whether the destroy job is manual or automatically run.'
    var_file:
      default: ''
      type: string
      description: 'Path to a variables files relative to root_dir.'
    fmt_rules:
      default:
        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
          when: never
        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
      type: array
      description: 'Defines the `rules` of the `fmt` job.'
    validate_rules:
      default:
        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
          when: never
        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
      type: array
      description: 'Defines the `rules` of the `validate` job.'
    plan_rules:
      default:
        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
          when: never
        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
      type: array
      description: 'Defines the `rules` of the `plan` job.'
    destroy_rules:
      default:
        - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && "$[[ inputs.auto_destroy ]]" == "true"'
        - when: manual
      type: array
      description: 'Defines the `rules` of the `destroy` job.'
    delete_state_rules:
      default:
        - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
        - when: manual
      type: array
      description: 'Defines the `rules` of the `delete-state` job.'
    warning_on_none_empty_plan:
      default: false
      type: boolean
      description: 'Whether to mark the job with a warning if the plan contains a diff.'

---

include:
  - local: '/templates/fmt.yml'
    inputs:
      as: '$[[ inputs.job_name_prefix ]]fmt'
      stage: $[[ inputs.stage_validate ]]
      version: $[[ inputs.version ]]
      base_os: $[[ inputs.base_os ]]
      opentofu_version: $[[ inputs.opentofu_version ]]
      image_registry_base: $[[ inputs.image_registry_base ]]
      image_name: $[[ inputs.image_name ]]
      image_digest: $[[ inputs.image_digest ]]
      root_dir: $[[ inputs.root_dir ]]
      needs: []
      rules: $[[ inputs.fmt_rules ]]
  - local: '/templates/validate.yml'
    inputs:
      as: '$[[ inputs.job_name_prefix ]]validate'
      stage: $[[ inputs.stage_validate ]]
      version: $[[ inputs.version ]]
      base_os: $[[ inputs.base_os ]]
      opentofu_version: $[[ inputs.opentofu_version ]]
      image_registry_base: $[[ inputs.image_registry_base ]]
      image_name: $[[ inputs.image_name ]]
      image_digest: $[[ inputs.image_digest ]]
      root_dir: $[[ inputs.root_dir ]]
      state_name: $[[ inputs.state_name ]]
      var_file: $[[ inputs.var_file ]]
      rules: $[[ inputs.validate_rules ]]
      cache_policy: pull-push
  - local: '/templates/plan.yml'
    inputs:
      as: '$[[ inputs.job_name_prefix ]]plan'
      stage: $[[ inputs.stage_build ]]
      version: $[[ inputs.version ]]
      base_os: $[[ inputs.base_os ]]
      opentofu_version: $[[ inputs.opentofu_version ]]
      image_registry_base: $[[ inputs.image_registry_base ]]
      image_name: $[[ inputs.image_name ]]
      image_digest: $[[ inputs.image_digest ]]
      root_dir: $[[ inputs.root_dir ]]
      state_name: $[[ inputs.state_name ]]
      plan_name: $[[ inputs.plan_name ]]
      artifacts_access: $[[ inputs.plan_artifacts_access ]]
      destroy: true
      var_file: $[[ inputs.var_file ]]
      rules: $[[ inputs.plan_rules ]]
      cache_policy: pull
      warning_on_none_empty_plan: $[[ inputs.warning_on_none_empty_plan ]]
  - local: '/templates/destroy.yml'
    inputs:
      as: '$[[ inputs.job_name_prefix ]]destroy'
      stage: $[[ inputs.stage_cleanup ]]
      version: $[[ inputs.version ]]
      base_os: $[[ inputs.base_os ]]
      opentofu_version: $[[ inputs.opentofu_version ]]
      image_registry_base: $[[ inputs.image_registry_base ]]
      image_name: $[[ inputs.image_name ]]
      image_digest: $[[ inputs.image_digest ]]
      root_dir: $[[ inputs.root_dir ]]
      state_name: $[[ inputs.state_name ]]
      no_plan: false
      plan_name: $[[ inputs.plan_name ]]
      auto_destroy: $[[ inputs.auto_destroy ]]
      var_file: $[[ inputs.var_file ]]
      rules: $[[ inputs.destroy_rules ]]
      cache_policy: pull
  - local: '/templates/delete-state.yml'
    inputs:
      as: '$[[ inputs.job_name_prefix ]]delete-state'
      stage: $[[ inputs.stage_cleanup ]]
      state_name: $[[ inputs.state_name ]]
      rules: $[[ inputs.delete_state_rules ]]

# FIXME: eventually, we'll have a `needs` input on the `delete-state`
# job template, but the issue is that we cannot default it to something
# meaningful other than `null` - but `null` is also not yet supported, see
# https://gitlab.com/gitlab-org/gitlab/-/issues/440468
'$[[ inputs.job_name_prefix ]]delete-state':
  needs: ['$[[ inputs.job_name_prefix ]]destroy']
