.
This commit is contained in:
parent
18bfc87a1c
commit
e47feaf5e8
@ -7,7 +7,7 @@ gitea-generated/client/gitea_api_client.go:: api.json
|
||||
[ -d gitea-generated ] || mkdir gitea-generated
|
||||
podman run --rm -v $$(pwd):/api ghcr.io/go-swagger/go-swagger generate client -f /api/api.json -t /api/gitea-generated
|
||||
|
||||
api: gitea-generated/client/gitea_api_client.go client.gen.go
|
||||
api: gitea-generated/client/gitea_api_client.go
|
||||
|
||||
build: api
|
||||
go build
|
||||
|
@ -10549,6 +10549,9 @@
|
||||
},
|
||||
"/repos/{owner}/{repo}/media/{filepath}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/octet-stream"
|
||||
],
|
||||
"tags": [
|
||||
"repository"
|
||||
],
|
||||
@ -10585,7 +10588,10 @@
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Returns raw file content."
|
||||
"description": "Returns raw file content.",
|
||||
"schema": {
|
||||
"type": "file"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/responses/notFound"
|
||||
@ -12621,14 +12627,13 @@
|
||||
},
|
||||
"/repos/{owner}/{repo}/raw/{filepath}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"repository"
|
||||
],
|
||||
"summary": "Get a file from a repository",
|
||||
"operationId": "repoGetRawFile",
|
||||
"produces" : ["application/octet-stream"],
|
||||
"consumes" : ["application/octet-stream"],
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
@ -12660,7 +12665,10 @@
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Returns raw file content."
|
||||
"description": "Returns raw file content.",
|
||||
"schema": {
|
||||
"type": "file"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/responses/notFound"
|
||||
|
@ -3,7 +3,7 @@ package common
|
||||
const (
|
||||
GiteaTokenEnv = "GITEA_TOKEN"
|
||||
ObsUserEnv = "OBS_USER"
|
||||
ObsPasswordEnv = "OBS_PW"
|
||||
ObsPasswordEnv = "OBS_PASSWORD"
|
||||
|
||||
DefaultGitPrj = "_ObsPrj"
|
||||
GiteaRequestHeader = "X-Gitea-Event-Type"
|
||||
|
@ -174,6 +174,17 @@ func (f writeFunc) Write(data []byte) (int, error) {
|
||||
return f(data)
|
||||
}
|
||||
|
||||
func (h writeFunc) UnmarshalText(text []byte) error {
|
||||
_, err := h.Write(text)
|
||||
return err
|
||||
}
|
||||
|
||||
func (h writeFunc) Close() error {
|
||||
_, err := h.Write(nil)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
func (e *RequestHandler) GitExec(cwd string, params ...string) ExecStream {
|
||||
if e.Error != nil {
|
||||
return e
|
||||
@ -436,6 +447,61 @@ func parseGitTree(data <-chan byte) (tree, error) {
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (e *RequestHandler) GitSubmoduleList(cwd, commitId string) map[string]string {
|
||||
var done sync.Mutex
|
||||
submoduleList := make(map[string]string)
|
||||
|
||||
done.Lock()
|
||||
data_in, data_out := ChanIO{make(chan byte, 256)}, ChanIO{make(chan byte, 70)}
|
||||
|
||||
go func() {
|
||||
defer done.Unlock()
|
||||
defer close(data_out.ch)
|
||||
|
||||
data_out.Write([]byte(commitId))
|
||||
data_out.ch <- '\x00'
|
||||
c, err := parseGitCommit(data_in.ch)
|
||||
if err != nil {
|
||||
e.Error = err
|
||||
e.LogError("Error parsing git commit: %v", err)
|
||||
return
|
||||
}
|
||||
data_out.Write([]byte(c.Tree))
|
||||
data_out.ch <- '\x00'
|
||||
tree, err := parseGitTree(data_in.ch)
|
||||
|
||||
if err != nil {
|
||||
e.Error = err
|
||||
e.LogError("Error parsing git tree: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, te := range tree.items {
|
||||
if te.isSubmodule() {
|
||||
submoduleList[te.name] = te.hash
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
cmd := exec.Command("/usr/bin/git", "cat-file", "--batch", "-Z")
|
||||
cmd.Env = []string{
|
||||
"GIT_CEILING_DIRECTORIES=" + e.GitPath,
|
||||
"GIT_CONFIG_GLOBAL=/dev/null",
|
||||
}
|
||||
cmd.Dir = filepath.Join(e.GitPath, cwd)
|
||||
cmd.Stdout = &data_in
|
||||
cmd.Stdin = &data_out
|
||||
cmd.Stderr = writeFunc(func(data []byte) (int, error) {
|
||||
e.Logger.LogError("%s", data)
|
||||
return len(data), nil
|
||||
})
|
||||
e.Log("command run: %v", cmd.Args)
|
||||
e.Error = cmd.Run()
|
||||
|
||||
done.Lock()
|
||||
return submoduleList
|
||||
}
|
||||
|
||||
func (e *RequestHandler) GitSubmoduleCommitId(cwd, packageName, commitId string) (string, bool) {
|
||||
if e.Error != nil {
|
||||
return "", false
|
||||
|
@ -7,6 +7,7 @@ package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
@ -15,13 +16,14 @@ import (
|
||||
// RepoGetRawFileOrLFSReader is a Reader for the RepoGetRawFileOrLFS structure.
|
||||
type RepoGetRawFileOrLFSReader struct {
|
||||
formats strfmt.Registry
|
||||
writer io.Writer
|
||||
}
|
||||
|
||||
// ReadResponse reads a server response into the received o.
|
||||
func (o *RepoGetRawFileOrLFSReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
switch response.Code() {
|
||||
case 200:
|
||||
result := NewRepoGetRawFileOrLFSOK()
|
||||
result := NewRepoGetRawFileOrLFSOK(o.writer)
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -38,8 +40,11 @@ func (o *RepoGetRawFileOrLFSReader) ReadResponse(response runtime.ClientResponse
|
||||
}
|
||||
|
||||
// NewRepoGetRawFileOrLFSOK creates a RepoGetRawFileOrLFSOK with default headers values
|
||||
func NewRepoGetRawFileOrLFSOK() *RepoGetRawFileOrLFSOK {
|
||||
return &RepoGetRawFileOrLFSOK{}
|
||||
func NewRepoGetRawFileOrLFSOK(writer io.Writer) *RepoGetRawFileOrLFSOK {
|
||||
return &RepoGetRawFileOrLFSOK{
|
||||
|
||||
Payload: writer,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -48,6 +53,7 @@ RepoGetRawFileOrLFSOK describes a response with status code 200, with default he
|
||||
Returns raw file content.
|
||||
*/
|
||||
type RepoGetRawFileOrLFSOK struct {
|
||||
Payload io.Writer
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this repo get raw file or l f s o k response has a 2xx status code
|
||||
@ -88,8 +94,17 @@ func (o *RepoGetRawFileOrLFSOK) String() string {
|
||||
return fmt.Sprintf("[GET /repos/{owner}/{repo}/media/{filepath}][%d] repoGetRawFileOrLFSOK", 200)
|
||||
}
|
||||
|
||||
func (o *RepoGetRawFileOrLFSOK) GetPayload() io.Writer {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *RepoGetRawFileOrLFSOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
@ -15,13 +16,14 @@ import (
|
||||
// RepoGetRawFileReader is a Reader for the RepoGetRawFile structure.
|
||||
type RepoGetRawFileReader struct {
|
||||
formats strfmt.Registry
|
||||
writer io.Writer
|
||||
}
|
||||
|
||||
// ReadResponse reads a server response into the received o.
|
||||
func (o *RepoGetRawFileReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
switch response.Code() {
|
||||
case 200:
|
||||
result := NewRepoGetRawFileOK()
|
||||
result := NewRepoGetRawFileOK(o.writer)
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -38,8 +40,11 @@ func (o *RepoGetRawFileReader) ReadResponse(response runtime.ClientResponse, con
|
||||
}
|
||||
|
||||
// NewRepoGetRawFileOK creates a RepoGetRawFileOK with default headers values
|
||||
func NewRepoGetRawFileOK() *RepoGetRawFileOK {
|
||||
return &RepoGetRawFileOK{}
|
||||
func NewRepoGetRawFileOK(writer io.Writer) *RepoGetRawFileOK {
|
||||
return &RepoGetRawFileOK{
|
||||
|
||||
Payload: writer,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -48,6 +53,7 @@ RepoGetRawFileOK describes a response with status code 200, with default header
|
||||
Returns raw file content.
|
||||
*/
|
||||
type RepoGetRawFileOK struct {
|
||||
Payload io.Writer
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this repo get raw file o k response has a 2xx status code
|
||||
@ -88,8 +94,17 @@ func (o *RepoGetRawFileOK) String() string {
|
||||
return fmt.Sprintf("[GET /repos/{owner}/{repo}/raw/{filepath}][%d] repoGetRawFileOK", 200)
|
||||
}
|
||||
|
||||
func (o *RepoGetRawFileOK) GetPayload() io.Writer {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *RepoGetRawFileOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ package repository
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
@ -103,6 +104,11 @@ func WithAcceptApplicationJSON(r *runtime.ClientOperation) {
|
||||
r.ProducesMediaTypes = []string{"application/json"}
|
||||
}
|
||||
|
||||
// WithAcceptApplicationOctetStream sets the Accept header to "application/octet-stream".
|
||||
func WithAcceptApplicationOctetStream(r *runtime.ClientOperation) {
|
||||
r.ProducesMediaTypes = []string{"application/octet-stream"}
|
||||
}
|
||||
|
||||
// WithAcceptTextHTML sets the Accept header to "text/html".
|
||||
func WithAcceptTextHTML(r *runtime.ClientOperation) {
|
||||
r.ProducesMediaTypes = []string{"text/html"}
|
||||
@ -303,9 +309,9 @@ type ClientService interface {
|
||||
|
||||
RepoGetPushMirrorByRemoteName(params *RepoGetPushMirrorByRemoteNameParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetPushMirrorByRemoteNameOK, error)
|
||||
|
||||
RepoGetRawFile(params *RepoGetRawFileParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetRawFileOK, error)
|
||||
RepoGetRawFile(params *RepoGetRawFileParams, authInfo runtime.ClientAuthInfoWriter, writer io.Writer, opts ...ClientOption) (*RepoGetRawFileOK, error)
|
||||
|
||||
RepoGetRawFileOrLFS(params *RepoGetRawFileOrLFSParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetRawFileOrLFSOK, error)
|
||||
RepoGetRawFileOrLFS(params *RepoGetRawFileOrLFSParams, authInfo runtime.ClientAuthInfoWriter, writer io.Writer, opts ...ClientOption) (*RepoGetRawFileOrLFSOK, error)
|
||||
|
||||
RepoGetRelease(params *RepoGetReleaseParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetReleaseOK, error)
|
||||
|
||||
@ -4103,7 +4109,7 @@ func (a *Client) RepoGetPushMirrorByRemoteName(params *RepoGetPushMirrorByRemote
|
||||
/*
|
||||
RepoGetRawFile gets a file from a repository
|
||||
*/
|
||||
func (a *Client) RepoGetRawFile(params *RepoGetRawFileParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetRawFileOK, error) {
|
||||
func (a *Client) RepoGetRawFile(params *RepoGetRawFileParams, authInfo runtime.ClientAuthInfoWriter, writer io.Writer, opts ...ClientOption) (*RepoGetRawFileOK, error) {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewRepoGetRawFileParams()
|
||||
@ -4112,11 +4118,11 @@ func (a *Client) RepoGetRawFile(params *RepoGetRawFileParams, authInfo runtime.C
|
||||
ID: "repoGetRawFile",
|
||||
Method: "GET",
|
||||
PathPattern: "/repos/{owner}/{repo}/raw/{filepath}",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{"application/json", "text/plain"},
|
||||
ProducesMediaTypes: []string{"application/octet-stream"},
|
||||
ConsumesMediaTypes: []string{"application/octet-stream"},
|
||||
Schemes: []string{"http", "https"},
|
||||
Params: params,
|
||||
Reader: &RepoGetRawFileReader{formats: a.formats},
|
||||
Reader: &RepoGetRawFileReader{formats: a.formats, writer: writer},
|
||||
AuthInfo: authInfo,
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
@ -4142,7 +4148,7 @@ func (a *Client) RepoGetRawFile(params *RepoGetRawFileParams, authInfo runtime.C
|
||||
/*
|
||||
RepoGetRawFileOrLFS gets a file or it s l f s object from a repository
|
||||
*/
|
||||
func (a *Client) RepoGetRawFileOrLFS(params *RepoGetRawFileOrLFSParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*RepoGetRawFileOrLFSOK, error) {
|
||||
func (a *Client) RepoGetRawFileOrLFS(params *RepoGetRawFileOrLFSParams, authInfo runtime.ClientAuthInfoWriter, writer io.Writer, opts ...ClientOption) (*RepoGetRawFileOrLFSOK, error) {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewRepoGetRawFileOrLFSParams()
|
||||
@ -4151,11 +4157,11 @@ func (a *Client) RepoGetRawFileOrLFS(params *RepoGetRawFileOrLFSParams, authInfo
|
||||
ID: "repoGetRawFileOrLFS",
|
||||
Method: "GET",
|
||||
PathPattern: "/repos/{owner}/{repo}/media/{filepath}",
|
||||
ProducesMediaTypes: []string{"application/json", "text/html"},
|
||||
ProducesMediaTypes: []string{"application/octet-stream"},
|
||||
ConsumesMediaTypes: []string{"application/json", "text/plain"},
|
||||
Schemes: []string{"http", "https"},
|
||||
Params: params,
|
||||
Reader: &RepoGetRawFileOrLFSReader{formats: a.formats},
|
||||
Reader: &RepoGetRawFileOrLFSReader{formats: a.formats, writer: writer},
|
||||
AuthInfo: authInfo,
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
|
@ -23,7 +23,7 @@ const PrPattern = "PR: %s/%s#%d"
|
||||
func (h *RequestHandler) allocateGiteaTransport() (*transport.Runtime, *apiclient.GiteaAPI) {
|
||||
r := transport.New("src.opensuse.org", apiclient.DefaultBasePath, [](string){"https"})
|
||||
r.DefaultAuthentication = transport.BearerToken(giteaToken)
|
||||
r.SetDebug(true)
|
||||
// r.SetDebug(true)
|
||||
|
||||
return r, apiclient.New(r, nil)
|
||||
}
|
||||
@ -287,6 +287,56 @@ func (h *RequestHandler) RequestReviews(pr *models.PullRequest, reviewer string)
|
||||
return review.GetPayload()
|
||||
}
|
||||
|
||||
func (h *RequestHandler) AddReviewComment(pr *models.PullRequest, state models.ReviewStateType, comment string) (*models.PullReview, error) {
|
||||
transport, client := h.allocateGiteaTransport()
|
||||
|
||||
h.Log("%#v", *pr)
|
||||
c, err := client.Repository.RepoCreatePullReview(
|
||||
repository.NewRepoCreatePullReviewParams().
|
||||
WithDefaults().
|
||||
WithOwner(pr.Base.Repo.Owner.UserName).
|
||||
WithRepo(pr.Base.Repo.Name).
|
||||
WithIndex(pr.Index).
|
||||
WithBody(&models.CreatePullReviewOptions{
|
||||
Event: state,
|
||||
Body: comment,
|
||||
}),
|
||||
transport.DefaultAuthentication,
|
||||
)
|
||||
/*
|
||||
c, err := client.Repository.RepoSubmitPullReview(
|
||||
repository.NewRepoSubmitPullReviewParams().
|
||||
WithDefaults().
|
||||
WithOwner(pr.Base.Repo.Owner.UserName).
|
||||
WithRepo(pr.Base.Repo.Name).
|
||||
WithIndex(pr.Index).
|
||||
WithID(review.ID).
|
||||
WithBody(&models.SubmitPullReviewOptions{
|
||||
Event: state,
|
||||
Body: comment,
|
||||
}),
|
||||
transport.DefaultAuthentication,
|
||||
)
|
||||
*/
|
||||
|
||||
/* c, err := client.Issue.IssueCreateComment(
|
||||
issue.NewIssueCreateCommentParams().
|
||||
WithDefaults().
|
||||
WithOwner(pr.Base.Repo.Owner.UserName).
|
||||
WithRepo(pr.Base.Repo.Name).
|
||||
WithIndex(pr.Index).
|
||||
WithBody(&models.CreateIssueCommentOption{
|
||||
Body: &comment,
|
||||
}),
|
||||
transport.DefaultAuthentication)
|
||||
*/
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.Payload, nil
|
||||
}
|
||||
|
||||
func (h *RequestHandler) GetAssociatedPrjGitPR(pr *PullRequestAction) *models.PullRequest {
|
||||
if h.HasError() {
|
||||
return nil
|
||||
@ -335,20 +385,30 @@ func (h *RequestHandler) GetAssociatedPrjGitPR(pr *PullRequestAction) *models.Pu
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *RequestHandler) GetRepositoryFileContent(pr *models.PullRequest, path string) ([]byte, error) {
|
||||
func (h *RequestHandler) GetRepositoryFileContent(repo *models.Repository, hash, path string) ([]byte, error) {
|
||||
if h.HasError() {
|
||||
return nil, h.Error
|
||||
}
|
||||
|
||||
transport, client := h.allocateGiteaTransport()
|
||||
repo := pr.Head.Repo
|
||||
var retData []byte
|
||||
|
||||
dataOut := writeFunc(func(data []byte) (int, error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
retData = data
|
||||
return len(data), nil
|
||||
})
|
||||
file, err := client.Repository.RepoGetRawFile(
|
||||
repository.NewRepoGetRawFileParams().
|
||||
WithOwner(repo.Owner.UserName).
|
||||
WithRepo(repo.Name).
|
||||
WithFilepath(path).
|
||||
WithRef(&pr.Head.Ref),
|
||||
WithRef(&hash),
|
||||
transport.DefaultAuthentication,
|
||||
dataOut,
|
||||
repository.WithContentTypeApplicationOctetStream,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
@ -359,6 +419,9 @@ func (h *RequestHandler) GetRepositoryFileContent(pr *models.PullRequest, path s
|
||||
return nil, fmt.Errorf("Invalid response from server (%d): %s", file.Code(), file.Error())
|
||||
}
|
||||
|
||||
return file.Body(), nil
|
||||
return retData, nil
|
||||
}
|
||||
|
||||
func (h *RequestHandler) GetPullRequestFileContent(pr *models.PullRequest, path string) ([]byte, error) {
|
||||
return h.GetRepositoryFileContent(pr.Head.Repo, pr.Head.Sha, path)
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ func prepareMsg(time time.Duration, id uint, str string, params ...any) string {
|
||||
}
|
||||
|
||||
func (s *StdoutLogging) LogPlainError(err error) (int, error) {
|
||||
return s.Stderr.WriteString(prepareMsg(time.Since(s.Date), s.Id, "%#v\n", err))
|
||||
return s.Stderr.WriteString(prepareMsg(time.Since(s.Date), s.Id, "%s\n", err.Error()))
|
||||
}
|
||||
|
||||
func (s *StdoutLogging) LogError(str string, params ...any) (int, error) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -34,14 +35,15 @@ func NewObsClient(host string) (*ObsClient, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
type RepositoryMeta struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Arch []string `xml:"arch"`
|
||||
Path []struct {
|
||||
XMLName xml.Name `xml:"path"`
|
||||
type RepositoryPathMeta struct {
|
||||
Project string `xml:"project,attr"`
|
||||
Repository string `xml:"repository,attr"`
|
||||
}
|
||||
|
||||
type RepositoryMeta struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Archs []string `xml:"arch"`
|
||||
Paths []RepositoryPathMeta `xml:"path"`
|
||||
}
|
||||
|
||||
type Flags struct {
|
||||
@ -53,11 +55,13 @@ type ProjectMeta struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Title string `xml:"title"`
|
||||
Description string `xml:"description"`
|
||||
ScmSync string `xml:"xmlsync"`
|
||||
Repositories []Repository `xml:"repository"`
|
||||
ScmSync string `xml:"scmsync"`
|
||||
Repositories []RepositoryMeta `xml:"repository"`
|
||||
|
||||
BuildFlags Flags `xml:"build"`
|
||||
PublicFlags Flags `xml:"publish"`
|
||||
DebugFlags Flags `xml:"debuginfo"`
|
||||
UseForBuild Flags `xml:"useforbuild"`
|
||||
}
|
||||
|
||||
func parseProjectMeta(data []byte) (*ProjectMeta, error) {
|
||||
@ -77,6 +81,8 @@ func (c *ObsClient) GetProjectMeta(project string) (*ProjectMeta, error) {
|
||||
return nil, err
|
||||
}
|
||||
req.SetBasicAuth(c.user, c.password)
|
||||
log.Printf("request: %#v", *req.URL)
|
||||
log.Printf("headers: %#v", req.Header)
|
||||
res, err := c.client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
@ -100,6 +106,57 @@ func (c *ObsClient) GetProjectMeta(project string) (*ProjectMeta, error) {
|
||||
return parseProjectMeta(data)
|
||||
}
|
||||
|
||||
func ObsSafeProjectName(prjname string) string {
|
||||
if len(prjname) < 1 {
|
||||
return prjname
|
||||
} else if len(prjname) > 200 {
|
||||
prjname = prjname[:199]
|
||||
}
|
||||
|
||||
switch prjname[0] {
|
||||
case '_', '.', ':':
|
||||
prjname = "X" + prjname[1:]
|
||||
// no UTF-8 in OBS :(
|
||||
// prjname = "_" + prjname[1:]
|
||||
// case ':':
|
||||
// prjname = ":" + prjname[1:]
|
||||
// case '.':
|
||||
// prjname = "․" + prjname[1:]
|
||||
}
|
||||
|
||||
return prjname
|
||||
}
|
||||
|
||||
func (c *ObsClient) SetProjectMeta(meta *ProjectMeta) (error) {
|
||||
|
||||
req, err := http.NewRequest("PUT", c.baseUrl.JoinPath("source", meta.Name, "_meta").String(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.SetBasicAuth(c.user, c.password)
|
||||
xml, err := xml.Marshal(meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Body = io.NopCloser(bytes.NewReader(xml))
|
||||
log.Printf("headers: %#v", req.Header)
|
||||
log.Printf("xml: %s", xml)
|
||||
res, err := c.client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch res.StatusCode {
|
||||
case 200:
|
||||
break
|
||||
default:
|
||||
return fmt.Errorf("Unexpected return code: %d", res.StatusCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ObsClient) DeleteProject(project string) error {
|
||||
req, err := http.NewRequest("DELETE", c.baseUrl.JoinPath("source", project).String(), nil)
|
||||
if err != nil {
|
||||
|
@ -24,8 +24,8 @@ func RequireGiteaSecretToken() error {
|
||||
}
|
||||
|
||||
func RequireObsSecretToken() error {
|
||||
obsPassword = os.Getenv(ObsUserEnv)
|
||||
obsUser = os.Getenv(ObsPasswordEnv)
|
||||
obsUser = os.Getenv(ObsUserEnv)
|
||||
obsPassword = os.Getenv(ObsPasswordEnv)
|
||||
|
||||
if len(obsPassword) < 10 || len(obsUser) < 2 {
|
||||
return fmt.Errorf("Missing OBS authentication: %s %s", ObsUserEnv, ObsPasswordEnv)
|
||||
|
@ -1,10 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"src.opensuse.org/autogits/common"
|
||||
"src.opensuse.org/autogits/common/gitea-generated/models"
|
||||
@ -12,6 +15,7 @@ import (
|
||||
|
||||
const (
|
||||
GitAuthor = "GiteaBot - Obs Staging"
|
||||
BotName = "ObsStaging"
|
||||
ObsBuildBot = "/obsbuild"
|
||||
)
|
||||
|
||||
@ -24,14 +28,20 @@ func failOnError(err error, msg string) {
|
||||
}
|
||||
}
|
||||
|
||||
func allocateRequestHandler() *common.RequestHandler {
|
||||
return &common.RequestHandler{
|
||||
Logger: common.CreateStdoutLogger(os.Stdout, os.Stdout),
|
||||
func fetchPrGit(h *common.RequestHandler, pr *models.PullRequest) error {
|
||||
// clone PR head and base and return path
|
||||
if _, err := os.Stat(path.Join(h.GitPath, pr.Head.Sha)); os.IsNotExist(err) {
|
||||
h.GitExec("", "clone", "--depth", "1", pr.Head.Repo.CloneURL, pr.Head.Sha)
|
||||
h.GitExec(pr.Head.Sha, "fetch", "--depth", "1", "origin", pr.Head.Sha, pr.Base.Sha)
|
||||
} else if err != nil {
|
||||
h.Error = err
|
||||
}
|
||||
|
||||
return h.Error
|
||||
}
|
||||
|
||||
func processPullNotification(h *common.RequestHandler, notification *models.NotificationSubject) {
|
||||
rx := regexp.MustCompile(`^https://src\.(?:open)?suse\.org/api/v\d+/repos/(?<org>[a-zA-Z0-9]+)/(?<project>[_a-zA-Z0-9]+)/issues/(?<num>[0-9]+)$`)
|
||||
rx := regexp.MustCompile(`^https://src\.(?:open)?suse\.(?:org|de)/api/v\d+/repos/(?<org>[a-zA-Z0-9]+)/(?<project>[_a-zA-Z0-9]+)/issues/(?<num>[0-9]+)$`)
|
||||
match := rx.FindStringSubmatch(notification.URL)
|
||||
if match == nil {
|
||||
log.Panicf("Unexpected format of notification: %s", notification.URL)
|
||||
@ -64,26 +74,89 @@ func processPullNotification(h *common.RequestHandler, notification *models.Noti
|
||||
for _, review := range reviews {
|
||||
h.Log("state: %s, body: %s, id:%d\n", string(review.State), review.Body, review.ID)
|
||||
|
||||
if *review.User.LoginName != "autogits_obs_staging_bot" {
|
||||
if review.User.UserName != "autogits_obs_staging_bot" {
|
||||
continue
|
||||
}
|
||||
|
||||
switch review.State {
|
||||
case common.ReviewStateUnknown, common.ReviewStateRequestReview:
|
||||
err := fetchPrGit(h, pr)
|
||||
if err != nil {
|
||||
h.LogError("Cannot fetch PR git: %s", pr.URL)
|
||||
return
|
||||
}
|
||||
|
||||
dir := pr.Head.Sha
|
||||
headSubmodules := h.GitSubmoduleList(dir, pr.Head.Sha)
|
||||
baseSubmodules := h.GitSubmoduleList(dir, pr.Base.Sha)
|
||||
|
||||
// find modified submodules and new submodules -- build them
|
||||
|
||||
h.Log("processing state...")
|
||||
|
||||
switch review.State {
|
||||
// create build project, if doesn't exist, and add it to pending requests
|
||||
case common.ReviewStateUnknown, common.ReviewStateRequestReview:
|
||||
h.Log("repo content fetching ...")
|
||||
buildPrjBytes, err := h.GetPullRequestFileContent(pr, "project.build")
|
||||
if err != nil {
|
||||
h.LogPlainError(err)
|
||||
_, err := h.AddReviewComment(pr, common.ReviewStateRequestChanges, "Cannot find reference project")
|
||||
if err != nil {
|
||||
h.LogPlainError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
buildPrj := strings.TrimSpace(string(buildPrjBytes))
|
||||
meta, err := obsClient.GetProjectMeta(string(buildPrj))
|
||||
if err != nil {
|
||||
h.Log("error fetching project meta for %s: %v", buildPrj, err)
|
||||
return
|
||||
}
|
||||
|
||||
// generate new project with paths pointinig back to original repos
|
||||
// disable publishing
|
||||
|
||||
// TODO: escape things here
|
||||
meta.Name = fmt.Sprintf("%s:%s:%s:PR:%d",
|
||||
obsClient.HomeProject,
|
||||
common.ObsSafeProjectName(pr.Base.Repo.Owner.UserName),
|
||||
common.ObsSafeProjectName(pr.Base.Repo.Name),
|
||||
pr.Index,
|
||||
)
|
||||
meta.Description = fmt.Sprintf(`Pull request build job: %s%s PR#%d`,
|
||||
"https://src.opensuse.org", pr.Base.Repo.Name, pr.Index)
|
||||
// meta.ScmSync = pr.Head.Repo.CloneURL + "?" +
|
||||
meta.Title = fmt.Sprintf("PR#%d to %s", pr.Index, pr.Base.Name)
|
||||
meta.PublicFlags = common.Flags{Contents: "<disable/>"}
|
||||
|
||||
// set paths to parent project
|
||||
for idx, r := range meta.Repositories {
|
||||
meta.Repositories[idx].Paths = []common.RepositoryPathMeta{{
|
||||
Project: buildPrj,
|
||||
Repository: r.Name,
|
||||
}}
|
||||
}
|
||||
|
||||
h.Log("%#v", meta)
|
||||
return
|
||||
|
||||
err = obsClient.SetProjectMeta(meta)
|
||||
if err != nil {
|
||||
h.LogError("cannot create meta project: %#v", err)
|
||||
}
|
||||
case common.ReviewStatePending:
|
||||
// waiting for build results
|
||||
case common.ReviewStateApproved:
|
||||
// done, mark notification as read
|
||||
case common.ReviewStateRequestChanges:
|
||||
// build failures, mark notification as read
|
||||
h.Log("processing request for failed request changes...")
|
||||
// build failures, nothing to do here, mark notification as read
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pollWorkNotifications() {
|
||||
h := allocateRequestHandler()
|
||||
h := common.CreateRequestHandler(GitAuthor, BotName)
|
||||
data, err := h.GetNotifications(nil)
|
||||
|
||||
if err != nil {
|
||||
@ -117,7 +190,25 @@ func main() {
|
||||
|
||||
pollWorkNotifications()
|
||||
|
||||
/*
|
||||
h := allocateRequestHandler()
|
||||
//" autogits/_ObsPrj/raw/project.build?ref=9680b770855e4fc2e9d9cebbd87e6a0d119693c3e03db187494e3aeff727312f"
|
||||
// https://src.opensuse.org/adamm/autogits/commit/8db4d8c3021fc21baa606b87eaad0e476bb7f624f76cb37b6a1819bdb5f04b43#diff-6e698c75c21cd4458440e8a71408c6301ba3a562
|
||||
f, err := h.GetRepositoryFileContent(
|
||||
&models.Repository{
|
||||
Owner: &models.User{
|
||||
UserName: "adamm",
|
||||
},
|
||||
Name: "autogits",
|
||||
},
|
||||
"54e418acaf960c5ed8be7f4a29616ae7b5eb75f797f7ed4d487f79485d056108",
|
||||
"bots-common/obs/client.go")
|
||||
|
||||
if err != nil {
|
||||
h.LogPlainError(err)
|
||||
}
|
||||
h.Log("len: %d", len(f))
|
||||
*/
|
||||
stuck := make(chan int)
|
||||
<-stuck
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user