8000 feat: add gitlab push to generic package registry by lmphil · Pull Request #266 · bomctl/bomctl · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: add gitlab push to generic package registry #266

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into fro 8000 m
Jan 27, 2025
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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,12 @@ Flags:
--tree Recursively push all SBOMs in external reference tree
```

An SBOM may be pushed as a package to a GitLab repository through the [Generic Package Registry web API](https://docs.gitlab.com/ee/user/packages/generic_packages) by using the following URL format. Authorization for this command is configured by assigning the value of your GitLab token to the `BOMCTL_GITLAB_TOKEN` environment variable.

```shell
bomctl push SBOM_ID_OR_ALIAS https://www.gitlab.com/PROJECT/REPOSITORY#PACKAGE_NAME@PACKAGE_VERSION
```

### Tag

Edit the tags of an SBOM document.
Expand Down
93 changes: 82 additions & 11 deletions internal/pkg/client/gitlab/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,82 @@ package gitlab

import (
"fmt"
"io"
"net/http"
"regexp"

gitlab "gitlab.com/gitlab-org/api/client-go"

"github.com/bomctl/bomctl/internal/pkg/netutil"
)

type Client struct {
ProjectProvider
BranchProvider
CommitProvider
DependencyListExporter
Export *gitlab.DependencyListExport
GitLabToken string
}
type (
projectProvider interface {
GetProject(
any,
*gitlab.GetProjectOptions,
...gitlab.RequestOptionFunc,
) (*gitlab.Project, *gitlab.Response, error)
}

branchProvider interface {
GetBranch(
any,
string,
...gitlab.RequestOptionFunc,
) (*gitlab.Branch, *gitlab.Response, error)
}

commitProvider interface {
GetCommit(
any,
string,
*gitlab.GetCommitOptions,
...gitlab.RequestOptionFunc,
) (*gitlab.Commit, *gitlab.Response, error)
}

dependencyListExporter interface {
CreateDependencyListExport(
int,
*gitlab.CreateDependencyListExportOptions,
...gitlab.RequestOptionFunc,
) (*gitlab.DependencyListExport, *gitlab.Response, error)
GetDependencyListExport(
int,
...gitlab.RequestOptionFunc,
) (*gitlab.DependencyListExport, *gitlab.Response, error)
DownloadDependencyListExport(int, ...gitlab.RequestOptionFunc) (io.Reader, *gitlab.Response, error)
}

genericPackagePublisher interface {
PublishPackageFile(
any,
string,
string,
string,
io.Reader,
*gitlab.PublishPackageFileOptions,
...gitlab.RequestOptionFunc,
) (*gitlab.GenericPackagesFile, *gitlab.Response, error)
}

sbomFile struct {
Contents string
Name string
}

Client struct {
projectProvider
branchProvider
commitProvider
dependencyListExporter
genericPackagePublisher
GitLabToken string
Export *gitlab.DependencyListExport
PushQueue []*sbomFile
}
)

func (*Client) Name() string {
return "GitLab"
Expand All @@ -44,8 +105,8 @@ func (*Client) Name() string {
func (*Client) RegExp() *regexp.Regexp {
return regexp.MustCompile(fmt.Sprintf("(?i)^%s%s%s$",
`(?P<scheme>https?|git|ssh):\/\/`,
`(?P<hostname>[^@\/?#:]+gitlab[^@\/?#:]+)(?::(?P<port>\d+))?/`,
`(?P<path>[^@#]+)@(?P<gitRef>\S+)`))
`(?P<hostname>[^@\/?#:]*gitlab[^@\/?#:]+)(?::(?P<port>\d+))?/`,
`(?P<path>[^@?#]+)(?:@(?P<gitRef>[^?#]+))?(?:\?(?P<query>[^#]+))?(?:#(?P<fragment>.+))?`))
}

func (client *Client) Parse(rawURL string) *netutil.URL {
Expand All @@ -58,7 +119,7 @@ func (client *Client) Parse(rawURL string) *netutil.URL {
}

// Ensure required map fields are present.
for _, required := range []string{"scheme", "hostname", "path", "gitRef"} {
for _, required := range []string{"scheme", "hostname", "path"} {
if value, ok := results[required]; !ok || value == "" {
return nil
}
Expand All @@ -70,5 +131,15 @@ func (client *Client) Parse(rawURL string) *netutil.URL {
Port: results["port"],
Path: results["path"],
GitRef: results["gitRef"],
Query: results["query"],
Fragment: results["fragment"],
}
}

func validateHTTPStatusCode(statusCode int) error {
if statusCode < http.StatusOK || statusCode >= http.StatusMultipleChoices {
return fmt.Errorf("%w. HTTP status code: %d", errFailedWebRequest, statusCode)
}

return nil
}
Loading
Loading
0