Go Mod Private Repo - go

So I have a private repo that my main.go imports. I'm getting this error when I do a go build:
cannot find module for path
Do I need to do anything special for a private repo? I have been googling and can't find any good information. It works fine with dep.

Do this
git config --global --add url."git#your-repo.com:".insteadOf "https://your-repo.com/"
export GOPRIVATE='your-repo.com'
Make sure your git clone via ssh works.

(Answer duplicated from this SO Question)
I wrote up a solution for this on Medium: Go Modules with Private Git Repositories.
The way we handle it is basically the same as the answer from Alex Pliutau, and the blog goes into some more detail with examples for how to set up your git config with tokens from GitHub/GitLab/BitBucket. It also goes into a working Dockerfile example for using modules with private repos.
The relevant bit for GitLab:
git config --global \
url."https://oauth2:${personal_access_token}#privategitlab.com".insteadOf \
"https://privategitlab.com"
#or
git config --global \
url."https://${user}:${personal_access_token}#privategitlab.com".insteadOf \
"https://privategitlab.com"
I hope it's helpful.

You should use a SSH Key to fetch your repository, check if your SSH key is in system keychain too:
ssh-add -K ~/.ssh/id_rsa

Given that such a private repo is often in active development, I personally simply clone it to the "proper" location in my $GOPATH and use the source management (e.g. git) as you would any other project. Adding the SSH key as in Rodrigo's answer is great, but if you are actively developing the private repo anyway, the extra step to clone it to the right directory isn't by any means a difficult step vs being able to go get it.
So, for example, for a private repo hosted on Github, I would cd to $GOHOME/src/github.com/git-username-for-repo then git clone the-repo

Related

How does golang import github private library dependencies [duplicate]

