-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
)
// GitHub API base URL
const baseURL = "https://api.github.com"
func ghRequest(url, token string) (map[string]interface{}, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept", "application/vnd.github+json")
req.Header.Set("Authorization", "Bearer "+token)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(body))
}
var result map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&result); err == io.EOF {
return nil, nil
} else if err != nil {
return nil, err
}
return result, nil
}
func ghRequestList(url, token string) ([]map[string]interface{}, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept", "application/vnd.github+json")
req.Header.Set("Authorization", "Bearer "+token)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(body))
}
var result []map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, err
}
return result, nil
}
func findInList(list []map[string]interface{}, name string) map[string]interface{} {
for _, pkg := range list {
if pkg["name"] == name {
return pkg
}
}
return nil
}
// π Function to change a package's visibility
func setPackageVisibility(org, pkgName, visibility, token string) error {
url := fmt.Sprintf("%s/orgs/%s/packages/container/%s/visibility", baseURL, org, pkgName)
body := map[string]string{"visibility": visibility}
jsonBody, _ := json.Marshal(body)
req, err := http.NewRequest("PATCH", url, bytes.NewReader(jsonBody))
if err != nil {
return err
}
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Accept", "application/vnd.github+json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
responseBody, _ := io.ReadAll(resp.Body)
if resp.StatusCode >= 400 {
return fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(responseBody))
}
fmt.Printf("β
Updated visibility to %s (HTTP %d)\n", visibility, resp.StatusCode)
return nil
}
func main() {
org := "stuttgart-things"
pkgName := "flux-source"
token := os.Getenv("GITHUB_TOKEN")
if token == "" {
log.Fatal("β Missing GITHUB_TOKEN in environment")
}
listURL := fmt.Sprintf("%s/orgs/%s/packages?package_type=container", baseURL, org)
fmt.Printf("π Listing from: %s\n", listURL)
list, err := ghRequestList(listURL, token)
if err != nil {
log.Printf("β οΈ Error listing packages: %v\n", err)
}
found := findInList(list, pkgName)
if found != nil {
fmt.Printf("β
Found %s (visibility: %s)\n", found["name"], found["visibility"])
return
}
directURL := fmt.Sprintf("%s/orgs/%s/packages/container/%s", baseURL, org, pkgName)
fmt.Printf("π Not found in list, trying direct lookup: %s\n", directURL)
direct, err := ghRequest(directURL, token)
if err != nil {
log.Fatalf("β Package not found: %v", err)
}
name := direct["name"]
visibility := direct["visibility"]
versionCount := direct["version_count"]
fmt.Printf("β
Found package: %s\n", name)
fmt.Printf(" β Visibility: %s\n", visibility)
fmt.Printf(" β Versions: %.0f\n", versionCount)
// π Example: change visibility to public
newVisibility := "public" // or "private"
if visibility != newVisibility {
fmt.Printf("βοΈ Changing visibility from %s β %s...\n", visibility, newVisibility)
if err := setPackageVisibility(org, pkgName, newVisibility, token); err != nil {
log.Fatalf("β Failed to update visibility: %v", err)
}
} else {
fmt.Println("βΉοΈ Package already has desired visibility.")
}
}This is not a bug in your Go code. Itβs a GitHub REST API limitation for org-owned GHCR packages:
For organization-owned container packages (flux-source under stuttgart-things), the API does not allow changing visibility at all.
Thatβs why the PATCH endpoint returns 404 Not Found, even though the package exists and your token is valid.
Only user-owned packages can currently have their visibility changed via API.
Metadata
Metadata
Assignees
Labels
No labels