diff --git a/github/orgs_packages.go b/github/orgs_packages.go index 4fb9a63b42..edd8e508fb 100644 --- a/github/orgs_packages.go +++ b/github/orgs_packages.go @@ -8,6 +8,7 @@ package github import ( "context" "fmt" + "net/url" ) // ListPackages lists the packages for an organization. @@ -38,11 +39,13 @@ func (s *OrganizationsService) ListPackages(ctx context.Context, org string, opt // GetPackage gets a package by name from an organization. // +// Note that packageName is escaped for the URL path so that you don't need to. +// // GitHub API docs: https://docs.github.com/rest/packages/packages#get-a-package-for-an-organization // //meta:operation GET /orgs/{org}/packages/{package_type}/{package_name} func (s *OrganizationsService) GetPackage(ctx context.Context, org, packageType, packageName string) (*Package, *Response, error) { - u := fmt.Sprintf("orgs/%v/packages/%v/%v", org, packageType, packageName) + u := fmt.Sprintf("orgs/%v/packages/%v/%v", org, packageType, url.PathEscape(packageName)) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err @@ -59,11 +62,13 @@ func (s *OrganizationsService) GetPackage(ctx context.Context, org, packageType, // DeletePackage deletes a package from an organization. // +// Note that packageName is escaped for the URL path so that you don't need to. +// // GitHub API docs: https://docs.github.com/rest/packages/packages#delete-a-package-for-an-organization // //meta:operation DELETE /orgs/{org}/packages/{package_type}/{package_name} func (s *OrganizationsService) DeletePackage(ctx context.Context, org, packageType, packageName string) (*Response, error) { - u := fmt.Sprintf("orgs/%v/packages/%v/%v", org, packageType, packageName) + u := fmt.Sprintf("orgs/%v/packages/%v/%v", org, packageType, url.PathEscape(packageName)) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err @@ -74,11 +79,13 @@ func (s *OrganizationsService) DeletePackage(ctx context.Context, org, packageTy // RestorePackage restores a package to an organization. // +// Note that packageName is escaped for the URL path so that you don't need to. +// // GitHub API docs: https://docs.github.com/rest/packages/packages#restore-a-package-for-an-organization // //meta:operation POST /orgs/{org}/packages/{package_type}/{package_name}/restore func (s *OrganizationsService) RestorePackage(ctx context.Context, org, packageType, packageName string) (*Response, error) { - u := fmt.Sprintf("orgs/%v/packages/%v/%v/restore", org, packageType, packageName) + u := fmt.Sprintf("orgs/%v/packages/%v/%v/restore", org, packageType, url.PathEscape(packageName)) req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, err @@ -89,11 +96,13 @@ func (s *OrganizationsService) RestorePackage(ctx context.Context, org, packageT // PackageGetAllVersions gets all versions of a package in an organization. // +// Note that packageName is escaped for the URL path so that you don't need to. +// // GitHub API docs: https://docs.github.com/rest/packages/packages#list-package-versions-for-a-package-owned-by-an-organization // //meta:operation GET /orgs/{org}/packages/{package_type}/{package_name}/versions func (s *OrganizationsService) PackageGetAllVersions(ctx context.Context, org, packageType, packageName string, opts *PackageListOptions) ([]*PackageVersion, *Response, error) { - u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions", org, packageType, packageName) + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions", org, packageType, url.PathEscape(packageName)) u, err := addOptions(u, opts) if err != nil { return nil, nil, err @@ -115,11 +124,13 @@ func (s *OrganizationsService) PackageGetAllVersions(ctx context.Context, org, p // PackageGetVersion gets a specific version of a package in an organization. // +// Note that packageName is escaped for the URL path so that you don't need to. +// // GitHub API docs: https://docs.github.com/rest/packages/packages#get-a-package-version-for-an-organization // //meta:operation GET /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id} func (s *OrganizationsService) PackageGetVersion(ctx context.Context, org, packageType, packageName string, packageVersionID int64) (*PackageVersion, *Response, error) { - u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v", org, packageType, packageName, packageVersionID) + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v", org, packageType, url.PathEscape(packageName), packageVersionID) req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err @@ -136,11 +147,13 @@ func (s *OrganizationsService) PackageGetVersion(ctx context.Context, org, packa // PackageDeleteVersion deletes a package version from an organization. // +// Note that packageName is escaped for the URL path so that you don't need to. +// // GitHub API docs: https://docs.github.com/rest/packages/packages#delete-package-version-for-an-organization // //meta:operation DELETE /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id} func (s *OrganizationsService) PackageDeleteVersion(ctx context.Context, org, packageType, packageName string, packageVersionID int64) (*Response, error) { - u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v", org, packageType, packageName, packageVersionID) + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v", org, packageType, url.PathEscape(packageName), packageVersionID) req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return nil, err @@ -151,11 +164,13 @@ func (s *OrganizationsService) PackageDeleteVersion(ctx context.Context, org, pa // PackageRestoreVersion restores a package version to an organization. // +// Note that packageName is escaped for the URL path so that you don't need to. +// // GitHub API docs: https://docs.github.com/rest/packages/packages#restore-package-version-for-an-organization // //meta:operation POST /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore func (s *OrganizationsService) PackageRestoreVersion(ctx context.Context, org, packageType, packageName string, packageVersionID int64) (*Response, error) { - u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v/restore", org, packageType, packageName, packageVersionID) + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v/restore", org, packageType, url.PathEscape(packageName), packageVersionID) req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, err diff --git a/github/orgs_packages_test.go b/github/orgs_packages_test.go index f8c8701d30..097cae7628 100644 --- a/github/orgs_packages_test.go +++ b/github/orgs_packages_test.go @@ -7,7 +7,7 @@ package github import ( "context" - "fmt" + "io" "net/http" "testing" @@ -20,7 +20,7 @@ func TestOrganizationsService_ListPackages(t *testing.T) { mux.HandleFunc("/orgs/o/packages", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - fmt.Fprint(w, `[{ + _, err := io.WriteString(w, `[{ "id": 197, "name": "hello_docker", "package_type": "container", @@ -52,6 +52,9 @@ func TestOrganizationsService_ListPackages(t *testing.T) { "html_url": "https://github.com/orgs/github/packages/container/package/hello_docker" } ]`) + if err != nil { + t.Fatal("Failed to write test response: ", err) + } }) ctx := context.Background() @@ -114,35 +117,39 @@ func TestOrganizationsService_GetPackage(t *testing.T) { client, mux, _, teardown := setup() defer teardown() - mux.HandleFunc("/orgs/o/packages/container/hello_docker", func(w http.ResponseWriter, r *http.Request) { + // don't url escape the package name here since mux will convert it to a slash automatically + mux.HandleFunc("/orgs/o/packages/container/hello/hello_docker", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - fmt.Fprint(w, `{ + _, err := io.WriteString(w, `{ "id": 197, - "name": "hello_docker", + "name": "hello/hello_docker", "package_type": "container", "version_count": 1, "visibility": "private", - "url": "https://api.github.com/orgs/github/packages/container/hello_docker", + "url": "https://api.github.com/orgs/github/packages/container/hello%2Fhello_docker", "created_at": `+referenceTimeStr+`, "updated_at": `+referenceTimeStr+`, - "html_url": "https://github.com/orgs/github/packages/container/package/hello_docker" + "html_url": "https://github.com/orgs/github/packages/container/package/hello%2Fhello_docker" }`) + if err != nil { + t.Fatal("Failed to write test response: ", err) + } }) ctx := context.Background() - packages, _, err := client.Organizations.GetPackage(ctx, "o", "container", "hello_docker") + packages, _, err := client.Organizations.GetPackage(ctx, "o", "container", "hello/hello_docker") if err != nil { t.Errorf("Organizations.GetPackage returned error: %v", err) } want := &Package{ ID: Int64(197), - Name: String("hello_docker"), + Name: String("hello/hello_docker"), PackageType: String("container"), VersionCount: Int64(1), Visibility: String("private"), - URL: String("https://api.github.com/orgs/github/packages/container/hello_docker"), - HTMLURL: String("https://github.com/orgs/github/packages/container/package/hello_docker"), + URL: String("https://api.github.com/orgs/github/packages/container/hello%2Fhello_docker"), + HTMLURL: String("https://github.com/orgs/github/packages/container/package/hello%2Fhello_docker"), CreatedAt: &Timestamp{referenceTime}, UpdatedAt: &Timestamp{referenceTime}, } @@ -169,12 +176,13 @@ func TestOrganizationsService_DeletePackage(t *testing.T) { client, mux, _, teardown := setup() defer teardown() - mux.HandleFunc("/orgs/o/packages/container/hello_docker", func(w http.ResponseWriter, r *http.Request) { + // don't url escape the package name here since mux will convert it to a slash automatically + mux.HandleFunc("/orgs/o/packages/container/hello/hello_docker", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) ctx := context.Background() - _, err := client.Organizations.DeletePackage(ctx, "o", "container", "hello_docker") + _, err := client.Organizations.DeletePackage(ctx, "o", "container", "hello/hello_docker") if err != nil { t.Errorf("Organizations.DeletePackage returned error: %v", err) } @@ -198,12 +206,13 @@ func TestOrganizationsService_RestorePackage(t *testing.T) { client, mux, _, teardown := setup() defer teardown() - mux.HandleFunc("/orgs/o/packages/container/hello_docker/restore", func(w http.ResponseWriter, r *http.Request) { + // don't url escape the package name here since mux will convert it to a slash automatically + mux.HandleFunc("/orgs/o/packages/container/hello/hello_docker/restore", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") }) ctx := context.Background() - _, err := client.Organizations.RestorePackage(ctx, "o", "container", "hello_docker") + _, err := client.Organizations.RestorePackage(ctx, "o", "container", "hello/hello_docker") if err != nil { t.Errorf("Organizations.RestorePackage returned error: %v", err) } @@ -215,7 +224,7 @@ func TestOrganizationsService_RestorePackage(t *testing.T) { }) testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { - return client.Organizations.RestorePackage(ctx, "", "container", "hello_docker") + return client.Organizations.RestorePackage(ctx, "", "container", "hello/hello_docker") }) } @@ -223,18 +232,19 @@ func TestOrganizationsService_ListPackagesVersions(t *testing.T) { client, mux, _, teardown := setup() defer teardown() - mux.HandleFunc("/orgs/o/packages/container/hello_docker/versions", func(w http.ResponseWriter, r *http.Request) { + // don't url escape the package name here since mux will convert it to a slash automatically + mux.HandleFunc("/orgs/o/packages/container/hello/hello_docker/versions", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{"per_page": "2", "page": "1", "state": "deleted", "visibility": "internal", "package_type": "container"}) - fmt.Fprint(w, `[ + _, err := io.WriteString(w, `[ { "id": 45763, "name": "sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9", - "url": "https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763", - "package_html_url": "https://github.com/users/octocat/packages/container/package/hello_docker", + "url": "https://api.github.com/users/octocat/packages/container/hello%2Fhello_docker/versions/45763", + "package_html_url": "https://github.com/users/octocat/packages/container/package/hello%2Fhello_docker", "created_at": `+referenceTimeStr+`, "updated_at": `+referenceTimeStr+`, - "html_url": "https://github.com/users/octocat/packages/container/hello_docker/45763", + "html_url": "https://github.com/users/octocat/packages/container/hello%2Fhello_docker/45763", "metadata": { "package_type": "container", "container": { @@ -244,13 +254,16 @@ func TestOrganizationsService_ListPackagesVersions(t *testing.T) { } } }]`) + if err != nil { + t.Fatal("Failed to write test response: ", err) + } }) ctx := context.Background() opts := &PackageListOptions{ String("internal"), String("container"), String("deleted"), ListOptions{Page: 1, PerPage: 2}, } - packages, _, err := client.Organizations.PackageGetAllVersions(ctx, "o", "container", "hello_docker", opts) + packages, _, err := client.Organizations.PackageGetAllVersions(ctx, "o", "container", "hello/hello_docker", opts) if err != nil { t.Errorf("Organizations.PackageGetAllVersions returned error: %v", err) } @@ -258,11 +271,11 @@ func TestOrganizationsService_ListPackagesVersions(t *testing.T) { want := []*PackageVersion{{ ID: Int64(45763), Name: String("sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9"), - URL: String("https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763"), - PackageHTMLURL: String("https://github.com/users/octocat/packages/container/package/hello_docker"), + URL: String("https://api.github.com/users/octocat/packages/container/hello%2Fhello_docker/versions/45763"), + PackageHTMLURL: String("https://github.com/users/octocat/packages/container/package/hello%2Fhello_docker"), CreatedAt: &Timestamp{referenceTime}, UpdatedAt: &Timestamp{referenceTime}, - HTMLURL: String("https://github.com/users/octocat/packages/container/hello_docker/45763"), + HTMLURL: String("https://github.com/users/octocat/packages/container/hello%2Fhello_docker/45763"), Metadata: &PackageMetadata{ PackageType: String("container"), Container: &PackageContainerMetadata{ @@ -293,17 +306,18 @@ func TestOrganizationsService_PackageGetVersion(t *testing.T) { client, mux, _, teardown := setup() defer teardown() - mux.HandleFunc("/orgs/o/packages/container/hello_docker/versions/45763", func(w http.ResponseWriter, r *http.Request) { + // don't url escape the package name here since mux will convert it to a slash automatically + mux.HandleFunc("/orgs/o/packages/container/hello/hello_docker/versions/45763", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - fmt.Fprint(w, ` + _, err := io.WriteString(w, ` { "id": 45763, "name": "sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9", - "url": "https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763", - "package_html_url": "https://github.com/users/octocat/packages/container/package/hello_docker", + "url": "https://api.github.com/users/octocat/packages/container/hello%2Fhello_docker/versions/45763", + "package_html_url": "https://github.com/users/octocat/packages/container/package/hello%2Fhello_docker", "created_at": `+referenceTimeStr+`, "updated_at": `+referenceTimeStr+`, - "html_url": "https://github.com/users/octocat/packages/container/hello_docker/45763", + "html_url": "https://github.com/users/octocat/packages/container/hello%2Fhello_docker/45763", "metadata": { "package_type": "container", "container": { @@ -313,10 +327,13 @@ func TestOrganizationsService_PackageGetVersion(t *testing.T) { } } }`) + if err != nil { + t.Fatal("Failed to write test response: ", err) + } }) ctx := context.Background() - packages, _, err := client.Organizations.PackageGetVersion(ctx, "o", "container", "hello_docker", 45763) + packages, _, err := client.Organizations.PackageGetVersion(ctx, "o", "container", "hello/hello_docker", 45763) if err != nil { t.Errorf("Organizations.PackageGetVersion returned error: %v", err) } @@ -324,11 +341,11 @@ func TestOrganizationsService_PackageGetVersion(t *testing.T) { want := &PackageVersion{ ID: Int64(45763), Name: String("sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9"), - URL: String("https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763"), - PackageHTMLURL: String("https://github.com/users/octocat/packages/container/package/hello_docker"), + URL: String("https://api.github.com/users/octocat/packages/container/hello%2Fhello_docker/versions/45763"), + PackageHTMLURL: String("https://github.com/users/octocat/packages/container/package/hello%2Fhello_docker"), CreatedAt: &Timestamp{referenceTime}, UpdatedAt: &Timestamp{referenceTime}, - HTMLURL: String("https://github.com/users/octocat/packages/container/hello_docker/45763"), + HTMLURL: String("https://github.com/users/octocat/packages/container/hello%2Fhello_docker/45763"), Metadata: &PackageMetadata{ PackageType: String("container"), Container: &PackageContainerMetadata{ @@ -359,12 +376,13 @@ func TestOrganizationsService_PackageDeleteVersion(t *testing.T) { client, mux, _, teardown := setup() defer teardown() - mux.HandleFunc("/orgs/o/packages/container/hello_docker/versions/45763", func(w http.ResponseWriter, r *http.Request) { + // don't url escape the package name here since mux will convert it to a slash automatically + mux.HandleFunc("/orgs/o/packages/container/hello/hello_docker/versions/45763", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) ctx := context.Background() - _, err := client.Organizations.PackageDeleteVersion(ctx, "o", "container", "hello_docker", 45763) + _, err := client.Organizations.PackageDeleteVersion(ctx, "o", "container", "hello/hello_docker", 45763) if err != nil { t.Errorf("Organizations.PackageDeleteVersion returned error: %v", err) } @@ -384,12 +402,13 @@ func TestOrganizationsService_PackageRestoreVersion(t *testing.T) { client, mux, _, teardown := setup() defer teardown() - mux.HandleFunc("/orgs/o/packages/container/hello_docker/versions/45763/restore", func(w http.ResponseWriter, r *http.Request) { + // don't url escape the package name here since mux will convert it to a slash automatically + mux.HandleFunc("/orgs/o/packages/container/hello/hello_docker/versions/45763/restore", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") }) ctx := context.Background() - _, err := client.Organizations.PackageRestoreVersion(ctx, "o", "container", "hello_docker", 45763) + _, err := client.Organizations.PackageRestoreVersion(ctx, "o", "container", "hello/hello_docker", 45763) if err != nil { t.Errorf("Organizations.PackageRestoreVersion returned error: %v", err) }