feat: [AH-1116]: remove artifact updated event (#3559)

* feat: [AH-1116]: remove artifact updated event
main
Tudor Macari 2025-03-24 09:08:32 +00:00 committed by Harness
parent 154bf4c4b1
commit d84b5cc7e1
18 changed files with 338 additions and 402 deletions

View File

@ -504,7 +504,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
if err != nil {
return nil, err
}
apiHandler := router.APIHandlerProvider(registryRepository, upstreamProxyConfigRepository, fileManager, tagRepository, manifestRepository, cleanupPolicyRepository, imageRepository, storageDriver, spaceFinder, transactor, authenticator, provider, authorizer, auditService, artifactRepository, webhooksRepository, webhooksExecutionRepository, service2, spacePathStore)
apiHandler := router.APIHandlerProvider(registryRepository, upstreamProxyConfigRepository, fileManager, tagRepository, manifestRepository, cleanupPolicyRepository, imageRepository, storageDriver, spaceFinder, transactor, authenticator, provider, authorizer, auditService, artifactRepository, webhooksRepository, webhooksExecutionRepository, service2, spacePathStore, reporter8)
mavenDBStore := maven.DBStoreProvider(registryRepository, imageRepository, artifactRepository, spaceStore, bandwidthStatRepository, downloadStatRepository, nodesRepository, upstreamProxyConfigRepository)
mavenLocalRegistry := maven.LocalRegistryProvider(mavenDBStore, transactor, fileManager)
mavenController := maven.ProvideProxyController(mavenLocalRegistry, secretService, spaceFinder)

View File

@ -49,6 +49,7 @@ type RegistryRequestBaseInfo struct {
parentID int64
RegistryType api.RegistryType
PackageType api.PackageType
}
type RegistryRequestInfo struct {

View File

@ -20,6 +20,7 @@ import (
urlprovider "github.com/harness/gitness/app/url"
"github.com/harness/gitness/audit"
storagedriver "github.com/harness/gitness/registry/app/driver"
registryevents "github.com/harness/gitness/registry/app/events"
"github.com/harness/gitness/registry/app/pkg/filemanager"
"github.com/harness/gitness/registry/app/store"
"github.com/harness/gitness/store/database/dbtx"
@ -47,6 +48,7 @@ type APIController struct {
WebhooksExecutionRepository store.WebhooksExecutionRepository
RegistryMetadataHelper RegistryMetadataHelper
WebhookService WebhookService
ArtifactEventReporter registryevents.Reporter
}
func NewAPIController(
@ -70,6 +72,7 @@ func NewAPIController(
webhooksExecutionRepository store.WebhooksExecutionRepository,
registryMetadataHelper RegistryMetadataHelper,
webhookService WebhookService,
artifactEventReporter registryevents.Reporter,
) *APIController {
return &APIController{
fileManager: fileManager,
@ -92,5 +95,6 @@ func NewAPIController(
WebhooksExecutionRepository: webhooksExecutionRepository,
RegistryMetadataHelper: registryMetadataHelper,
WebhookService: webhookService,
ArtifactEventReporter: artifactEventReporter,
}
}

View File

@ -22,9 +22,11 @@ import (
"github.com/harness/gitness/app/api/request"
"github.com/harness/gitness/audit"
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
"github.com/harness/gitness/registry/services/webhook"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/opencontainers/go-digest"
"github.com/rs/zerolog/log"
)
@ -90,10 +92,19 @@ func (c *APIController) deleteTagWithAudit(
ctx context.Context, regInfo *RegistryRequestBaseInfo,
registryName string, principal types.Principal, artifactName string, versionName string,
) error {
existingDigest := c.getTagDigest(ctx, regInfo.RegistryID, artifactName, versionName)
err := c.TagStore.DeleteTag(ctx, regInfo.RegistryID, artifactName, versionName)
if err != nil {
return err
}
if existingDigest != "" {
payload := webhook.GetArtifactDeletedPayload(ctx, principal.ID, regInfo.RegistryID,
registryName, versionName, existingDigest.String(), regInfo.RootIdentifier,
regInfo.PackageType, artifactName, c.URLProvider)
c.ArtifactEventReporter.ArtifactDeleted(ctx, &payload)
}
auditErr := c.AuditService.Log(
ctx,
principal,
@ -117,3 +128,19 @@ func throwDeleteArtifactVersion500Error(err error) artifact.DeleteArtifactVersio
),
}
}
func (c *APIController) getTagDigest(
ctx context.Context,
registryID int64,
imageName string,
tag string,
) digest.Digest {
existingTag, findTagErr := c.TagStore.FindTag(ctx, registryID, imageName, tag)
if findTagErr == nil && existingTag != nil {
existingTaggedManifest, getManifestErr := c.ManifestStore.Get(ctx, existingTag.ManifestID)
if getManifestErr == nil {
return existingTaggedManifest.Digest
}
}
return ""
}

View File

@ -179,8 +179,6 @@ func mapTpAPITriggerType(trigger enum.WebhookTrigger) api.Trigger {
switch trigger {
case enum.WebhookTriggerArtifactCreated:
return api.TriggerARTIFACTCREATION
case enum.WebhookTriggerArtifactUpdated:
return api.TriggerARTIFACTMODIFICATION
case enum.WebhookTriggerArtifactDeleted:
return api.TriggerARTIFACTDELETION
}

View File

@ -114,6 +114,7 @@ func (r *GitnessRegistryMetadataHelper) GetRegistryRequestBaseInfo(
baseInfo.RegistryIdentifier = regIdentifier
baseInfo.RegistryID = reg.ID
baseInfo.RegistryType = reg.Type
baseInfo.PackageType = reg.PackageType
}
return baseInfo, nil
@ -252,8 +253,6 @@ func (r *GitnessRegistryMetadataHelper) MapToInternalWebhookTriggers(
switch trigger {
case api.TriggerARTIFACTCREATION:
webhookTriggers = append(webhookTriggers, enum.WebhookTriggerArtifactCreated)
case api.TriggerARTIFACTMODIFICATION:
webhookTriggers = append(webhookTriggers, enum.WebhookTriggerArtifactUpdated)
case api.TriggerARTIFACTDELETION:
webhookTriggers = append(webhookTriggers, enum.WebhookTriggerArtifactDeleted)
}
@ -283,8 +282,6 @@ func (r *GitnessRegistryMetadataHelper) MapToAPIWebhookTriggers(triggers []enum.
switch trigger {
case enum.WebhookTriggerArtifactCreated:
webhookTriggers = append(webhookTriggers, api.TriggerARTIFACTCREATION)
case enum.WebhookTriggerArtifactUpdated:
webhookTriggers = append(webhookTriggers, api.TriggerARTIFACTMODIFICATION)
case enum.WebhookTriggerArtifactDeleted:
webhookTriggers = append(webhookTriggers, api.TriggerARTIFACTDELETION)
}

View File

@ -347,13 +347,11 @@ func TestMapToInternalWebhookTriggers(t *testing.T) {
apiTriggers := []api.Trigger{
api.TriggerARTIFACTCREATION,
api.TriggerARTIFACTMODIFICATION,
api.TriggerARTIFACTDELETION,
}
expectedInternalTriggers := []gitnessenum.WebhookTrigger{
gitnessenum.WebhookTriggerArtifactCreated,
gitnessenum.WebhookTriggerArtifactUpdated,
gitnessenum.WebhookTriggerArtifactDeleted,
}
@ -366,13 +364,11 @@ func TestMapToAPIWebhookTriggers(t *testing.T) {
internalTriggers := []gitnessenum.WebhookTrigger{
gitnessenum.WebhookTriggerArtifactCreated,
gitnessenum.WebhookTriggerArtifactUpdated,
gitnessenum.WebhookTriggerArtifactDeleted,
}
expectedAPITriggers := []api.Trigger{
api.TriggerARTIFACTCREATION,
api.TriggerARTIFACTMODIFICATION,
api.TriggerARTIFACTDELETION,
}

View File

@ -2162,7 +2162,6 @@ components:
description: refers to trigger
enum:
- ARTIFACT_CREATION
- ARTIFACT_MODIFICATION
- ARTIFACT_DELETION
ExtraHeader:
type: object

View File

@ -1,6 +1,6 @@
// Package artifact provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT.
// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.1.0 DO NOT EDIT.
package artifact
import (
@ -346,6 +346,7 @@ type MiddlewareFunc func(http.Handler) http.Handler
// CreateRegistry operation middleware
func (siw *ServerInterfaceWrapper) CreateRegistry(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -368,11 +369,12 @@ func (siw *ServerInterfaceWrapper) CreateRegistry(w http.ResponseWriter, r *http
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// DeleteRegistry operation middleware
func (siw *ServerInterfaceWrapper) DeleteRegistry(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -393,11 +395,12 @@ func (siw *ServerInterfaceWrapper) DeleteRegistry(w http.ResponseWriter, r *http
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetRegistry operation middleware
func (siw *ServerInterfaceWrapper) GetRegistry(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -418,11 +421,12 @@ func (siw *ServerInterfaceWrapper) GetRegistry(w http.ResponseWriter, r *http.Re
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// ModifyRegistry operation middleware
func (siw *ServerInterfaceWrapper) ModifyRegistry(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -443,11 +447,12 @@ func (siw *ServerInterfaceWrapper) ModifyRegistry(w http.ResponseWriter, r *http
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// ListArtifactLabels operation middleware
func (siw *ServerInterfaceWrapper) ListArtifactLabels(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -495,11 +500,12 @@ func (siw *ServerInterfaceWrapper) ListArtifactLabels(w http.ResponseWriter, r *
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetArtifactStatsForRegistry operation middleware
func (siw *ServerInterfaceWrapper) GetArtifactStatsForRegistry(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -539,11 +545,12 @@ func (siw *ServerInterfaceWrapper) GetArtifactStatsForRegistry(w http.ResponseWr
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// DeleteArtifact operation middleware
func (siw *ServerInterfaceWrapper) DeleteArtifact(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -573,11 +580,12 @@ func (siw *ServerInterfaceWrapper) DeleteArtifact(w http.ResponseWriter, r *http
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// UpdateArtifactLabels operation middleware
func (siw *ServerInterfaceWrapper) UpdateArtifactLabels(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -607,11 +615,12 @@ func (siw *ServerInterfaceWrapper) UpdateArtifactLabels(w http.ResponseWriter, r
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetArtifactStats operation middleware
func (siw *ServerInterfaceWrapper) GetArtifactStats(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -660,11 +669,12 @@ func (siw *ServerInterfaceWrapper) GetArtifactStats(w http.ResponseWriter, r *ht
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetArtifactSummary operation middleware
func (siw *ServerInterfaceWrapper) GetArtifactSummary(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -694,11 +704,12 @@ func (siw *ServerInterfaceWrapper) GetArtifactSummary(w http.ResponseWriter, r *
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// DeleteArtifactVersion operation middleware
func (siw *ServerInterfaceWrapper) DeleteArtifactVersion(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -737,11 +748,12 @@ func (siw *ServerInterfaceWrapper) DeleteArtifactVersion(w http.ResponseWriter,
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetArtifactDetails operation middleware
func (siw *ServerInterfaceWrapper) GetArtifactDetails(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -791,11 +803,12 @@ func (siw *ServerInterfaceWrapper) GetArtifactDetails(w http.ResponseWriter, r *
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetDockerArtifactDetails operation middleware
func (siw *ServerInterfaceWrapper) GetDockerArtifactDetails(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -852,11 +865,12 @@ func (siw *ServerInterfaceWrapper) GetDockerArtifactDetails(w http.ResponseWrite
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetDockerArtifactLayers operation middleware
func (siw *ServerInterfaceWrapper) GetDockerArtifactLayers(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -913,11 +927,12 @@ func (siw *ServerInterfaceWrapper) GetDockerArtifactLayers(w http.ResponseWriter
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetDockerArtifactManifest operation middleware
func (siw *ServerInterfaceWrapper) GetDockerArtifactManifest(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -974,11 +989,12 @@ func (siw *ServerInterfaceWrapper) GetDockerArtifactManifest(w http.ResponseWrit
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetDockerArtifactManifests operation middleware
func (siw *ServerInterfaceWrapper) GetDockerArtifactManifests(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1017,11 +1033,12 @@ func (siw *ServerInterfaceWrapper) GetDockerArtifactManifests(w http.ResponseWri
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetArtifactFiles operation middleware
func (siw *ServerInterfaceWrapper) GetArtifactFiles(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1103,11 +1120,12 @@ func (siw *ServerInterfaceWrapper) GetArtifactFiles(w http.ResponseWriter, r *ht
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetHelmArtifactDetails operation middleware
func (siw *ServerInterfaceWrapper) GetHelmArtifactDetails(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1146,11 +1164,12 @@ func (siw *ServerInterfaceWrapper) GetHelmArtifactDetails(w http.ResponseWriter,
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetHelmArtifactManifest operation middleware
func (siw *ServerInterfaceWrapper) GetHelmArtifactManifest(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1189,11 +1208,12 @@ func (siw *ServerInterfaceWrapper) GetHelmArtifactManifest(w http.ResponseWriter
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetArtifactVersionSummary operation middleware
func (siw *ServerInterfaceWrapper) GetArtifactVersionSummary(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1232,11 +1252,12 @@ func (siw *ServerInterfaceWrapper) GetArtifactVersionSummary(w http.ResponseWrit
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetAllArtifactVersions operation middleware
func (siw *ServerInterfaceWrapper) GetAllArtifactVersions(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1309,11 +1330,12 @@ func (siw *ServerInterfaceWrapper) GetAllArtifactVersions(w http.ResponseWriter,
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetAllArtifactsByRegistry operation middleware
func (siw *ServerInterfaceWrapper) GetAllArtifactsByRegistry(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1385,11 +1407,12 @@ func (siw *ServerInterfaceWrapper) GetAllArtifactsByRegistry(w http.ResponseWrit
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetClientSetupDetails operation middleware
func (siw *ServerInterfaceWrapper) GetClientSetupDetails(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1429,11 +1452,12 @@ func (siw *ServerInterfaceWrapper) GetClientSetupDetails(w http.ResponseWriter,
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// ListWebhooks operation middleware
func (siw *ServerInterfaceWrapper) ListWebhooks(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1497,11 +1521,12 @@ func (siw *ServerInterfaceWrapper) ListWebhooks(w http.ResponseWriter, r *http.R
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// CreateWebhook operation middleware
func (siw *ServerInterfaceWrapper) CreateWebhook(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1522,11 +1547,12 @@ func (siw *ServerInterfaceWrapper) CreateWebhook(w http.ResponseWriter, r *http.
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// DeleteWebhook operation middleware
func (siw *ServerInterfaceWrapper) DeleteWebhook(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1556,11 +1582,12 @@ func (siw *ServerInterfaceWrapper) DeleteWebhook(w http.ResponseWriter, r *http.
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetWebhook operation middleware
func (siw *ServerInterfaceWrapper) GetWebhook(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1590,11 +1617,12 @@ func (siw *ServerInterfaceWrapper) GetWebhook(w http.ResponseWriter, r *http.Req
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// UpdateWebhook operation middleware
func (siw *ServerInterfaceWrapper) UpdateWebhook(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1624,11 +1652,12 @@ func (siw *ServerInterfaceWrapper) UpdateWebhook(w http.ResponseWriter, r *http.
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// ListWebhookExecutions operation middleware
func (siw *ServerInterfaceWrapper) ListWebhookExecutions(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1677,11 +1706,12 @@ func (siw *ServerInterfaceWrapper) ListWebhookExecutions(w http.ResponseWriter,
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetWebhookExecution operation middleware
func (siw *ServerInterfaceWrapper) GetWebhookExecution(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1720,11 +1750,12 @@ func (siw *ServerInterfaceWrapper) GetWebhookExecution(w http.ResponseWriter, r
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// ReTriggerWebhookExecution operation middleware
func (siw *ServerInterfaceWrapper) ReTriggerWebhookExecution(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1763,11 +1794,12 @@ func (siw *ServerInterfaceWrapper) ReTriggerWebhookExecution(w http.ResponseWrit
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetArtifactStatsForSpace operation middleware
func (siw *ServerInterfaceWrapper) GetArtifactStatsForSpace(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1807,11 +1839,12 @@ func (siw *ServerInterfaceWrapper) GetArtifactStatsForSpace(w http.ResponseWrite
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetAllArtifacts operation middleware
func (siw *ServerInterfaceWrapper) GetAllArtifacts(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1899,11 +1932,12 @@ func (siw *ServerInterfaceWrapper) GetAllArtifacts(w http.ResponseWriter, r *htt
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
// GetAllRegistries operation middleware
func (siw *ServerInterfaceWrapper) GetAllRegistries(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
@ -1991,7 +2025,7 @@ func (siw *ServerInterfaceWrapper) GetAllRegistries(w http.ResponseWriter, r *ht
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
handler.ServeHTTP(w, r.WithContext(ctx))
}
type UnescapedCookieParamError struct {
@ -5734,97 +5768,97 @@ func (sh *strictHandler) GetAllRegistries(w http.ResponseWriter, r *http.Request
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
"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",
"ey7uc0V7uY2/ud/8fwAAAP//9679LzfkAAA=",
"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",
"P6z/PwAA//+vQi5MH+QAAA==",
}
// GetSwagger returns the content of the embedded swagger specification file

View File

@ -1,6 +1,6 @@
// Package artifact provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT.
// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.1.0 DO NOT EDIT.
package artifact
import (
@ -54,9 +54,8 @@ const (
// Defines values for Trigger.
const (
TriggerARTIFACTCREATION Trigger = "ARTIFACT_CREATION"
TriggerARTIFACTDELETION Trigger = "ARTIFACT_DELETION"
TriggerARTIFACTMODIFICATION Trigger = "ARTIFACT_MODIFICATION"
TriggerARTIFACTCREATION Trigger = "ARTIFACT_CREATION"
TriggerARTIFACTDELETION Trigger = "ARTIFACT_DELETION"
)
// Defines values for UpstreamConfigSource.

View File

@ -29,6 +29,7 @@ import (
"github.com/harness/gitness/registry/app/api/middleware"
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
storagedriver "github.com/harness/gitness/registry/app/driver"
registryevents "github.com/harness/gitness/registry/app/events"
"github.com/harness/gitness/registry/app/pkg/filemanager"
"github.com/harness/gitness/registry/app/store"
registrywebhook "github.com/harness/gitness/registry/services/webhook"
@ -74,6 +75,7 @@ func NewAPIHandler(
webhooksExecutionRepository store.WebhooksExecutionRepository,
webhookService registrywebhook.Service,
spacePathStore corestore.SpacePathStore,
artifactEventReporter registryevents.Reporter,
) APIHandler {
r := chi.NewRouter()
r.Use(audit.Middleware())
@ -101,6 +103,7 @@ func NewAPIHandler(
webhooksExecutionRepository,
registryMetadataHelper,
&webhookService,
artifactEventReporter,
)
handler := artifact.NewStrictHandler(apiController, []artifact.StrictMiddlewareFunc{})

View File

@ -33,6 +33,7 @@ import (
"github.com/harness/gitness/registry/app/api/router/oci"
packagerrouter "github.com/harness/gitness/registry/app/api/router/packages"
storagedriver "github.com/harness/gitness/registry/app/driver"
registryevents "github.com/harness/gitness/registry/app/events"
"github.com/harness/gitness/registry/app/pkg/filemanager"
"github.com/harness/gitness/registry/app/store"
registrywebhook "github.com/harness/gitness/registry/services/webhook"
@ -71,6 +72,7 @@ func APIHandlerProvider(
webhooksExecutionRepository store.WebhooksExecutionRepository,
webhookService *registrywebhook.Service,
spacePathStore corestore.SpacePathStore,
artifactEventReporter *registryevents.Reporter,
) harness.APIHandler {
return harness.NewAPIHandler(
repoDao,
@ -93,6 +95,7 @@ func APIHandlerProvider(
webhooksExecutionRepository,
*webhookService,
spacePathStore,
*artifactEventReporter,
)
}

View File

@ -26,7 +26,6 @@ import (
const ArtifactsCategory = "artifacts"
const ArtifactCreatedEvent events.EventType = "artifact-created"
const ArtifactUpdatedEvent events.EventType = "artifact-updated"
const ArtifactDeletedEvent events.EventType = "artifact-deleted"
type ArtifactCreatedPayload struct {
@ -74,12 +73,6 @@ type ArtifactInfo struct {
Artifact interface{} `json:"artifact"`
}
type ArtifactChangeInfo struct {
Type artifact.PackageType `json:"type"`
Name string `json:"name"`
ArtifactChange interface{} `json:"artifact_change"`
}
func (r *Reporter) ArtifactCreated(ctx context.Context, payload *ArtifactCreatedPayload) {
eventID, err := events.ReporterSendEvent(r.innerReporter, ctx, ArtifactCreatedEvent, payload)
if err != nil {
@ -97,18 +90,6 @@ func (r *Reader) RegisterArtifactCreated(
return events.ReaderRegisterEvent(r.innerReader, ArtifactCreatedEvent, fn, opts...)
}
type ArtifactUpdatedPayload struct {
RegistryID int64 `json:"registry_id"`
PrincipalID int64 `json:"principal_id"`
ArtifactType artifact.PackageType `json:"artifact_type"`
ArtifactChange ArtifactChange `json:"artifact_change"`
}
type ArtifactChange struct {
Old Artifact
New Artifact
}
type DockerArtifactChange struct {
Old DockerArtifact
New DockerArtifact
@ -119,23 +100,6 @@ type HelmArtifactChange struct {
New HelmArtifact
}
func (r *Reporter) ArtifactUpdated(ctx context.Context, payload *ArtifactUpdatedPayload) {
eventID, err := events.ReporterSendEvent(r.innerReporter, ctx, ArtifactUpdatedEvent, payload)
if err != nil {
log.Ctx(ctx).Err(err).Msgf("failed to send artifact updated event")
return
}
log.Ctx(ctx).Debug().Msgf("reported artifact updated event with id '%s'", eventID)
}
func (r *Reader) RegisterArtifactUpdated(
fn events.HandlerFunc[*ArtifactUpdatedPayload],
opts ...events.HandlerOption,
) error {
return events.ReaderRegisterEvent(r.innerReader, ArtifactUpdatedEvent, fn, opts...)
}
type ArtifactDeletedPayload struct {
RegistryID int64 `json:"registry_id"`
PrincipalID int64 `json:"principal_id"`

View File

@ -21,7 +21,6 @@ import (
"database/sql"
"errors"
"fmt"
"net/url"
"time"
"github.com/harness/gitness/app/api/request"
@ -39,6 +38,7 @@ import (
"github.com/harness/gitness/registry/app/store"
"github.com/harness/gitness/registry/app/store/database/util"
"github.com/harness/gitness/registry/gc"
"github.com/harness/gitness/registry/services/webhook"
"github.com/harness/gitness/registry/types"
gitnessstore "github.com/harness/gitness/store"
db "github.com/harness/gitness/store/database"
@ -51,8 +51,6 @@ import (
"github.com/rs/zerolog/log"
)
const ociPrefix = "oci://"
type manifestService struct {
registryDao store.RegistryRepository
manifestDao store.ManifestRepository
@ -204,8 +202,6 @@ func (l *manifestService) dbTagManifest(
if err != nil {
return formatFailedToTagErr(err)
}
existingDigest := l.getTagDigest(ctx, dbRegistry.ID, imageName, tagName)
err = l.tx.WithTx(ctx, func(ctx context.Context) error {
// Prevent long running transactions by setting an upper limit of manifestTagGCLockTimeout. If the GC is holding
// the lock of a related review record, the processing there should be fast enough to avoid this. Regardless, we
@ -241,15 +237,9 @@ func (l *manifestService) dbTagManifest(
}
l.reportEventAsync(ctx, reg.ID, info.RegIdentifier, imageName, tagName, packageType, spacePath)
session, _ := request.AuthSessionFrom(ctx)
createPayload := l.getArtifactCreatedPayload(ctx, info, session.Principal.ID,
reg.ID, reg.Name, tagName, dgst.String())
createPayload := webhook.GetArtifactCreatedPayload(ctx, info, session.Principal.ID,
reg.ID, reg.Name, tagName, dgst.String(), l.urlProvider)
l.artifactEventReporter.ArtifactCreated(ctx, &createPayload)
if existingDigest != "" && existingDigest != dgst {
updatePayload := l.getArtifactUpdatedPayload(ctx, info, session.Principal.ID,
reg.ID, reg.Name, tagName, existingDigest.String(), dgst.String())
l.artifactEventReporter.ArtifactUpdated(ctx, &updatePayload)
}
} else {
log.Ctx(ctx).Err(err).Msg("Failed to find spacePath, not publishing event")
}
@ -257,139 +247,6 @@ func (l *manifestService) dbTagManifest(
return nil
}
func (l *manifestService) getArtifactCreatedPayload(
ctx context.Context,
info pkg.RegistryInfo,
principalID int64,
registryID int64,
regIdentifier string,
tag string,
digest string,
) registryevents.ArtifactCreatedPayload {
payload := registryevents.ArtifactCreatedPayload{
RegistryID: registryID,
PrincipalID: principalID,
ArtifactType: info.PackageType,
}
artifactURL := l.urlProvider.RegistryURL(ctx, info.RootIdentifier, regIdentifier) + "/" + info.Image + ":" + tag
urlWithoutProtocol := GetRepoURLWithoutProtocol(artifactURL)
baseArtifact := registryevents.BaseArtifact{
Name: info.Image,
Ref: fmt.Sprintf("%s:%s", info.Image, tag),
}
if info.PackageType == artifact.PackageTypeDOCKER {
payload.Artifact = &registryevents.DockerArtifact{
BaseArtifact: baseArtifact,
Tag: tag,
URL: urlWithoutProtocol,
Digest: digest,
}
} else if info.PackageType == artifact.PackageTypeHELM {
payload.Artifact = &registryevents.HelmArtifact{
BaseArtifact: baseArtifact,
Tag: tag,
URL: ociPrefix + urlWithoutProtocol,
Digest: digest,
}
}
return payload
}
func (l *manifestService) getArtifactDeletedPayload(
ctx context.Context,
info pkg.RegistryInfo,
principalID int64,
registryID int64,
regIdentifier string,
tag string,
digest string,
) registryevents.ArtifactDeletedPayload {
payload := registryevents.ArtifactDeletedPayload{
RegistryID: registryID,
PrincipalID: principalID,
ArtifactType: info.PackageType,
}
artifactURL := l.urlProvider.RegistryURL(ctx, info.RootIdentifier, regIdentifier) + "/" + info.Image + ":" + tag
urlWithoutProtocol := GetRepoURLWithoutProtocol(artifactURL)
baseArtifact := registryevents.BaseArtifact{
Name: info.Image,
Ref: fmt.Sprintf("%s:%s", info.Image, tag),
}
if info.PackageType == artifact.PackageTypeDOCKER {
payload.Artifact = &registryevents.DockerArtifact{
BaseArtifact: baseArtifact,
Tag: tag,
Digest: digest,
URL: urlWithoutProtocol,
}
} else if info.PackageType == artifact.PackageTypeHELM {
payload.Artifact = &registryevents.HelmArtifact{
BaseArtifact: baseArtifact,
Tag: tag,
Digest: digest,
URL: ociPrefix + urlWithoutProtocol,
}
}
return payload
}
func (l *manifestService) getArtifactUpdatedPayload(
ctx context.Context,
info pkg.RegistryInfo,
principalID int64,
registryID int64,
regIdentifier string,
tag string,
oldDigest string,
newDigest string,
) registryevents.ArtifactUpdatedPayload {
payload := registryevents.ArtifactUpdatedPayload{
RegistryID: registryID,
PrincipalID: principalID,
ArtifactType: info.PackageType,
}
artifactURL := l.urlProvider.RegistryURL(ctx, info.RootIdentifier, regIdentifier) + "/" + info.Image + ":" + tag
urlWithoutProtocol := GetRepoURLWithoutProtocol(artifactURL)
baseArtifact := registryevents.BaseArtifact{
Name: info.Image,
Ref: fmt.Sprintf("%s:%s", info.Image, tag),
}
if info.PackageType == artifact.PackageTypeDOCKER {
payload.ArtifactChange = registryevents.ArtifactChange{
Old: &registryevents.DockerArtifact{
BaseArtifact: baseArtifact,
Tag: tag,
URL: urlWithoutProtocol,
Digest: oldDigest,
},
New: &registryevents.DockerArtifact{
BaseArtifact: baseArtifact,
Tag: tag,
URL: urlWithoutProtocol,
Digest: newDigest,
},
}
} else if info.PackageType == artifact.PackageTypeHELM {
payload.ArtifactChange = registryevents.ArtifactChange{
Old: &registryevents.HelmArtifact{
BaseArtifact: baseArtifact,
Tag: tag,
URL: ociPrefix + urlWithoutProtocol,
Digest: oldDigest,
},
New: &registryevents.HelmArtifact{
BaseArtifact: baseArtifact,
Tag: tag,
URL: ociPrefix + urlWithoutProtocol,
Digest: newDigest,
},
}
}
return payload
}
func formatFailedToTagErr(err error) error {
return fmt.Errorf("failed to tag manifest: %w", err)
}
@ -1240,10 +1097,12 @@ func (l *manifestService) DeleteTag(
return false, distribution.ErrTagUnknown{Tag: tag}
}
session, _ := request.AuthSessionFrom(ctx)
payload := l.getArtifactDeletedPayload(ctx, info, session.Principal.ID, registry.ID,
registry.Name, tag, existingDigest.String())
l.artifactEventReporter.ArtifactDeleted(ctx, &payload)
if existingDigest != "" {
session, _ := request.AuthSessionFrom(ctx)
payload := webhook.GetArtifactDeletedPayload(ctx, session.Principal.ID, registry.ID,
registry.Name, tag, existingDigest.String(), info.RootIdentifier, info.PackageType, info.Image, l.urlProvider)
l.artifactEventReporter.ArtifactDeleted(ctx, &payload)
}
return true, nil
}
@ -1364,14 +1223,3 @@ func (l *manifestService) DeleteManifest(
},
)
}
func GetRepoURLWithoutProtocol(registryURL string) string {
repoURL := registryURL
parsedURL, err := url.Parse(repoURL)
if err != nil {
log.Error().Stack().Err(err).Msg("Error parsing URL: ")
return ""
}
return parsedURL.Host + parsedURL.Path
}

View File

@ -29,11 +29,10 @@ import (
// ArtifactEventPayload describes the payload of Artifact related webhook triggers.
type ArtifactEventPayload struct {
Trigger enum.WebhookTrigger `json:"trigger"`
Registry RegistryInfo `json:"registry"`
Principal gitnesswebhook.PrincipalInfo `json:"principal"`
ArtifactInfo *registryevents.ArtifactInfo `json:"artifact_info"`
ArtifactChangeInfo *registryevents.ArtifactChangeInfo `json:"artifact_change_info"`
Trigger enum.WebhookTrigger `json:"trigger"`
Registry RegistryInfo `json:"registry"`
Principal gitnesswebhook.PrincipalInfo `json:"principal"`
ArtifactInfo *registryevents.ArtifactInfo `json:"artifact_info"`
}
type RegistryInfo struct {
@ -81,45 +80,6 @@ func (s *Service) handleEventArtifactCreated(
})
}
// handleEventArtifactUpdated handles branch updated events
// and triggers branch updated webhooks for the source repo.
func (s *Service) handleEventArtifactUpdated(
ctx context.Context,
event *events.Event[*registryevents.ArtifactUpdatedPayload],
) error {
return s.triggerForEventWithArtifact(ctx, enum.WebhookTriggerArtifactUpdated,
event.ID, event.Payload.PrincipalID, event.Payload.RegistryID,
func(
principal *types.Principal,
registry *registrytypes.Registry,
) (any, error) {
space, err := s.spaceStore.Find(ctx, registry.ParentID)
if err != nil {
return nil, err
}
return &ArtifactEventPayload{
Trigger: enum.WebhookTriggerArtifactUpdated,
Registry: RegistryInfo{
ID: registry.ID,
Name: registry.Name,
Description: registry.Description,
URL: s.urlProvider.GenerateUIRegistryURL(ctx, space.Path, registry.Name),
},
Principal: gitnesswebhook.PrincipalInfo{
ID: principal.ID,
UID: principal.UID,
DisplayName: principal.DisplayName,
Email: principal.Email,
Type: principal.Type,
Created: principal.Created,
Updated: principal.Updated,
},
ArtifactInfo: getArtifactInfo(event.Payload.ArtifactChange.New),
ArtifactChangeInfo: getArtifactInfoForArtifactUpdated(*event.Payload),
}, nil
})
}
// handleEventArtifactDeleted handles branch deleted events
// and triggers branch deleted webhooks for the source repo.
func (s *Service) handleEventArtifactDeleted(
@ -174,21 +134,6 @@ func getArtifactInfo(eventArtifact registryevents.Artifact) *registryevents.Arti
return &artifactInfo
}
func getArtifactInfoForArtifactUpdated(
payload registryevents.ArtifactUpdatedPayload,
) *registryevents.ArtifactChangeInfo {
artifactInfo := registryevents.ArtifactChangeInfo{
Type: payload.ArtifactType,
}
if dockerArtifact, ok := payload.ArtifactChange.New.(*registryevents.DockerArtifact); ok {
artifactInfo.Name = dockerArtifact.Name
} else if helmArtifact, ok := payload.ArtifactChange.New.(*registryevents.HelmArtifact); ok {
artifactInfo.Name = helmArtifact.Name
}
artifactInfo.ArtifactChange = &payload.ArtifactChange
return &artifactInfo
}
// triggerForEventWithArtifact triggers all webhooks for the given registry and triggerType
// using the eventID to generate a deterministic triggerID and using the output of bodyFn as payload.
// The method tries to find the registry and principal and provides both to the bodyFn to generate the body.

View File

@ -0,0 +1,122 @@
// Copyright 2023 Harness, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package webhook
import (
"context"
"fmt"
"net/url"
urlprovider "github.com/harness/gitness/app/url"
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
registryevents "github.com/harness/gitness/registry/app/events"
"github.com/harness/gitness/registry/app/pkg"
"github.com/rs/zerolog/log"
)
const ociPrefix = "oci://"
func GetArtifactCreatedPayload(
ctx context.Context,
info pkg.RegistryInfo,
principalID int64,
registryID int64,
regIdentifier string,
tag string,
digest string,
urlProvider urlprovider.Provider,
) registryevents.ArtifactCreatedPayload {
payload := registryevents.ArtifactCreatedPayload{
RegistryID: registryID,
PrincipalID: principalID,
ArtifactType: info.PackageType,
}
artifactURL := urlProvider.RegistryURL(ctx, info.RootIdentifier, regIdentifier) + "/" + info.Image + ":" + tag
urlWithoutProtocol := GetRepoURLWithoutProtocol(artifactURL)
baseArtifact := registryevents.BaseArtifact{
Name: info.Image,
Ref: fmt.Sprintf("%s:%s", info.Image, tag),
}
if info.PackageType == artifact.PackageTypeDOCKER {
payload.Artifact = &registryevents.DockerArtifact{
BaseArtifact: baseArtifact,
Tag: tag,
URL: urlWithoutProtocol,
Digest: digest,
}
} else if info.PackageType == artifact.PackageTypeHELM {
payload.Artifact = &registryevents.HelmArtifact{
BaseArtifact: baseArtifact,
Tag: tag,
URL: ociPrefix + urlWithoutProtocol,
Digest: digest,
}
}
return payload
}
func GetArtifactDeletedPayload(
ctx context.Context,
principalID int64,
registryID int64,
regIdentifier string,
tag string,
digest string,
rootIdentifier string,
packageType artifact.PackageType,
image string,
urlProvider urlprovider.Provider,
) registryevents.ArtifactDeletedPayload {
payload := registryevents.ArtifactDeletedPayload{
RegistryID: registryID,
PrincipalID: principalID,
ArtifactType: packageType,
}
artifactURL := urlProvider.RegistryURL(ctx, rootIdentifier, regIdentifier) + "/" + image + ":" + tag
urlWithoutProtocol := GetRepoURLWithoutProtocol(artifactURL)
baseArtifact := registryevents.BaseArtifact{
Name: image,
Ref: fmt.Sprintf("%s:%s", image, tag),
}
if packageType == artifact.PackageTypeDOCKER {
payload.Artifact = &registryevents.DockerArtifact{
BaseArtifact: baseArtifact,
Tag: tag,
Digest: digest,
URL: urlWithoutProtocol,
}
} else if packageType == artifact.PackageTypeHELM {
payload.Artifact = &registryevents.HelmArtifact{
BaseArtifact: baseArtifact,
Tag: tag,
Digest: digest,
URL: ociPrefix + urlWithoutProtocol,
}
}
return payload
}
func GetRepoURLWithoutProtocol(registryURL string) string {
repoURL := registryURL
parsedURL, err := url.Parse(repoURL)
if err != nil {
log.Error().Stack().Err(err).Msg("Error parsing URL: ")
return ""
}
return parsedURL.Host + parsedURL.Path
}

View File

@ -96,7 +96,6 @@ func NewService(
// register events
_ = r.RegisterArtifactCreated(service.handleEventArtifactCreated)
_ = r.RegisterArtifactUpdated(service.handleEventArtifactUpdated)
_ = r.RegisterArtifactDeleted(service.handleEventArtifactDeleted)
return nil

View File

@ -197,8 +197,6 @@ const (
// WebhookTriggerArtifactCreated gets triggered when an artifact gets created.
WebhookTriggerArtifactCreated WebhookTrigger = "artifact_created"
// WebhookTriggerArtifactUpdated gets triggered when an artifact gets updated.
WebhookTriggerArtifactUpdated WebhookTrigger = "artifact_updated"
// WebhookTriggerArtifactDeleted gets triggered when an artifact gets deleted.
WebhookTriggerArtifactDeleted WebhookTrigger = "artifact_deleted"
)
@ -222,6 +220,5 @@ var webhookTriggers = sortEnum([]WebhookTrigger{
WebhookTriggerPullReqLabelAssigned,
WebhookTriggerPullReqReviewSubmitted,
WebhookTriggerArtifactCreated,
WebhookTriggerArtifactUpdated,
WebhookTriggerArtifactDeleted,
})