I'm searching for the way to get $ go get work with private repository, after many google try.
The first try:
$ go get -v gitlab.com/secmask/awserver-go
Fetching https://gitlab.com/secmask/awserver-go?go-get=1
https fetch failed.
Fetching http://gitlab.com/secmask/awserver-go?go-get=1
Parsing meta tags from http://gitlab.com/secmask/awserver-go?go-get=1 (status code 200)
import "gitlab.com/secmask/awserver-go": parse http://gitlab.com/secmask/awserver-go?go-get=1: no go-import meta tags
package gitlab.com/secmask/awserver-go: unrecognized import path "gitlab.com/secmask/awserver-go
Yep, it did not see the meta tags because I could not know how to provide login information.
The second try:
Follow https://gist.github.com/shurcooL/6927554. Add config to .gitconfig.
[url "ssh://git#gitlab.com/"]
insteadOf = https://gitlab.com/
$ go get -v gitlab.com/secmask/awserver-go --> not work
$ go get -v gitlab.com/secmask/awserver-go.git --> work but I got src/gitlab.com/secmask/awserer-go.git
Yes it work but with .git extension with my project name, I can rename it to original but do it everytime $ go get is not so good, is there an otherway?
You have one thing to configure. The example is based on GitHub but this shouldn't change the process:
$ git config --global url.git#github.com:.insteadOf https://github.com/
$ cat ~/.gitconfig
[url "git#github.com:"]
insteadOf = https://github.com/
$ go get github.com/private/repo
For Go modules to work (with Go 1.11 or newer), you'll also need to set the GOPRIVATE variable, to avoid using the public servers to fetch the code:
export GOPRIVATE=github.com/private/repo
The proper way is to manually put the repository in the right place. Once the repository is there, you can use go get -u to update the package and go install to install it. A package named
github.com/secmask/awserver-go
goes into
$GOPATH/src/github.com/secmask/awserver-go
The commands you type are:
cd $GOPATH/src/github.com/secmask
git clone git#github.com:secmask/awserver-go.git
I had a problem with go get using private repository on gitlab from our company.
I lost a few minutes trying to find a solution. And I did find this one:
You need to get a private token at:
https://gitlab.mycompany.com/profile/account
Configure you git to add extra header with your private token:
$ git config --global http.extraheader "PRIVATE-TOKEN: YOUR_PRIVATE_TOKEN"
Configure your git to convert requests from http to ssh:
$ git config --global url."git#gitlab.mycompany.com:".insteadOf "https://gitlab.mycompany.com/"
Finally you can use your go get normally:
$ go get gitlab.com/company/private_repo
For people using private GitLabs, here's a snippet that may help: https://gist.github.com/MicahParks/1ba2b19c39d1e5fccc3e892837b10e21
Also pasted below:
Problem
The go command line tool needs to be able to fetch dependencies from your private GitLab, but authenticaiton is required.
This assumes your private GitLab is hosted at privategitlab.company.com.
Environment variables
The following environment variables are recommended:
export GO111MODULE=on
export GOPRIVATE=privategitlab.company.com # this is comma delimited if using multiple private repos
The above lines might fit best in your shell startup, like a ~/.bashrc.
Explanation
GO111MODULE=on tells Golang command line tools you are using modules. I have not tested this with projects not using
Golang modules on a private GitLab.
GOPRIVATE=privategitlab.company.com tells Golang command line tools to not use public internet resources for the hostnames
listed (like the public module proxy).
Get a personal access token from your private GitLab
To future proof these instructions, please follow this guide from the GitLab docs.
I know that the read_api scope is required for Golang command line tools to work, and I may suspect read_repository as
well, but have not confirmed this.
Set up the ~/.netrc
In order for the Golang command line tools to authenticate to GitLab, a ~/.netrc file is best to use.
To create the file if it does not exist, run the following commands:
touch ~/.netrc
chmod 600 ~/.netrc
Now edit the contents of the file to match the following:
machine privategitlab.company.com login USERNAME_HERE password TOKEN_HERE
Where USERNAME_HERE is replaced with your GitLab username and TOKEN_HERE is replaced with the access token aquired in the
previous section.
Common mistakes
Do not set up a global git configuration with something along the lines of this:
git config --global url."git#privategitlab.company.com:".insteadOf "https://privategitlab.company.com"
I beleive at the time of writing this, the SSH git is not fully supported by Golang command line tools and this may cause
conflicts with the ~/.netrc.
Bonus: SSH config file
For regular use of the git tool, not the Golang command line tools, it's convient to have a ~/.ssh/config file set up.
In order to do this, run the following commands:
mkdir ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/config
chmod 600 ~/.ssh/config
Please note the permissions on the files and directory above are essentail for SSH to work in it's default configuration on
most Linux systems.
Then, edit the ~/.ssh/config file to match the following:
Host privategitlab.company.com
Hostname privategitlab.company.com
User USERNAME_HERE
IdentityFile ~/.ssh/id_rsa
Please note the spacing in the above file matters and will invalidate the file if it is incorrect.
Where USERNAME_HERE is your GitLab username and ~/.ssh/id_rsa is the path to your SSH private key in your file system.
You've already uploaded its public key to GitLab. Here are some instructions.
All of the above did not work for me. Cloning the repo was working correctly but I was still getting an unrecognized import error.
As it stands for Go v1.13, I found in the doc that we should use the GOPRIVATE env variable like so:
$ GOPRIVATE=github.com/ORGANISATION_OR_USER_NAME go get -u github.com/ORGANISATION_OR_USER_NAME/REPO_NAME
Generate a github oauth token here and export your github token as an environment variable:
export GITHUB_TOKEN=123
Set git config to use the basic auth url:
git config --global url."https://$GITHUB_TOKEN:x-oauth-basic#github.com/".insteadOf "https://github.com/"
Now you can go get your private repo.
If you've already got git using SSH, this answer by Ammar Bandukwala is a simple workaround:
$ go get uses git internally. The following one liners will make git and consequently $ go get clone your package via SSH.
Github:
$ git config --global url."git#github.com:".insteadOf "https://github.com/"
BitBucket:
$ git config --global url."git#bitbucket.org:".insteadOf "https://bitbucket.org/"
I came across .netrc and found it relevant to this.
Create a file ~/.netrc with the following content:
machine github.com
login <github username>
password <github password or Personal access tokens >
Done!
Additionally, for latest GO versions, you might need to add this to the environment variables GOPRIVATE=github.com
(I've added it to my .zshrc)
netrc also makes my development environment setup better as my personal github access for HTTPS is been configured now to be used across the machine (just like my SSH configuration).
Generate GitHub personal access tokens: https://github.com/settings/tokens
See this answer for its use with Git on Windows specifically
Ref: netrc man page
If you want to stick with the SSH authentication, then mask the request to use ssh forcefully
git config --global url."git#github.com:".insteadOf "https://github.com/"
More methods for setting up git access: https://gist.github.com/technoweenie/1072829#gistcomment-2979908
That looks like the GitLab issue 5769.
In GitLab, since the repositories always end in .git, I must specify .git at the end of the repository name to make it work, for example:
import "example.org/myuser/mygorepo.git"
And:
$ go get example.org/myuser/mygorepo.git
Looks like GitHub solves this by appending ".git".
It is supposed to be resolved in “Added support for Go's repository retrieval. #5958”, provided the right meta tags are in place.
Although there is still an issue for Go itself: “cmd/go: go get cannot discover meta tag in HTML5 documents”.
After trying multiple solutions my problem still persisted. The final solution after setting up the ~/.netrc and SSH config file, was to add the following line to my ~/.bash_profile
export GOPRIVATE="github.com/[organization]"
I have created a user specific ssh-config, so my user automatically logs in with the correct credentials and key.
First I needed to generate an key-pair
ssh-keygen -t rsa -b 4096 -C "my#email.here"
and saved it to e.g ~/.ssh/id_my_domain. Note that this is also the keypair (private and public) I've connected to my Github account, so mine is stored in~/.ssh/id_github_com.
I have then created (or altered) a file called ~/.ssh/config with an entry:
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_github_com
On another server, the "ssh-url" is admin#domain.com:username/private-repo.git and the entry for this server would have been:
Host domain.com
HostName domain.com
User admin
IdentityFile ~/.ssh/id_domain_com
Just to clarify that you need ensure that the User, Host and HostName is set correctly.
Now I can just browse into the go path and then go get <package>, e.g go get main where the file main/main.go includes the package (from last example above) domain.com:username/private-repo.git.
For me, the solutions offered by others still gave the following error during go get
git#gl.nimi24.com: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
What this solution required
As stated by others:
git config --global url."git#github.com:".insteadOf "https://github.com/"
Removing the passphrase from my ./ssh/id_rsa key which was used for authenticating the connection to the repository. This can be done by entering an empty password when prompted as a response to:
ssh-keygen -p
Why this works
This is not a pretty workaround as it is always better to have a passphrase on your private key, but it was causing issues somewhere inside OpenSSH.
go get uses internally git, which uses openssh to open the connection. OpenSSH takes the certs necessary for authentication from .ssh/id_rsa. When executing git commands from the command line an agent can take care of opening the id_rsa file for you so that you do not have to specify the passphrase every time, but when executed in the belly of go get, this did not work somewhy in my case. OpenSSH wants to prompt you then for a password but since it is not possible due to how it was called, it prints to its debug log:
read_passphrase: can't open /dev/tty: No such device or address
And just fails. If you remove the passphrase from the key file, OpenSSH will get to your key without that prompt and it works
This might be caused by Go fetching modules concurrently and opening multiple SSH connections to Github at the same time (as described in this article). This is somewhat supported by the fact that OpenSSH debug log showed the initial connection to the repository succeed, but later tried it again for some reason and this time opted to ask for a passphrase.
However the solution of using SSH connection multiplexing as put forward in the mentioned article did not work for me. For the record, the author suggested adding the collowing conf to the ssh config file for the affected host:
ControlMaster auto
ControlPersist 3600
ControlPath ~/.ssh/%r#%h:%p
But as stated, for me it did not work, maybe I did it wrong
After setting up GOPRIVATE and git config ...
People may still meeting problems like this when fetching private source:
https fetch: Get "https://private/user/repo?go-get=1": EOF
They can't use private repo without .git extension.
The reason is the go tool has no idea about the VCS protocol of this repo, git or svn or any other, unlike github.com or golang.org them are hardcoded into go's source.
Then the go tool will do a https query before fetching your private repo:
https://private/user/repo?go-get=1
If your private repo has no support for https request, please use replace to tell it directly :
require private/user/repo v1.0.0
...
replace private/user/repo => private.server/user/repo.git v1.0.0
https://golang.org/cmd/go/#hdr-Remote_import_paths
Make sure you remove your previous gitconfigs, I had the same issue.
Previously I executed gitconfig whose token was expired, when you execute the command next time with new token make sure to delete previous one.
first I tried
[url "ssh://git#github.com/"]
insteadOf = https://github.com/
but it didn't worked for my local.
I tried
ssh -t git#github.com
and it shows my ssh is fine.
finally, I fix the problem to tell the go get to consider all as private and use ssh instead of HTTPS.
adding export GOPRIVATE=*
For standalone/final repos, an as a quick fix, why don't just to name the module within the go.mod as a package using your company's domain ... ?
module go.yourcompany.tld/the_repo
go.yourcompany.tld don't even have to exist as a valid (sub)domain...
Also, in the same go.mod you can use replacement block/lines to use private repos previously cloned the same way (within a respective folder cloned also in $GOPATH/src/go.yourcompany.tld) (why do we have to depend too much in GitHub?)
Edit
Needless to say that a private repo usually shall be a private repo, typically a standard git repo, right? With that, why not just to git clone and then go get within the cloned folder?
It's Hard Code In Go Get. Not The Git Reason. So Modify Go Source.
Reason:
repoRootForImportDynamic Will Request: https://....go-get
// RepoRootForImportPath analyzes importPath to determine the
// version control system, and code repository to use.
func RepoRootForImportPath(importPath string, mod ModuleMode, security web.SecurityMode) (*RepoRoot, error) {
rr, err := repoRootFromVCSPaths(importPath, security, vcsPaths)
if err == errUnknownSite {
rr, err = repoRootForImportDynamic(importPath, mod, security)
if err != nil {
err = importErrorf(importPath, "unrecognized import path %q: %v", importPath, err)
}
}
if err != nil {
rr1, err1 := repoRootFromVCSPaths(importPath, security, vcsPathsAfterDynamic)
if err1 == nil {
rr = rr1
err = nil
}
}
So add gitlab domain to vcsPaths will ok.
Download go source code:
vi ./src/cmd/go/internal/vcs/vcs.go
Look for code below:
var vcsPaths = []*vcsPath{
// GitHub
{
pathPrefix: "github.com",
regexp: lazyregexp.New(`^(?P<root>github\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`),
vcs: "git",
repo: "https://{root}",
check: noVCSSuffix,
},
add Code As Follow,XXXX Is Your Domain:
// GitLab
{
pathPrefix: "gitlab.xxxx.com",
regexp: lazyregexp.New(`^(?P<root>gitlab.xxxx\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`),
vcs: "git",
repo: "https://{root}",
check: noVCSSuffix,
},
compile and replace go.

unable to get go package from private github repository

Had this working perfectly before I had my computer refreshed, now I now am unable to pull packages from my orgs private github repository. At this time I only need an ssh private key to clone the repository, i am not aware of any 2fA requirement. I have spent hours already trying to resolve this, from what i read this is what I think should work, omitting sensitive variable values.
Error i was getting was unknown versions, but I changed some stuff and now i am getting "ssh: Could not resolve hostname".
#!/bin/bash
export GOPATH="$HOME/go"
export GOBIN="$HOME/go/bin"
export GOPRIVATE="github.com/${GITHUB_ORG}"
go env -w GO111MODULE="on"
go env -w GOPRIVATE="github.com/${GITHUB_ORG}"
git config --global url."git#github.com:".insteadOf "https://github.com/"
pushd ~/.ssh
eval $(ssh-agent);
ssh-add "${GITHUB_PRIVATE_KEY_PATH}"
popd
go get package "github.com/${GITHUB_ORG}/${GITHUB_REPO}/${GO_PACKAGE}"
The command you posted is missing the url.ssh in the git config.
You can try by changing git to use ssh instead of https so that you can fetch private go repositories using go get.
Suggestion -
git config --global url.ssh://git#github.com/.insteadOf https://github.com/

Is it possible to create a new git repository from a template only using the command line?

Creating a new repo using another as a template is a great function, but I can only see how to use this ability on github.com. Can it be done entirely from command line? Perhaps without a remote?
I would like to use templates for a user to intialise a repo to store their secrets in, and it may not even require a remote, but its very important that it isn't connected to the original template repo for privacy. The .gitignore file and the folder tree provided are the most important functions that I'm hoping to provide the user with this ability.
June 2020: Since a template repository such as this one is a GitHub repository, you can:
clone it
as commented remove the .git folder
git init .
git add .
git commit -m "First commit"
create a new empty repository on GitHub using the new gh CLI: gh repo create
git push -u origin master
That way, everything is done form the command line.
Update Sept. 2020: the other approach through the GitHub CLI tool gh, and mentions in Ben Gubler's answer, stems from PR 1590: "Create repositories from a template repo" from Mislav Marohnić and Colin Shum.
(merged in commit 99372f0)
gh repo create <new-repo-name> --template="<link-to-template-repo>"
# OR
gh repo create <new-repo-name> --template="<owner/template-repo>"
Try gh repo create myrepo --template someuser/sometemplate
The existing answers are great for simple use cases, but I wanted to do something a bit more specific to my use-case:
Reuse an existing repo (GitHub template)
Keep the history of the source
Clone locally + create repo on GitHub
Configure the new repo automatically (private, default description, enable squash, ...)
Configure the remote and fetch branches from all remotes (to keep the new project up-to-date with the template easily)
Through a single command that I can quickly adapt to deploy new projects
Here is what I came up with:
cd ~/dev \
&& gh repo create NEW_REPO \
--template OWNER/SOURCE_REPO \
--private \
--clone \
&& cd NEW_REPO \
&& gh repo edit OWNER/NEW_REPO \
--delete-branch-on-merge \
--description "Default description for NEW_REPO." \
--enable-squash-merge \
&& gh repo sync OWNER/NEW_REPO \
--source OWNER/SOURCE_REPO \
--force \
&& git remote add template git#github.com:OWNER/SOURCE_REPO.git \
&& git fetch --all
Note that I first change directory to ~/dev, you might want to change that.
Create your template repo. Put it (the contents of the .git dir if it's not bare) somewhere they can reach with a filesystem path. Clean out anything you don't want. Then they can git init --template=/path/to/that/template.
Since the template directory isn't named .git you can even make a repository to track it and publish that, then people can clone your template and use its work tree as a template.

How can I use private gems(GemFury) in a docker container?

I'm trying to run some ruby scripts for automating exports. Since these run remotely we build them in a Docker container and push them to iron worker.
We use GemFury for hosting some essential private gems for these scripts.
To keep the credentials for GemFury out of Git we use a global bundle config bundle config gem.fury.io MY_SECRET_TOKEN.
How can I set the config for bundle so it will pull in gems from GemFury without having them show in source control?
Set the global bundle config property as an application specific property. Push the changes to the public repository. Update the SECRET_TOKEN value in the bundle-config file ($APP_DIR/.bundle/config) and run the $ git update-index --assume-unchanged <file> command to remove the file from git tracking and prevent updating the actual SECRET_TOKEN value in the public repository.
$ bundle config --local gem.fury.io SECRET_TOKEN
$ git commit -a -m "adding application bundle config properties"
$ git push origin master
$ bundle config --local gem.fury.io d1320f07ac50d1033e8ef5fbd56adf360ec103b2
$ git update-index --assume-unchanged $APP_DIR/.bundle/config
This creates a template file on the public repository. Provide instructions to repository contributors to add the secret token and execute the same --assume-unchanged command.
Example Files
$APP_DIR/.bundle/config file on public github repo:
---
BUNDLE_GEM__FURY__IO: MY_SECRET_TOKEN
$APP_DIR/.bundle/config file a local machine
---
BUNDLE_GEM__FURY__IO: d1320f07ac50d1033e8ef5fbd56adf360ec103b2
See bundle-cofig documentation for clarification and more detail
NOTE: The disadvantage to this approach is two fold:
Developers who clone the repository and need the SECRET_TOKEN value will have to obtain it by some external manual process (good security practices, but a pain to set up)
If you need to add more bundle-config properties, you will have to run git update-index --no-assume-unchanged <file> to enable tracking, and revert all of the private values to their pseudo values. This template method, also risks that contributors forget to disable tracking on the file and push their private values to the public repo (but at least they won't be your secret values)
The advantage of this template approach is that you are giving the developers as much as possible to be able to start contributing to the repository.

cloning private repo using ruby-git

I'm using ruby-git to programmatically perform some operations git repos hosted on GitHub.
Everything works fine when I do it on public repos however, I'm not able to clone private repos even if I have created an ssh key on the machine when the code runs and added the public one on GitHub. To make sure the key is properly setup I have cloned the repo directly from the terminal and the repo was successfully cloned. The key has also been added to the ssh-agent and $SSH_AUTH_SOCK is set.
So, I think the issue is related to how I use the ruby-git gem.
Here my (simple) code
#repo = Git.clone("git#github.com:#{repo_full_name}.git", path)
And here, if it may be helpful teh error
Git::GitExecuteError: git clone '--' 'git#github.com:USER/REPO.git' '/var/www/repo-root/USER/REPO' 2>&1:Cloning into '/var/www/repo-root/USER/REPO'... Permission denied (publickey). fatal: Could not read
Am I missing anything here?
Thanks
Do you have your Git env config pointing at your ssh key path?
Git.configure do |config|
# If you want to use a custom git binary
config.binary_path = '/git/bin/path'
# If you need to use a custom SSH script
config.git_ssh = '/path/to/ssh/script'
end

Resources