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

NFPMS build fails on windows #2068

Closed
niondir opened this issue Feb 18, 2021 · 18 comments
Closed

NFPMS build fails on windows #2068

niondir opened this issue Feb 18, 2021 · 18 comments
Labels
bug Something isn't working

Comments

@niondir
Copy link

niondir commented Feb 18, 2021

Describe the bug

On windows the build fails with:

release failed after 9.09s error=invalid nfpm config: matching "C:devgopathsrcgithub.comlobaromy-projectbuildmy-project_linux_amd64my-project": file does not exist

To Reproduce

Steps to reproduce the behavior:

nfpms:
  - id: default
    builds:
      - my-project
    formats:
      - deb

Additional context
Works in CI on linux

@niondir niondir added the bug Something isn't working label Feb 18, 2021
@caarlos0
Copy link
Member

hmm, seems to be an issue on fileglob, thanks for reporting 🙏

@jkowalski
Copy link

jkowalski commented Feb 28, 2021

Seeing the same issue. I'd really like to use the recent version of goreleaser because of darwin/amd64 and go1.16, but Windows release got broken after upgrade:

https://github.com/kopia/kopia/runs/1996818039?check_suite_focus=true

Can you prioritize fixing this?

@caarlos0
Copy link
Member

caarlos0 commented Mar 1, 2021

I'm already looking into it, unfortunately I don't have a windows machine to test it which makes things extra difficult and 500% more annoying

@caarlos0
Copy link
Member

caarlos0 commented Mar 1, 2021

can you try with v0.158?

@jkowalski
Copy link

that did not help:

https://github.com/kopia/kopia/runs/2009486429?check_suite_focus=true

⨯ release failed after 47.11s error=invalid nfpm config: glob failed: D:\a\kopia\kopia\dist\kopia_linux_arm64\kopia: stat static prefix D:/D:akopiakopiadistkopia_linux_arm64kopia: open D:akopiakopiadistkopia_linux_arm64kopia: invalid argument
229

It is different than previous failure:

⨯ release failed after 40.64s error=invalid nfpm config: matching "D:akopiakopiadistkopia_linux_arm_6kopia": file does not exist
229

@caarlos0
Copy link
Member

caarlos0 commented Mar 2, 2021

ok, will try to dig into it when I have some time...

@caarlos0
Copy link
Member

caarlos0 commented Mar 2, 2021

may I ask why you are releasing from windows? (curious because you seem to test on other OSes as well)

@caarlos0
Copy link
Member

caarlos0 commented Mar 2, 2021

also worth nothing: #1947 (comment)

@jkowalski
Copy link

jkowalski commented Mar 2, 2021

Actually I'm not releasing on windows (using --skip-publish on Mac and Windows so that only Linux packages that later get pushed). I'm using goreleaser to produce Windows binary that's going to be later embedded in ElectronJS app (it's quite complicated). I think at this point the only reason for using goreleaser on non-linux is defining ldflags in one place which gives me consistent versioning for all OSes.

This is slightly outdated artifact pipeline for my app:
https://github.com/kopia/kopia/blob/master/build_architecture.svg

But since you asked:

What I'd really like would be some ability to override parts of YAML via command line (without having to maintain 3 different goreleaser yaml for each OS), so that I can decide which sections of the config to use/ignore based on flags. This way on Windows/Mac I can skip the whole RPM/DEB mess which I don't really need. Going forward when running on macOS and Windows I'd like to do additional signing steps and notarization (completely different for each OS). Also on a mac I'd want to produce fat binary which has both amd64 and darwin64 in it (requires lipo tool running on macOS). This is going to become quite complex quickly and I'm not sure I'll be able to maintain sane goreleaser pipeline for too long.

@caarlos0
Copy link
Member

caarlos0 commented Mar 2, 2021

Got it. We already have an issue for fat binaries on macos, but honestly, I don't think we'll have a way to skip parts of the config via flags, as it would become fairly complex real quick as well.

This is going to become quite complex quickly and I'm not sure I'll be able to maintain sane goreleaser pipeline for too long.

Doing it on a single file would make it even worse...

@jkowalski
Copy link

But I can’t break the release process into smaller units today, can I? For example to only run the packaging (rpm and deb) without also running the compiler, hooks, etc. Or to run the just signing of binaries that have been prebuilt.

@caarlos0
Copy link
Member

caarlos0 commented Mar 2, 2021

no you can't, but that shouldn't be an issue if you share go cache

@jkowalski
Copy link

FYI: I'm going to disable goreleaser on windows and mac (linux will remain as-is for now) and will switch to makefile script on those platforms.

kopia/kopia#861

@GGP1
Copy link
Contributor

GGP1 commented Mar 9, 2021

Hi @caarlos0, I think this could help.

goreleaser/nfpm -> goreleaser/fileglob -> gobwas/glob -> https://github.com/gobwas/glob/blob/e7a84e9525fe90abcda167b604e483cc959ad4aa/syntax/lexer/lexer.go#L243

func (l *lexer) fetchText(breakers []rune) {
	var data []rune
	var escaped bool

reading:
	for {
		r := l.read()
		if r == eof {
			break
		}

		if !escaped {
			if r == char_escape { // char_escape = "\\"
				escaped = true
				continue
			}

			if runes.IndexRune(breakers, r) != -1 {
				l.unread()
				break reading
			}
		}

		escaped = false
		data = append(data, r)
	}

	if len(data) > 0 {
		l.tokens.push(Token{Text, string(data)})
	}
}

This function is skipping windows path separators "\\" so if the token was "C:\\Users\\test\\desktop", after fetchText() it's "C:Userstestdesktop". In goreleaser/fileglob this last is used to do a system call and there's where it fails.

file: https://github.com/goreleaser/fileglob/blob/main/glob.go#L116

...
pattern = strings.TrimSuffix(...) // "C:\\Users\\test\\desktop"
matcher, err := glob.Compile(pattern, separatorRune) // Here's where fetchText() is called
if err != nil {
	return matches, fmt.Errorf("compile glob pattern: %w", err)
}

// pattern is now "C:Userstestdesktop"

prefix, err := staticPrefix(pattern)
if err != nil {
	return nil, fmt.Errorf("cannot determine static prefix: %w", err)
}

// prefix = "C:Userstestdesktop"

prefixInfo, err := fs.Stat(options.fs, prefix) // System call to "C:Userstestdesktop"
if errors.Is(err, fs.ErrNotExist) {
	if !ContainsMatchers(pattern) {
		return []string{}, fmt.Errorf(`matching "%s%s": %w`, options.prefix, prefix, fs.ErrNotExist) // This is the error that @Niondir got
	}

	return []string{}, nil
}
...

The author suggests using QuoteMeta() to compile but I got the same error with it. Related issues:

gobwas/glob#35
gobwas/glob#36

@caarlos0
Copy link
Member

caarlos0 commented Mar 9, 2021

Thanks @GGP1 !

I think we just need to call filepath.ToSlash on GoReleaser before passing it to fileglob... just haven't tested it yet...

This was referenced Mar 9, 2021
@GGP1
Copy link
Contributor

GGP1 commented Mar 20, 2021

I can confirm it now builds successfully on Windows.

@caarlos0
Copy link
Member

Amazing, thanks for verifying 🙏

@github-actions
Copy link
Contributor

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 20, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants