Skip to content

Commit 0ef343c

Browse files
committed
fix: auto-detect hub type when catalog type is empty
When the catalog type is not specified, the code now probes the Artifact Hub stats endpoint to determine the catalog type. If the endpoint responds successfully, the catalog is treated as Artifact Hub; otherwise, it falls back to Tekton Hub. - Call /api/v1/stats endpoint to detect Artifact Hub catalogs - Fallback to Tekton Hub if the API call fails - Update tests with HTTP mock client for catalog type detection https://issues.redhat.com/browse/SRVKP-9248 Signed-off-by: Zaki Shaikh <[email protected]>
1 parent 9572f3b commit 0ef343c

File tree

3 files changed

+74
-1
lines changed

3 files changed

+74
-1
lines changed

docs/content/docs/install/settings.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,11 @@ Pipelines-as-Code supports fetching tasks and pipelines with its remote annotati
211211

212212
The type of hub catalog. Supported values are:
213213

214-
* `artifacthub` - For Artifact Hub (default if not specified)
214+
* `artifacthub` - For Artifact Hub
215215
* `tektonhub` - For Tekton Hub
216216

217+
If `hub-catalog-type` is empty, Pipelines as Code will auto-detect the catalog type by probing the Artifact Hub stats endpoint. If the endpoint responds successfully, the catalog is treated as Artifact Hub; otherwise, it falls back to Tekton Hub.
218+
217219
* By default, both Artifact Hub and Tekton Hub are configured:
218220

219221
* Artifact Hub is the default catalog (no prefix needed, but `artifact://` can be used explicitly)

pkg/params/settings/default.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package settings
22

33
import (
4+
"context"
45
"fmt"
6+
"net/http"
57
"net/url"
8+
"strings"
69
"sync"
10+
"time"
711

812
hubtypes "github.com/openshift-pipelines/pipelines-as-code/pkg/hub/vars"
913
"go.uber.org/zap"
@@ -20,6 +24,9 @@ func getHubCatalogs(logger *zap.SugaredLogger, catalogs *sync.Map, config map[st
2024

2125
if hubType, ok := config[HubCatalogTypeKey]; !ok || hubType == "" {
2226
config[HubCatalogTypeKey] = hubtypes.ArtifactHubType
27+
if config[HubURLKey] != "" {
28+
config[HubCatalogTypeKey] = getHubCatalogTypeViaAPI(config[HubURLKey])
29+
}
2330
} else if hubType != hubtypes.ArtifactHubType && hubType != hubtypes.TektonHubType {
2431
logger.Warnf("CONFIG: invalid hub type %s, defaulting to %s", hubType, hubtypes.ArtifactHubType)
2532
config[HubCatalogTypeKey] = hubtypes.ArtifactHubType
@@ -105,3 +112,28 @@ func getHubCatalogs(logger *zap.SugaredLogger, catalogs *sync.Map, config map[st
105112
}
106113
return catalogs
107114
}
115+
116+
func getHubCatalogTypeViaAPI(hubURL string) string {
117+
statsURL := fmt.Sprintf("%s/api/v1/stats", strings.TrimSuffix(hubURL, "/"))
118+
119+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
120+
defer cancel()
121+
122+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, statsURL, nil)
123+
if err != nil {
124+
return hubtypes.TektonHubType
125+
}
126+
127+
resp, err := http.DefaultClient.Do(req)
128+
if err != nil {
129+
return hubtypes.TektonHubType
130+
}
131+
defer resp.Body.Close()
132+
133+
if resp.StatusCode == http.StatusOK {
134+
return hubtypes.ArtifactHubType
135+
}
136+
137+
// if the API call fails, return Tekton Hub type
138+
return hubtypes.TektonHubType
139+
}

pkg/params/settings/default_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package settings
22

33
import (
4+
"net/http"
5+
"net/http/httptest"
46
"sync"
57
"testing"
68

9+
hubtypes "github.com/openshift-pipelines/pipelines-as-code/pkg/hub/vars"
710
"go.uber.org/zap"
811
zapobserver "go.uber.org/zap/zaptest/observer"
912
"gotest.tools/v3/assert"
@@ -163,3 +166,39 @@ func TestGetCatalogHub(t *testing.T) {
163166
})
164167
}
165168
}
169+
170+
func TestGetHubCatalogTypeViaAPI(t *testing.T) {
171+
tests := []struct {
172+
name string
173+
serverStatus int
174+
expectedResult string
175+
}{
176+
{
177+
name: "returns ArtifactHubType on 200 OK",
178+
serverStatus: http.StatusOK,
179+
expectedResult: hubtypes.ArtifactHubType,
180+
},
181+
{
182+
name: "returns TektonHubType on 404 Not Found",
183+
serverStatus: http.StatusNotFound,
184+
expectedResult: hubtypes.TektonHubType,
185+
},
186+
{
187+
name: "returns TektonHubType on 500 Internal Server Error",
188+
serverStatus: http.StatusInternalServerError,
189+
expectedResult: hubtypes.TektonHubType,
190+
},
191+
}
192+
193+
for _, tt := range tests {
194+
t.Run(tt.name, func(t *testing.T) {
195+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
196+
w.WriteHeader(tt.serverStatus)
197+
}))
198+
defer server.Close()
199+
200+
result := getHubCatalogTypeViaAPI(server.URL)
201+
assert.Equal(t, result, tt.expectedResult)
202+
})
203+
}
204+
}

0 commit comments

Comments
 (0)