Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions acceptance/testdata/repo/repo-autolink.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Create a repository to hold the autolink references
exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private

# Defer repo cleanup
defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING

# List the autolinks. There should be none
exec gh repo autolink list --repo $ORG/$SCRIPT_NAME-$RANDOM_STRING --json=keyPrefix
! stdout keyPrefix

# Create an alphanumeric autolink
exec gh repo autolink create --repo $ORG/$SCRIPT_NAME-$RANDOM_STRING TICKET- 'https://example.com/TICKET?query=<num>'

# Ensure the autolink was created
exec gh repo autolink list --repo $ORG/$SCRIPT_NAME-$RANDOM_STRING --json=keyPrefix --jq='.[].keyPrefix'
stdout 'TICKET-'

# Get the autolink id
exec gh repo autolink list --repo $ORG/$SCRIPT_NAME-$RANDOM_STRING --json=keyPrefix,id --jq='.[] | select(.keyPrefix == "TICKET-") | .id'
stdout2env AUTOLINK_ID

# View the autolink and ensure the url template round tripped
exec gh repo autolink view --repo $ORG/$SCRIPT_NAME-$RANDOM_STRING $AUTOLINK_ID --json=urlTemplate --jq='.urlTemplate'
stdout 'https://example\.com/TICKET\?query=<num>'

# Delete the autolink
exec gh repo autolink delete --repo $ORG/$SCRIPT_NAME-$RANDOM_STRING $AUTOLINK_ID --yes

# Ensure the autolink was deleted
exec gh repo autolink list --repo $ORG/$SCRIPT_NAME-$RANDOM_STRING --json=id --jq='.[].id'
! stdout $AUTOLINK_ID
104 changes: 43 additions & 61 deletions pkg/cmd/extension/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,49 +18,47 @@ func repoExists(httpClient *http.Client, repo ghrepo.Interface) (bool, error) {
if err != nil {
return false, err
}
req, err := http.NewRequest("GET", url.String(), nil)

req, err := http.NewRequest(http.MethodGet, url.String(), nil)
if err != nil {
return false, err
}

// TODO(api-client-rollout)
// This has been deferred from moving to api.Client due to its exact-status contract and body-blind response handling.
resp, err := httpClient.Do(req)
if err != nil {
return false, err
}
defer resp.Body.Close()

switch resp.StatusCode {
case 200:
case http.StatusOK:
return true, nil
case 404:
case http.StatusNotFound:
return false, nil
default:
return false, api.HandleHTTPError(resp)
}
}

