Skip to content

Commit

Permalink
Merge pull request gruntwork-io#43 from jniesen/master
Browse files Browse the repository at this point in the history
support github enterprise by allowing custom api and base urls
  • Loading branch information
brikis98 authored Aug 11, 2018
2 parents 42132dc + bb810bf commit ad606a2
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 44 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ authentication. Fetch makes it possible to handle all of these cases with a one-
- Download a binary asset from a specific release.
- Verify the SHA256 or SHA512 checksum of a binary asset.
- Download from public repos, or from private repos by specifying a [GitHub Personal Access Token](https://help.github.com/articles/creating-an-access-token-for-command-line-use/).
- Download from GitHub Enterprise.
- When specifying a git tag, you can can specify either exactly the tag you want, or a [Tag Constraint Expression](#tag-constraint-expressions) to do things like "get the latest non-breaking version" of this repo. Note that fetch assumes git tags are specified according to [Semantic Versioning](http://semver.org/) principles.

#### Quick examples
Expand Down Expand Up @@ -75,6 +76,8 @@ The supported options are:
downloading from private GitHub repos. **NOTE:** fetch will also look for this token using the `GITHUB_OAUTH_TOKEN`
environment variable, which we recommend using instead of the command line option to ensure the token doesn't get
saved in bash history.
- `--github-api-version` (**Optional**): Used when fetching an artifact from a GitHub Enterprise instance.
Defaults to `v3`. This is ignored when fetching from GitHub.com.

The supported arguments are:

Expand Down Expand Up @@ -152,6 +155,14 @@ Download the release asset `foo.exe` from a GitHub release where the tag is exac
fetch --repo="https://github.com/foo/bar" --tag="0.1.5" --release-asset="foo.exe" /tmp
```

#### Usage Example 7

Download the release asset `foo.exe` from a GitHub release hosted on a GitHub Enterprise instance running at `ghe.mycompany.com` where the tag is exactly `0.1.5`, and save it to `/tmp`:

```
fetch --repo="https://ghe.mycompany.com/foo/bar" --tag="0.1.5" --release-asset="foo.exe" /tmp
```

## License

This code is released under the MIT License. See [LICENSE.txt](/LICENSE.txt).
Expand Down
6 changes: 5 additions & 1 deletion checksum_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ const SAMPLE_RELEASE_ASSET_CHECKSUM_SHA512="28d9e487c1001e3c28d915c9edd3ed37632f

func TestVerifyReleaseAsset(t *testing.T) {
tmpDir := mkTempDir(t)
testInst := GitHubInstance{
BaseUrl: "github.com",
ApiUrl: "api.github.com",
}

githubRepo, err := ParseUrlIntoGitHubRepo(SAMPLE_RELEASE_ASSET_GITHUB_REPO_URL, "")
githubRepo, err := ParseUrlIntoGitHubRepo(SAMPLE_RELEASE_ASSET_GITHUB_REPO_URL, "", testInst)
if err != nil {
t.Fatalf("Failed to parse sample release asset GitHub URL into Fetch GitHubRepo struct: %s", err)
}
Expand Down
67 changes: 50 additions & 17 deletions github.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
package main

import (
"net/http"
"fmt"
"bytes"
"encoding/json"
"regexp"
"os"
"fmt"
"io"
"net/http"
"net/url"
"os"
"regexp"
)

type GitHubRepo struct {
Url string // The URL of the GitHub repo
Owner string // The GitHub account name under which the repo exists
Name string // The GitHub repo name
Token string // The personal access token to access this repo (if it's a private repo)
Url string // The URL of the GitHub repo
BaseUrl string // The Base URL of the GitHub Instance
ApiUrl string // The API Url of the GitHub Instance
Owner string // The GitHub account name under which the repo exists
Name string // The GitHub repo name
Token string // The personal access token to access this repo (if it's a private repo)
}

type GitHubInstance struct {
BaseUrl string
ApiUrl string
}

// Represents a specific git commit.
Expand Down Expand Up @@ -62,11 +70,34 @@ type GitHubReleaseAsset struct {
Name string
}

func ParseUrlIntoGithubInstance(repoUrl string, apiv string) (GitHubInstance, *FetchError) {
var instance GitHubInstance

u, err := url.Parse(repoUrl)
if err != nil {
return instance, newError(GITHUB_REPO_URL_MALFORMED_OR_NOT_PARSEABLE, fmt.Sprintf("GitHub Repo URL %s is malformed.", repoUrl))
}

baseUrl := u.Host
apiUrl := "api.github.com"
if baseUrl != "github.com" && baseUrl != "www.github.com" {
fmt.Printf("Assuming GitHub Enterprise since the provided url (%s) does not appear to be for GitHub.com\n", repoUrl)
apiUrl = baseUrl + "/api/" + apiv
}

instance = GitHubInstance{
BaseUrl: baseUrl,
ApiUrl: apiUrl,
}

return instance, nil
}

// Fetch all tags from the given GitHub repo
func FetchTags(githubRepoUrl string, githubToken string) ([]string, *FetchError) {
func FetchTags(githubRepoUrl string, githubToken string, instance GitHubInstance) ([]string, *FetchError) {
var tagsString []string

repo, err := ParseUrlIntoGitHubRepo(githubRepoUrl, githubToken)
repo, err := ParseUrlIntoGitHubRepo(githubRepoUrl, githubToken, instance)
if err != nil {
return tagsString, wrapError(err)
}
Expand Down Expand Up @@ -96,10 +127,10 @@ func FetchTags(githubRepoUrl string, githubToken string) ([]string, *FetchError)
}

// Convert a URL into a GitHubRepo struct
func ParseUrlIntoGitHubRepo(url string, token string) (GitHubRepo, *FetchError) {
func ParseUrlIntoGitHubRepo(url string, token string, instance GitHubInstance) (GitHubRepo, *FetchError) {
var gitHubRepo GitHubRepo

regex, regexErr := regexp.Compile("https?://(?:www\\.)?github.com/(.+?)/(.+?)(?:$|\\?|#|/)")
regex, regexErr := regexp.Compile("https?://(?:www\\.)?" + instance.BaseUrl + "/(.+?)/(.+?)(?:$|\\?|#|/)")
if regexErr != nil {
return gitHubRepo, newError(GITHUB_REPO_URL_MALFORMED_OR_NOT_PARSEABLE, fmt.Sprintf("GitHub Repo URL %s is malformed.", url))
}
Expand All @@ -110,10 +141,12 @@ func ParseUrlIntoGitHubRepo(url string, token string) (GitHubRepo, *FetchError)
}

gitHubRepo = GitHubRepo{
Url: url,
Owner: matches[1],
Name: matches[2],
Token: token,
Url: url,
BaseUrl: instance.BaseUrl,
ApiUrl: instance.ApiUrl,
Owner: matches[1],
Name: matches[2],
Token: token,
}

return gitHubRepo, nil
Expand Down Expand Up @@ -161,7 +194,7 @@ func createGitHubRepoUrlForPath(repo GitHubRepo, path string) string {
func callGitHubApi(repo GitHubRepo, path string, customHeaders map[string]string) (*http.Response, *FetchError) {
httpClient := &http.Client{}

request, err := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/%s", path), nil)
request, err := http.NewRequest("GET", fmt.Sprintf("https://"+repo.ApiUrl+"/%s", path), nil)
if err != nil {
return nil, wrapError(err)
}
Expand Down
Loading

0 comments on commit ad606a2

Please sign in to comment.