spec:
  inputs:
    # Job and Stage name
    as:
      default: 'plan'
      description: 'Defines the name of this job.'
    stage:
      default: 'build'
      description: 'Defines the stage that this job will belong to.'

    # 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
    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: 'plan'
      description: 'The name of the plan cache and plan json file.'
    destroy:
      default: false
      type: boolean
      description: 'Indicate if the plan should be a destroy plan. You may want to change the `plan_name` input to `destroy-plan` which is the default for the destroy job.'
    artifacts_access:
      default: 'none'
      description: 'Access level for the plan artifact. See https://docs.gitlab.com/ee/ci/yaml/#artifactsaccess for possible values.'
    var_file:
      default: ''
      type: string
      description: 'Path to a variables files relative to root_dir.'
    rules:
      # FIXME: eventually, we'll want to define `null` as the default,
      # but this is NOT support yet, see
      # https://gitlab.com/gitlab-org/gitlab/-/issues/440468
      default: [{when: on_success}]
      type: array
      description: 'Defines the `rules` of the job.'
    cache_policy:
      default: pull-push
      type: string
      description: 'Defines the cache policy of the job.'
    warning_on_non_empty_plan:
      default: false
      type: boolean
      description: 'Whether to mark the job with a warning if the plan contains a diff.'

---

# NOTE: the two following jobs are necessary to implement the abstraction logic
# required for the `warning_on_non_empty_plan` input.
# Without any kind of flow control support for the GitLab CI YAML we cannot infer
# another value from the input. However, we can clearly apply "inheritance" to
# customize behavior related to the CI keywords that have otherwise nothing
# in common with the inputs value.
'.$[[ inputs.as ]]:detailed_exitcode:warning:false':
  extends: null

'.$[[ inputs.as ]]:detailed_exitcode:warning:true':
  variables:
    OPENTOFU_COMPONENT_USE_DETAILED_EXITCODE: '$[[ inputs.warning_on_non_empty_plan ]]'
    # NOTE: we rely on correct exitcode reporting behavior for the `warning_on_non_empty_plan` input
    # behavior. However, when using bash the runner does not work properly without setting
    # the feature flag below to `true`.
    FF_USE_NEW_BASH_EVAL_STRATEGY: 'true'
  allow_failure:
    # NOTE: tofu plan -detailed-exitcode return 2 as exit code
    # when the plan is non-empty.
    exit_codes: [2]
  artifacts:
    # NOTE: we require to always upload artifacts, because when `warning_on_non_empty_plan` is set enabled
    # and there is a non-empty plan we have an exit code of `2` which is considered a (failure),
    # but we still want to upload all the artifacts.
    when: always

'$[[ inputs.as ]]':
  stage: $[[ inputs.stage ]]
  extends:
    # NOTE: see the comment above. This is to support the `warning_on_non_empty_plan` input.
    - '.$[[ inputs.as ]]:detailed_exitcode:warning:$[[ inputs.warning_on_non_empty_plan ]]'
  environment:
    name: $[[ inputs.state_name ]]
    action: prepare
  resource_group: $[[ inputs.state_name ]]
  artifacts:
    # Terraform's cache files can include secrets which can be accidentally exposed.
    # Please exercise caution when utilizing secrets in your Terraform infrastructure and
    # consider limiting access to artifacts or take other security measures to protect sensitive information.
    # See https://docs.gitlab.com/ee/ci/yaml/#artifactsaccess for possible values.
    access: '$[[ inputs.artifacts_access ]]'
    paths:
      - $TF_ROOT/$[[ inputs.plan_name ]].cache
    reports:
      terraform: $TF_ROOT/$[[ inputs.plan_name]].json
  rules: $[[ inputs.rules ]]
  cache:
    key: "$__CACHE_KEY_HACK"
    policy: $[[ inputs.cache_policy ]]
    paths:
      - $TF_ROOT/.terraform/
  variables:
    # FIXME: work around to make slashes work in `cache:key`. see https://gitlab.com/gitlab-org/gitlab/-/issues/439898
    __CACHE_KEY_HACK: "$[[ inputs.root_dir ]]"
    TF_ROOT: $[[ inputs.root_dir ]]
    TF_STATE_NAME: $[[ inputs.state_name ]]
    TF_PLAN_NAME: $[[ inputs.plan_name ]]
    OPENTOFU_COMPONENT_PLAN_WITH_JSON: true
    OPENTOFU_COMPONENT_VAR_FILE: '$[[ inputs.var_file ]]'
  image:
    name: '$[[ inputs.image_registry_base ]]/$[[ inputs.image_name ]]:$[[ inputs.version ]]-opentofu$[[ inputs.opentofu_version ]]-$[[ inputs.base_os ]]$[[ inputs.image_digest ]]'
  script:
    - "args=\"\"\nif [ \"$[[ inputs.destroy ]]\" == \"true\" ]; then \n  echo \"Planning for a destroy\"\n  args=\"-destroy\"\nfi\n"
    - gitlab-tofu plan $args