func hasScript(httpClient *http.Client, repo ghrepo.Interface) (bool, error) {
url, err := safeurl.JoinPathWithHostPrefix(ghinstance.RESTPrefix(repo.RepoHost()), "repos", repo.RepoOwner(), repo.RepoName(), "contents", repo.RepoName())
if err != nil {
return false, err
}
req, err := http.NewRequest("GET", url.String(), nil)
path, err := safeurl.JoinPath("repos", repo.RepoOwner(), repo.RepoName(), "contents", repo.RepoName())
if err != nil {
return false, err
}

resp, err := httpClient.Do(req)
// The response body is not decoded, because a script is considered present for any
// successful response regardless of the content type reported.
// TODO(api-client-rollout)
// This line of code is part of a mechanical roll out of the api client.
// As a follow up, consider whether the api client can be injected to this call site, rather than constructed
err = api.NewClientFromHTTP(httpClient).REST(repo.RepoHost(), http.MethodGet, path.String(), nil, nil)
if err != nil {
return false, err
}
defer resp.Body.Close()

if resp.StatusCode == 404 {
return false, nil
}

if resp.StatusCode > 299 {
err = api.HandleHTTPError(resp)
var httpErr api.HTTPError
if errors.As(err, &httpErr) && httpErr.StatusCode == http.StatusNotFound {
return false, nil
}
return false, err
}

Expand All @@ -87,6 +85,8 @@ func downloadAsset(httpClient *http.Client, assetURL safeurl.SafeURL, destPath s
req.Header.Set("Accept", "application/octet-stream")

var resp *http.Response
// TODO(api-client-rollout)
// This has been deferred from moving to api.Client due to its custom Accept header and binary response streaming.
if resp, downloadErr = httpClient.Do(req); downloadErr != nil {
return
}
Expand Down Expand Up @@ -117,36 +117,26 @@ var repositoryNotFoundErr = errors.New("repository not found")

// fetchLatestRelease finds the latest published release for a repository.
func fetchLatestRelease(httpClient *http.Client, baseRepo ghrepo.Interface) (*release, error) {
url, err := safeurl.JoinPathWithHostPrefix(ghinstance.RESTPrefix(baseRepo.RepoHost()), "repos", baseRepo.RepoOwner(), baseRepo.RepoName(), "releases", "latest")
if err != nil {
return nil, err
}
req, err := http.NewRequest("GET", url.String(), nil)
if err != nil {
return nil, err
}

resp, err := httpClient.Do(req)
path, err := safeurl.JoinPath("repos", baseRepo.RepoOwner(), baseRepo.RepoName(), "releases", "latest")
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode == 404 {
return nil, releaseNotFoundErr
}
if resp.StatusCode > 299 {
return nil, api.HandleHTTPError(resp)
}

b, err := io.ReadAll(resp.Body)
var data json.RawMessage
// TODO(api-client-rollout)
// This line of code is part of a mechanical roll out of the api client.
// As a follow up, consider whether the api client can be injected to this call site, rather than constructed
err = api.NewClientFromHTTP(httpClient).REST(baseRepo.RepoHost(), http.MethodGet, path.String(), nil, &data)
if err != nil {
var httpErr api.HTTPError
if errors.As(err, &httpErr) && httpErr.StatusCode == http.StatusNotFound {
return nil, releaseNotFoundErr
}
return nil, err
}

var r release
err = json.Unmarshal(b, &r)
if err != nil {
if err := json.Unmarshal(data, &r); err != nil {
return nil, err
}

Expand All @@ -155,36 +145,26 @@ func fetchLatestRelease(httpClient *http.Client, baseRepo ghrepo.Interface) (*re

// fetchReleaseFromTag finds release by tag name for a repository
func fetchReleaseFromTag(httpClient *http.Client, baseRepo ghrepo.Interface, tagName string) (*release, error) {
url, err := safeurl.JoinPathWithHostPrefix(ghinstance.RESTPrefix(baseRepo.RepoHost()), "repos", baseRepo.RepoOwner(), baseRepo.RepoName(), "releases", "tags", tagName)
if err != nil {
return nil, err
}
req, err := http.NewRequest("GET", url.String(), nil)
path, err := safeurl.JoinPath("repos", baseRepo.RepoOwner(), baseRepo.RepoName(), "releases", "tags", tagName)
if err != nil {
return nil, err
}

resp, err := httpClient.Do(req)
if err != nil {
return nil, err
}

defer resp.Body.Close()
if resp.StatusCode == 404 {
return nil, releaseNotFoundErr
}
if resp.StatusCode > 299 {
return nil, api.HandleHTTPError(resp)
}

b, err := io.ReadAll(resp.Body)
var data json.RawMessage
// TODO(api-client-rollout)
// This line of code is part of a mechanical roll out of the api client.
// As a follow up, consider whether the api client can be injected to this call site, rather than constructed
err = api.NewClientFromHTTP(httpClient).REST(baseRepo.RepoHost(), http.MethodGet, path.String(), nil, &data)
if err != nil {
var httpErr api.HTTPError
if errors.As(err, &httpErr) && httpErr.StatusCode == http.StatusNotFound {
return nil, releaseNotFoundErr
}
return nil, err
}

var r release
err = json.Unmarshal(b, &r)
if err != nil {
if err := json.Unmarshal(data, &r); err != nil {
return nil, err
}

Expand All @@ -203,6 +183,8 @@ func fetchCommitSHA(httpClient *http.Client, baseRepo ghrepo.Interface, targetRe
}

req.Header.Set("Accept", "application/vnd.github.v3.sha")
// TODO(api-client-rollout)
// This has been deferred from moving to api.Client due to its custom Accept header and bare SHA response body.
resp, err := httpClient.Do(req)
if err != nil {
return "", err
Expand Down
Loading