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

rake release failed to push tag due to local out of date branch #7818

Closed
ryancyq opened this issue Jul 1, 2024 · 10 comments
Closed

rake release failed to push tag due to local out of date branch #7818

ryancyq opened this issue Jul 1, 2024 · 10 comments
Labels

Comments

@ryancyq
Copy link

ryancyq commented Jul 1, 2024

Describe the problem as clearly as you can

Encountered a git push issue with bundle rake release when it is being called in the CI environment, especially with the GitHub Action provided by RubyGems (https://github.com/rubygems/release-gem).

Due to the fix in #4309, the release task will always push branch to remote when pushing the tag.

However, in the CI environment where a release task is triggered after the test suite has passed, the git push command might be pushing the out of date branch and causing git to raise an error. As a result, the release will fail.

It is also impossible to retry the release task for an older commit in this case, regardless of the CI environment or local machine setup.

Did you try upgrading rubygems & bundler?

Yes

Post steps to reproduce the problem

  1. git commit with gemspec version changes
  2. continue adding commits on code changes (excluding gemspec version)
  3. git push to origin
  4. git checkout the older commit with gemspec version changes
  5. run bundle exec rake release

Which command did you run?

bundle exec rake release

What were you expecting to happen?

bundle exec rake release push tag to remote successfully as long as current commit exists in remote

What actually happened?

bundle exec rake release is pushing remote tag and branch all the time.

Tagged v0.5.0.
Untagging v0.5.0 due to error.
rake aborted!
Running `git push origin refs/heads/main` failed with the following output:

To https://github.com/some_org/some_repo
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'https://github.com/some_org/some_repo'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

/home/runner/work/some_org/some_repo/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/exe/rake:27:in `<top (required)>'
/opt/hostedtoolcache/Ruby/3.3.1/x64/bin/bundle:[25](https://github.com/some_org/some_repo/actions/runs/9717391434/job/26823056030#step:5:29):in `load'
/opt/hostedtoolcache/Ruby/3.3.1/x64/bin/bundle:25:in `<main>'
Tasks: TOP => release => release:source_control_push
(See full trace by running task with --trace)
Error: Process completed with exit code 1.

If not included with the output of your command, run bundle env and paste the output below

Environment

Bundler       2.5.14
  Platforms   ruby, arm64-darwin-23
Ruby          3.3.1p55 (2024-04-23 revision c56cd86388092faec079981f779f140717020d58) [arm64-darwin-23]
  Full Path   /Users/some_user/.rbenv/versions/3.3.1/bin/ruby
  Config Dir  /Users/some_user/.rbenv/versions/3.3.1/etc
RubyGems      3.5.14
  Gem Home    /Users/some_user/.rbenv/versions/3.3.1/lib/ruby/gems/3.3.0
  Gem Path    /Users/some_user/.gem/ruby/3.3.0:/Users/some_user/.rbenv/versions/3.3.1/lib/ruby/gems/3.3.0
  User Home   /Users/some_user
  User Path   /Users/some_user/.gem/ruby/3.3.0
  Bin Dir     /Users/some_user/.rbenv/versions/3.3.1/bin
Tools         
  Git         2.39.3 (Apple Git-146)
  RVM         not installed
  rbenv       rbenv 1.2.0
  chruby      not installed

Bundler Build Metadata

Built At          2024-06-21
Git SHA           72920bc230
Released Version  true

Bundler settings

gem.changelog
  Set for the current user (/Users/some_user/.bundle/config): false
gem.ci
  Set for the current user (/Users/some_user/.bundle/config): false
gem.coc
  Set for the current user (/Users/some_user/.bundle/config): false
gem.linter
  Set for the current user (/Users/some_user/.bundle/config): "rubocop"
gem.mit
  Set for the current user (/Users/some_user/.bundle/config): false
gem.test
  Set for the current user (/Users/some_user/.bundle/config): false
@ryancyq ryancyq added the Bundler label Jul 1, 2024
@deivid-rodriguez
Copy link
Member

Hei, thanks for the report. Can you explain, with git commands, what is it that Bundler used to run that works in your situation vs what we run now? I think a long time ago, we used to run git push --tags, does that work in your situation (current commit but also more recent commits present upstream?). Does this depend on git remote.*.push configuration or some other configuration?

@ryancyq
Copy link
Author

ryancyq commented Jul 3, 2024

Hi @deivid-rodriguez, I wasn't using rake release until the release of https://github.com/rubygems/release-gem.

Before that, I used the following steps to publish a gem:

  • Made manual changes to the gemspec version and tagged the version with git push --tags
  • Followed by gem build *.gemspec and gem push *.gem (this was triggered as part of CI)

In this case, either git push --tags or git push origin refs/tags/XXX would still work for me.
The issue appears when the release task tries to push the current branch to the remote.

I saw the note on missing logic to infer the remote in #4309. I'm just wondering if it will be fixed to push the current branch only when it has not yet been pushed.

@deivid-rodriguez
Copy link
Member

Ok, thanks for letting me know, that makes sense.

Just checking how the implementation again, I think we have never supported your current situation, since even when we did git push --tags, we were also running git push without arguments, which I assume will fail in your situation too.

That said, I think it'd be reasonable to cover your case by only pushing the current branch if the current commit is not already part of it. Would you consider sending us a patch to implement that?

@ryancyq
Copy link
Author

ryancyq commented Jul 3, 2024

@deivid-rodriguez I would be happy to work on a patch for it.

I am planning to use git status -sb (git > 1.8.5) to match "#{remote}/#{current_branch}" to check if the current branch has an upstream branch.

If this sounds good to you, I will submit a PR using this approach.

@deivid-rodriguez
Copy link
Member

Happy with any solution you come up with, but will that work? If I understand correctly, this is about detecting if the current HEAD commit is already present in the remote branch, not about detecting the proper remote branch. My understanding is that the proper remote branch to push to is already resolved by git automatically?

@ryancyq
Copy link
Author

ryancyq commented Jul 4, 2024

Let me elaborate in more detail. The example of matching the current branch with the remote branch was one of the possible scenarios.

I tried a few scenarios on my end with git status -sb:

  1. When the current branch does not have a remote branch:
    ## fix/bug
  2. When the current branch has a remote branch but the current HEAD commit already exists in the remote branch:
    ## fix/bug...origin/fix/bug or ## fix/bug...origin/fix/bug [behind 2]
  3. When the current branch has a remote branch but the current HEAD commit does not exist in the remote branch:
    ## fix/bug...origin/fix/bug [ahead 1]
  4. When the current branch has a remote branch but the current HEAD commit does not exist in the remote branch and there are additional commits present upstream:
    ## fix/bug...origin/fix/bug [ahead 2, behind 1]

My assumption for the fix is to support scenarios 3 and 4 only. Regarding scenario 4, we could let the "git push #{remote} refs/heads/#{current_branch}" fail through and rollback the git tag operation.

Another question I have in mind is whether a git fetch operation is needed. However, given that the current tagging operation doesn't do that, we probably can leave it the same for pushing the HEAD commit.

@deivid-rodriguez
Copy link
Member

Oh, I see!

You'll use git status -sb to parse "ahead" and "behind" information 👍. Just to make sure I understand the different scenarios, I think "Scenario 3" is already properly supported, and rake release will push the current branch normally?

My current thoughts are:

  • If this is about parsing the non structured output of a git command anyways, should we instead parse the git push non structured error message to detect the situation we want to support? I guess we can use either git status --porcelain or git push --porcelain for more stable parsing, by the way.

  • Is this actually something we want to add? In your original scenario, aren't you leaving unreleased commits? Is that really want you want or could be a mistake on your side? Would it be better to make the release right after committing gemspec version changes and then add the other commits, if it is actually intended?

@ryancyq
Copy link
Author

ryancyq commented Jul 4, 2024

Good point on the --porcelain part 👍 , we definitely should be using that instead.

To summarize the issue I faced, the current behavior for rake release is to perform git push origin refs/heads/main in all four scenarios. However, I believe it should skip pushing the HEAD commit for scenario 2 and continue with pushing the tag, since the tag is being created during rake release.

In the original scenario, all the commits were being pushed to remote. For example, the commit of the gemspec is pushed to remote, which triggers the test suite to run. This is followed by a rake release after some delay, depending on the time taken by the test suite. Additional commits being pushed to remote within the delay would cause the rake release to fail.

@ryancyq
Copy link
Author

ryancyq commented Jul 5, 2024

Hi @deivid-rodriguez i just created a PR #7835 for this issue and written down the specific scenario in the test.

@ryancyq
Copy link
Author

ryancyq commented Jul 6, 2024

Referring to #7835 (comment), I agreed with @deivid-rodriguez that this probably shouldn't be a concern for the release task (in #7818 (comment)).

To workaround this behavior in my use case (e.g. the CI environment), i have resorted to create a new releases/vX.X.X branch as placeholder before running rake release and clean up the release branch after the rake task is completed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants