Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

!reference can't handle complex rules with anchors #1056

Open
robertmclaws opened this issue Nov 14, 2024 · 0 comments
Open

!reference can't handle complex rules with anchors #1056

robertmclaws opened this issue Nov 14, 2024 · 0 comments

Comments

@robertmclaws
Copy link

Current Behavior

Given the following rule file:

# ===============================================
# RWM: BASE RULES
#      These have to be set before they can be referenced anywhere else.
# ===============================================

  # Don't run on Merge Requests.
  merged_only: &merged-only
    - if: '$CI_MERGE_REQUEST_IID'
      when: never

  # Don't run on tagged, in case a build creates a tag.
  not_tagged: &not-tagged
    - if: '$CI_COMMIT_TAG'
      when: never

# ===============================================
# RWM: BRANCH-SPECIFIC RULES
#      These are the rules that will be referenced in the stages.
# ===============================================
  
  # Only runs on main (release branch)
  release_only: &release-only
    - if: '$CI_COMMIT_BRANCH == "main"'
    - *not-tagged

    # Only runs on main after an MR has been merged. (release branch)
  release_only_merged:
    - *release-only
    - *merged-only

  # Only runs on dev (default branch)
  dev_only: &dev-only
    - if: '$CI_COMMIT_BRANCH == "dev"'
    - *not-tagged

  # Only runs on dev after an MR has been merged. (default branch)
  dev_only_merged:
    - *dev-only
    - *merged-only

  # Only runs on feature branches (not main or default branch)
  feature_only:
    - if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "dev"'
      when: never
    - if: '$CI_COMMIT_BRANCH'
    - *merged-only
    - *not-tagged

...that has been imported into a template .yaml in another file, so you can use those rules to set version numbers based on particular pipelines, like this:

set_version:
  stage: .pre
  needs: ["set_patch"]
  environment: ${COMPUTED_ENVIRONMENT}
  variables:
    VERSION_SUFFIX: ""
  rules:
    - !reference [.rules, feature_only]
      when: always
      variables:
        VERSION_SUFFIX: "ci"
    - !reference [.rules, dev_only]
      when: always
      variables:
        VERSION_SUFFIX: "pre"
    - !reference [.rules, release_only]
      when: always
  script:
    - |
      if [ -n "$VERSION_SUFFIX" ]; then
        export DATE=$(date +%Y%m%d)
        export TIME=$(date +%H%M%S)
        export COMPUTED_VERSION="${VERSION_PREFIX}-${VERSION_SUFFIX}-${DATE}-${TIME}"
      else
        export COMPUTED_VERSION="${VERSION_PREFIX}"
      fi
    - echo "COMPUTED_VERSION=$COMPUTED_VERSION" >> version.env
    - echo $COMPUTED_VERSION
  artifacts:
    reports:
      dotenv: version.env
    expire_in: 1h

... the parser will choke on Linux because the rule anchors are not parsed properly, therefore you can only use a single -!reference per stage of the entire build process breaks.

When asked to diagnose the problem, Claude.ai had this to say:

In GitLab's YAML processing on Linux runners, there's a quirk with YAML anchors and multiple rule references. The issue occurs when trying to use multiple YAML anchors with & and * in rules sections.

For example, this can be problematic:

  release_only: &release-only
    - if: '$CI_COMMIT_BRANCH == "main"'
    - *not-tagged    # This reference combined with others can cause issues

  release_only_merged:
    - *release-only  # Combining multiple references like this
    - *merged-only   # can cause parsing problems on Linux

To fix this, it's better to explicitly write out the rules rather than trying to combine multiple references. For example:

  release_only_merged:
    - if: '$CI_COMMIT_BRANCH == "main"'
    - if: '$CI_COMMIT_TAG'
      when: never
    - if: '$CI_MERGE_REQUEST_IID'
      when: never

This is more verbose but more reliable on Linux runners because it avoids the YAML anchor/alias resolution issues that can occur with multiple references.

The issue stems from how GitLab's YAML parser (which is based on Go's YAML library) handles multiple levels of reference resolution on Linux systems, which can sometimes differ from how it works on other platforms.

This is consistently reproducible on GitLab Linux runners are referenced here: https://gitlab.com/gitlab-org/gitlab/-/issues/356911#note_2211037998

Expected Behavior

I expect that Go's YAML parser would function to the same quality level as the one GitLab's Windows runner would use, because Go on Linux is supposed to be a better language running on a better OS.

@robertmclaws robertmclaws changed the title !reference Can't handle complex rules with anchors !reference can't handle complex rules with anchors Nov 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant