mooltiverse / nyx

The one stop semantic release tool
https://github.com/mooltiverse/nyx
Apache License 2.0
116 stars 8 forks source link

Handle "detached head" checkout #280

Closed bertbaron closed 11 months ago

bertbaron commented 11 months ago

On our hosted Gitlab environment (maybe on all gitlab environments?) the branch is checked out as detached head. This makes nyx use HEAD as branch name.

My current workaround is to run git checkout -b $CI_COMMIT_BRANCH prior to any job using nyx but this is a bit uggly.

I noted Semantic Release doesn't have this problem, as this use-case is handled in the env-ci library (TL;DR: in case of HEAD use git show -s --pretty=%d HEAD and take the first origin branch.)

It would be nice if nyx woud be able to handle this case in a similar matter. Personally I would really prefer auto-detection, but if this isn't desirable for some reasons another option could be to provide a branch-override setting.

If I know the preferred solution I might be able to provide a pull request.

flelli commented 11 months ago

Hi @bertbaron ,

that's indeed GitLab's default behavior for all repos and it's a known issue.

On the other hand Nyx doesn't check out the repo because it may lead to unexpected side effects for the user. Instead, it just relies on the repo it's started in.

The solution is to configure your script so that the whole repo is checked out. Here you can find an hint.

bertbaron commented 11 months ago

Thanks for answering so quickly. Unfortunately your suggestion doesn't seem to solve the issue. I do a clone, and the git depth is set to 0. The thing is that gitlab does a checkout of the specific commit hash to ensure it doesn't run on a moving target. This behavior seems under some discussion though, see for example this issue. This is what I see in the logs:

Getting source from Git repository
Fetching changes...
Initialized empty Git repository in /builds/my-project/.git/
Created fresh repository.
Checking out f81c08d1 as detached HEAD (ref is feature/test-nyx)...

A git branch will show that we are working on a detached HEAD and nyx will use HEAD as branch name.

So while there is a chance that this behavior will be improved in the future and while a workaround is possible, the thing is that semantic-release just seems to cope with this behavior.

On the other hand Nyx doesn't check out the repo because it may lead to unexpected side effects for the user. Instead, it just relies on the repo it's started in.

Note that I don't suggest to perform a checkout. That is not what semantic-release does and also not what I do in my workaround. I recreate the branch locally so that it has the expected name.

bertbaron commented 11 months ago

Just a follow-up for anyone who ends up here. My current workaround is:

  variables:
    GIT_DEPTH: 0
    GIT_STRATEGY: clone # not necessary though because k8s runner will always do a clone
  before_script:
    - git checkout $CI_COMMIT_BRANCH
    - git reset --hard $CI_COMMIT_SHA

This works on our Kubernetes Gitlab runners (version 16.7.0) and also allows for pushing committed changes.

I don't think this issue should have been closed, since this simply doesn't seem to work without de workaround. My suggested fix to the code to do something like git show -s --pretty=%d HEAD would however only partly work because it would fail to push committed changes. But better integration with gitlab would really be appreciated because this workaround is not nice and requires to have the git cli tool available on the build image in addition to nyx itself.

playworker commented 9 months ago

We're having the same issue here, self-hosted GitLab/Kubernetes runner also. I'm going to give your workaround a try but I was really hoping to be able to get rid of the git cli build requirement so a "proper" fix would be appreciated

applitect commented 6 months ago

Don't know if you all know this, but I solved this quite easily using the environment variable matcher instead of branch matcher. Here's an example of my releaseTypes items for a branch (written in Kotlinscript--but you get the idea). It uses the gitlab environment variable CI_COMMIT_REF_NAME. Of course I needed to add something for local dev as the gitlab env variables don't exist.

            create("branch") {
                collapseVersions.set(true)
                collapsedVersionQualifier.set("{{#upper}}{{#capture expression=\".*\\/([0-9a-zA-Z-_]+)$\" group=1}}{{#environmentVariable}}CI_COMMIT_REF_NAME{{/environmentVariable}}{{/capture}}{{/upper}}")
                description.set("Feature release {{version}}")
                filterTags.set("^({{configuration.releasePrefix}})?([0-9]\\d*)\\.([0-9]\\d*)\\.([0-9]\\d*)((([0-9a-zA-Z-_]*)(\\.([0-9]\\d*))?)?)\$")
                gitCommit.set("false")
                gitPush.set("false")
                gitTag.set("false")
                matchEnvironmentVariables {
                    put("CI_COMMIT_REF_NAME", ".*(feature|bugfix|improvement)((-|\\/)[0-9a-zA-Z-_]+)?\$")
                }
                publish.set("false")
                publishPreRelease.set("true")
                versionRangeFromBranchName.set(false)
            }