Add support for cloning private repos as part of automation API (#5333)
This commit is contained in:
parent
0504780346
commit
aafe84d823
|
@ -9,6 +9,11 @@ CHANGELOG
|
||||||
asking interactively as the final option.
|
asking interactively as the final option.
|
||||||
[#5327](https://github.com/pulumi/pulumi/pull/5327)
|
[#5327](https://github.com/pulumi/pulumi/pull/5327)
|
||||||
|
|
||||||
|
- feat(autoapi): Add support for working with private Git repos. Either `SSHPrivateKeyPath`,
|
||||||
|
`PersonalAccessToken` or `UserName` and `Password` can be pushed to the `auto.GitRepo` struct
|
||||||
|
when interacting with a private repo
|
||||||
|
[#5333](https://github.com/pulumi/pulumi/pull/5333)
|
||||||
|
|
||||||
## 2.10.0 (2020-09-10)
|
## 2.10.0 (2020-09-10)
|
||||||
|
|
||||||
- feat(autoapi): add Upsert methods for stacks
|
- feat(autoapi): add Upsert methods for stacks
|
||||||
|
|
|
@ -18,6 +18,7 @@ package auto
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
@ -205,6 +206,63 @@ func ExampleGitRepo() {
|
||||||
NewStackRemoteSource(ctx, fqsn, repo, Project(project))
|
NewStackRemoteSource(ctx, fqsn, repo, Project(project))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleGitRepo_personalAccessToken() {
|
||||||
|
ctx := context.Background()
|
||||||
|
pName := "go_remote_proj"
|
||||||
|
fqsn := FullyQualifiedStackName("myOrg", pName, "myStack")
|
||||||
|
|
||||||
|
// Get the Sourcecode Repository PERSONAL_ACCESS_TOKEN
|
||||||
|
token, _ := os.LookupEnv("PERSONAL_ACCESS_TOKEN")
|
||||||
|
|
||||||
|
repo := GitRepo{
|
||||||
|
URL: "https://github.com/pulumi/test-repo.git",
|
||||||
|
ProjectPath: "goproj",
|
||||||
|
Auth: &GitAuth{
|
||||||
|
PersonalAccessToken: token,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize a stack from the git repo, specifying our project override
|
||||||
|
NewStackRemoteSource(ctx, fqsn, repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleGitRepo_privateKeyPath() {
|
||||||
|
ctx := context.Background()
|
||||||
|
pName := "go_remote_proj"
|
||||||
|
fqsn := FullyQualifiedStackName("myOrg", pName, "myStack")
|
||||||
|
|
||||||
|
repo := GitRepo{
|
||||||
|
URL: "https://github.com/pulumi/test-repo.git",
|
||||||
|
ProjectPath: "goproj",
|
||||||
|
Auth: &GitAuth{
|
||||||
|
SSHPrivateKeyPath: "/Users/myuser/.ssh/id_rsa",
|
||||||
|
Password: "PrivateKeyPassword",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize a stack from the git repo, specifying our project override
|
||||||
|
NewStackRemoteSource(ctx, fqsn, repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleGitRepo_usernameAndPassword() {
|
||||||
|
ctx := context.Background()
|
||||||
|
pName := "go_remote_proj"
|
||||||
|
fqsn := FullyQualifiedStackName("myOrg", pName, "myStack")
|
||||||
|
|
||||||
|
repo := GitRepo{
|
||||||
|
URL: "https://github.com/pulumi/test-repo.git",
|
||||||
|
ProjectPath: "goproj",
|
||||||
|
Auth: &GitAuth{
|
||||||
|
// This will use a username and password combination for the private repo
|
||||||
|
Username: "myuser",
|
||||||
|
Password: "myPassword1234!",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize a stack from the git repo, specifying our project override
|
||||||
|
NewStackRemoteSource(ctx, fqsn, repo)
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleLocalWorkspace() {
|
func ExampleLocalWorkspace() {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
// create a workspace from a local project
|
// create a workspace from a local project
|
||||||
|
|
|
@ -21,11 +21,57 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
git "gopkg.in/src-d/go-git.v4"
|
git "gopkg.in/src-d/go-git.v4"
|
||||||
"gopkg.in/src-d/go-git.v4/plumbing"
|
"gopkg.in/src-d/go-git.v4/plumbing"
|
||||||
|
"gopkg.in/src-d/go-git.v4/plumbing/transport/http"
|
||||||
|
"gopkg.in/src-d/go-git.v4/plumbing/transport/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupGitRepo(ctx context.Context, workDir string, repoArgs *GitRepo) (string, error) {
|
func setupGitRepo(ctx context.Context, workDir string, repoArgs *GitRepo) (string, error) {
|
||||||
|
cloneOptions := &git.CloneOptions{
|
||||||
|
URL: repoArgs.URL,
|
||||||
|
}
|
||||||
|
|
||||||
|
if repoArgs.Auth != nil {
|
||||||
|
|
||||||
|
authDetails := repoArgs.Auth
|
||||||
|
// Each of the authentication options are mutually exclusive so let's check that only 1 is specified
|
||||||
|
if (authDetails.SSHPrivateKeyPath != "" && authDetails.PersonalAccessToken != "") ||
|
||||||
|
(authDetails.SSHPrivateKeyPath != "" && authDetails.Username != "") ||
|
||||||
|
(authDetails.PersonalAccessToken != "" && authDetails.Username != "") {
|
||||||
|
return "", errors.New("please specify one authentication option of `Personal Access Token`, " +
|
||||||
|
"`Username\\Password` or `SSH Private Key Path`")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Firstly we will try to check that an SSH Private Key Path has been specified
|
||||||
|
if authDetails.SSHPrivateKeyPath != "" {
|
||||||
|
publicKeys, err := ssh.NewPublicKeysFromFile("git", repoArgs.Auth.SSHPrivateKeyPath, repoArgs.Auth.Password)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, "unable to use SSH Private Key")
|
||||||
|
}
|
||||||
|
|
||||||
|
cloneOptions.Auth = publicKeys
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then we check to see if a Personal Access Token has been specified
|
||||||
|
// the username for use with a PAT can be *anything* but an empty string
|
||||||
|
// so we are setting this to `git`
|
||||||
|
if authDetails.PersonalAccessToken != "" {
|
||||||
|
cloneOptions.Auth = &http.BasicAuth{
|
||||||
|
Username: "git",
|
||||||
|
Password: repoArgs.Auth.PersonalAccessToken,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// then we check to see if a username and a password has been specified
|
||||||
|
if authDetails.Password != "" && authDetails.Username != "" {
|
||||||
|
cloneOptions.Auth = &http.BasicAuth{
|
||||||
|
Username: repoArgs.Auth.Username,
|
||||||
|
Password: repoArgs.Auth.Password,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// clone
|
// clone
|
||||||
repo, err := git.PlainCloneContext(ctx, workDir, false, &git.CloneOptions{URL: repoArgs.URL})
|
repo, err := git.PlainCloneContext(ctx, workDir, false, cloneOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "unable to clone repo")
|
return "", errors.Wrap(err, "unable to clone repo")
|
||||||
}
|
}
|
||||||
|
|
|
@ -584,6 +584,25 @@ type GitRepo struct {
|
||||||
CommitHash string
|
CommitHash string
|
||||||
// Optional function to execute after enlisting in the specified repo.
|
// Optional function to execute after enlisting in the specified repo.
|
||||||
Setup SetupFn
|
Setup SetupFn
|
||||||
|
// GitAuth is the different Authentication options for the Git repository
|
||||||
|
Auth *GitAuth
|
||||||
|
}
|
||||||
|
|
||||||
|
// GitAuth is the authentication details that can be specified for a private Git repo.
|
||||||
|
// There are 3 different authentication paths:
|
||||||
|
// * PersonalAccessToken
|
||||||
|
// * SSHPrivateKeyPath (and it's potential password)
|
||||||
|
// * Username and Password
|
||||||
|
// Only 1 authentication path is valid. If more than 1 is specified it will result in an error
|
||||||
|
type GitAuth struct {
|
||||||
|
// The absolute path to a private key for access to the git repo
|
||||||
|
SSHPrivateKeyPath string
|
||||||
|
// The password that pairs with a username or as part of an SSH Private Key
|
||||||
|
Password string
|
||||||
|
// PersonalAccessToken is a Git personal access token in replacement of your password
|
||||||
|
PersonalAccessToken string
|
||||||
|
// Username is the username to use when authenticating to a git repository
|
||||||
|
Username string
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetupFn is a function to execute after enlisting in a git repo.
|
// SetupFn is a function to execute after enlisting in a git repo.
|
||||||
|
|
Loading…
Reference in a new issue