44 | {message} 45 |
46 | ) : ( 47 | <>> 48 | )} 49 | > 50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /internal/server/api/v1/repos/commit_status_list.go: -------------------------------------------------------------------------------- 1 | package repos 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "go.uber.org/zap" 8 | 9 | gb "github.com/gitploy-io/gitploy/internal/server/global" 10 | "github.com/gitploy-io/gitploy/model/ent" 11 | "github.com/gitploy-io/gitploy/model/extent" 12 | ) 13 | 14 | func (s *CommitAPI) ListStatuses(c *gin.Context) { 15 | ctx := c.Request.Context() 16 | 17 | var ( 18 | sha = c.Param("sha") 19 | ) 20 | 21 | uv, _ := c.Get(gb.KeyUser) 22 | u := uv.(*ent.User) 23 | 24 | rv, _ := c.Get(KeyRepo) 25 | repo := rv.(*ent.Repo) 26 | 27 | ss, err := s.i.ListCommitStatuses(ctx, u, repo, sha) 28 | if err != nil { 29 | s.log.Check(gb.GetZapLogLevel(err), "Failed to list commit statuses.").Write(zap.Error(err)) 30 | gb.ResponseWithError(c, err) 31 | return 32 | } 33 | 34 | gb.Response(c, http.StatusOK, map[string]interface{}{ 35 | "state": mergeState(ss), 36 | "statuses": ss, 37 | }) 38 | } 39 | 40 | func mergeState(ss []*extent.Status) string { 41 | // The state is failure if one of them is failure. 42 | for _, s := range ss { 43 | if s.State == extent.StatusStateFailure || s.State == extent.StatusStateCancelled { 44 | return string(extent.StatusStateFailure) 45 | } 46 | } 47 | 48 | for _, s := range ss { 49 | if s.State == extent.StatusStatePending { 50 | return string(extent.StatusStatePending) 51 | } 52 | } 53 | 54 | return string(extent.StatusStateSuccess) 55 | } 56 | -------------------------------------------------------------------------------- /model/ent/schema/deploymentstatus.go: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | import ( 4 | "entgo.io/ent" 5 | "entgo.io/ent/dialect/entsql" 6 | "entgo.io/ent/schema/edge" 7 | "entgo.io/ent/schema/field" 8 | ) 9 | 10 | // DeploymentStatus holds the schema definition for the DeploymentStatus entity. 11 | type DeploymentStatus struct { 12 | ent.Schema 13 | } 14 | 15 | // Fields of the DeploymentStatus. 16 | func (DeploymentStatus) Fields() []ent.Field { 17 | return []ent.Field{ 18 | field.String("status"), 19 | field.String("description"). 20 | Optional(), 21 | field.String("log_url"). 22 | Optional(), 23 | field.Time("created_at"). 24 | Default(nowUTC), 25 | field.Time("updated_at"). 26 | Default(nowUTC). 27 | UpdateDefault(nowUTC), 28 | 29 | // edges 30 | field.Int("deployment_id"), 31 | // Denormalize the 'repo_id' field so that 32 | // we can figure out the repository easily. 33 | field.Int64("repo_id"). 34 | Optional(), 35 | } 36 | } 37 | 38 | // Edges of the DeploymentStatus. 39 | func (DeploymentStatus) Edges() []ent.Edge { 40 | return []ent.Edge{ 41 | edge.From("deployment", Deployment.Type). 42 | Ref("deployment_statuses"). 43 | Field("deployment_id"). 44 | Unique(). 45 | Required(), 46 | edge.From("repo", Repo.Type). 47 | Ref("deployment_statuses"). 48 | Field("repo_id"). 49 | Unique(), 50 | edge.To("event", Event.Type). 51 | Annotations(entsql.Annotation{ 52 | OnDelete: entsql.Cascade, 53 | }), 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /openapi/v1/paths/repos/deployment_remote_statuses.yaml: -------------------------------------------------------------------------------- 1 | post: 2 | tags: 3 | - Repo 4 | summary: Create a new remote deployment status. 5 | parameters: 6 | - in: path 7 | name: namespace 8 | required: true 9 | schema: 10 | type: string 11 | - in: path 12 | name: name 13 | required: true 14 | schema: 15 | type: string 16 | - in: path 17 | name: number 18 | required: true 19 | schema: 20 | type: integer 21 | description: The deployment number. 22 | requestBody: 23 | content: 24 | application/json: 25 | schema: 26 | type: object 27 | properties: 28 | status: 29 | type: string 30 | description: 31 | type: string 32 | log_url: 33 | type: string 34 | required: 35 | - status 36 | responses: 37 | '200': 38 | description: Return the deployment status. 39 | content: 40 | application/json: 41 | schema: 42 | $ref: '../../schemas/RemoteDeploymentStatus.yaml' 43 | '401': 44 | $ref: '../../responses.yaml#/401Unauthorized' 45 | '402': 46 | $ref: '../../responses.yaml#/402PaymentRequired' 47 | '403': 48 | $ref: '../../responses.yaml#/403Forbidden' 49 | '422': 50 | $ref: '../../responses.yaml#/422UnprocessableEntity' 51 | '500': 52 | $ref: '../../responses.yaml#/500InternalError' -------------------------------------------------------------------------------- /openapi/v1/paths/repos/deployment_changes.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | tags: 3 | - Repo 4 | summary: List commits from the environment state. 5 | description: > 6 | List commits from the environment state, internally, 7 | it compares with the previous succeed deployment. 8 | parameters: 9 | - in: path 10 | name: namespace 11 | required: true 12 | schema: 13 | type: string 14 | - in: path 15 | name: name 16 | required: true 17 | schema: 18 | type: string 19 | - in: path 20 | name: number 21 | required: true 22 | schema: 23 | type: integer 24 | description: The deployment number. 25 | - in: query 26 | name: page 27 | schema: 28 | type: integer 29 | default: 1 30 | - in: query 31 | name: per_page 32 | schema: 33 | type: integer 34 | default: 30 35 | responses: 36 | '200': 37 | description: Commits 38 | content: 39 | application/json: 40 | schema: 41 | type: array 42 | items: 43 | $ref: '../../schemas/Commit.yaml' 44 | '401': 45 | $ref: '../../responses.yaml#/401Unauthorized' 46 | '402': 47 | $ref: '../../responses.yaml#/402PaymentRequired' 48 | '403': 49 | $ref: '../../responses.yaml#/403Forbidden' 50 | '404': 51 | $ref: '../../responses.yaml#/404NotFound' 52 | '500': 53 | $ref: '../../responses.yaml#/500InternalError' -------------------------------------------------------------------------------- /model/ent/notificationrecord/notificationrecord.go: -------------------------------------------------------------------------------- 1 | // Code generated by entc, DO NOT EDIT. 2 | 3 | package notificationrecord 4 | 5 | const ( 6 | // Label holds the string label denoting the notificationrecord type in the database. 7 | Label = "notification_record" 8 | // FieldID holds the string denoting the id field in the database. 9 | FieldID = "id" 10 | // FieldEventID holds the string denoting the event_id field in the database. 11 | FieldEventID = "event_id" 12 | // EdgeEvent holds the string denoting the event edge name in mutations. 13 | EdgeEvent = "event" 14 | // Table holds the table name of the notificationrecord in the database. 15 | Table = "notification_records" 16 | // EventTable is the table that holds the event relation/edge. 17 | EventTable = "notification_records" 18 | // EventInverseTable is the table name for the Event entity. 19 | // It exists in this package in order to avoid circular dependency with the "event" package. 20 | EventInverseTable = "events" 21 | // EventColumn is the table column denoting the event relation/edge. 22 | EventColumn = "event_id" 23 | ) 24 | 25 | // Columns holds all SQL columns for notificationrecord fields. 26 | var Columns = []string{ 27 | FieldID, 28 | FieldEventID, 29 | } 30 | 31 | // ValidColumn reports if the column name is valid (part of the table columns). 32 | func ValidColumn(column string) bool { 33 | for i := range Columns { 34 | if column == Columns[i] { 35 | return true 36 | } 37 | } 38 | return false 39 | } 40 | -------------------------------------------------------------------------------- /pkg/api/deployment_status_test.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | "testing" 7 | 8 | "github.com/gitploy-io/gitploy/model/ent" 9 | "github.com/gitploy-io/gitploy/model/extent" 10 | "gopkg.in/h2non/gock.v1" 11 | ) 12 | 13 | func TestDeploymentStatus_List(t *testing.T) { 14 | t.Run("Return the list of statuses.", func(t *testing.T) { 15 | dss := []*ent.DeploymentStatus{ 16 | {ID: 1}, 17 | } 18 | gock.New("https://cloud.gitploy.io"). 19 | Get("/api/v1/repos/gitploy-io/gitploy/deployments/1/statuses"). 20 | Reply(200). 21 | JSON(dss) 22 | 23 | c := NewClient("https://cloud.gitploy.io/", http.DefaultClient) 24 | 25 | _, err := c.DeploymentStatus.List(context.Background(), "gitploy-io", "gitploy", 1, &ListOptions{}) 26 | if err != nil { 27 | t.Fatalf("Create returns an error: %s", err) 28 | } 29 | }) 30 | } 31 | 32 | func TestDeploymentStatus_Create(t *testing.T) { 33 | t.Run("Return the deployment statuses.", func(t *testing.T) { 34 | gock.New("https://cloud.gitploy.io"). 35 | Post("/api/v1/repos/gitploy-io/gitploy/deployments/1/remote-statuses"). 36 | Reply(201). 37 | JSON(extent.RemoteDeploymentStatus{ID: 1}) 38 | 39 | c := NewClient("https://cloud.gitploy.io/", http.DefaultClient) 40 | 41 | _, err := c.DeploymentStatus.CreateRemote(context.Background(), "gitploy-io", "gitploy", 1, &DeploymentStatusCreateRemoteRequest{}) 42 | if err != nil { 43 | t.Fatalf("Create returns an error: %s", err) 44 | } 45 | }) 46 | } 47 | -------------------------------------------------------------------------------- /internal/server/api/v1/repos/review_list.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Gitploy.IO Inc. All rights reserved. 2 | // Use of this source code is governed by the Gitploy Non-Commercial License 3 | // that can be found in the LICENSE file. 4 | 5 | //go:build !oss 6 | 7 | package repos 8 | 9 | import ( 10 | "net/http" 11 | "strconv" 12 | 13 | "github.com/gin-gonic/gin" 14 | gb "github.com/gitploy-io/gitploy/internal/server/global" 15 | "github.com/gitploy-io/gitploy/model/ent" 16 | "github.com/gitploy-io/gitploy/pkg/e" 17 | "go.uber.org/zap" 18 | ) 19 | 20 | func (s *ReviewAPI) List(c *gin.Context) { 21 | ctx := c.Request.Context() 22 | 23 | var ( 24 | number int 25 | err error 26 | ) 27 | 28 | if number, err = strconv.Atoi(c.Param("number")); err != nil { 29 | s.log.Warn("Invalid parameter: number must be integer.", zap.Error(err)) 30 | gb.ResponseWithError(c, e.NewError(e.ErrorCodeParameterInvalid, err)) 31 | return 32 | } 33 | 34 | vr, _ := c.Get(KeyRepo) 35 | re := vr.(*ent.Repo) 36 | 37 | d, err := s.i.FindDeploymentOfRepoByNumber(ctx, re, number) 38 | if err != nil { 39 | s.log.Check(gb.GetZapLogLevel(err), "Failed to find the deployment.").Write(zap.Error(err)) 40 | gb.ResponseWithError(c, err) 41 | return 42 | } 43 | 44 | rvs, err := s.i.ListReviews(ctx, d) 45 | if err != nil { 46 | s.log.Check(gb.GetZapLogLevel(err), "Failed to list reviews.").Write(zap.Error(err)) 47 | gb.ResponseWithError(c, err) 48 | return 49 | } 50 | 51 | gb.Response(c, http.StatusOK, rvs) 52 | } 53 | -------------------------------------------------------------------------------- /openapi/v1/responses.yaml: -------------------------------------------------------------------------------- 1 | 400BadRequest: 2 | description: | 3 | The request could not be understood by the server due to malformed syntax. 4 | content: 5 | application/json: 6 | schema: 7 | $ref: './schemas/Error.yaml' 8 | 9 | 401Unauthorized: 10 | description: Unauthorized access 11 | content: 12 | application/json: 13 | schema: 14 | $ref: './schemas/Error.yaml' 15 | 16 | 402PaymentRequired: 17 | description: License is expired 18 | content: 19 | application/json: 20 | schema: 21 | $ref: './schemas/Error.yaml' 22 | 23 | 403Forbidden: 24 | description: Permisson denied 25 | content: 26 | application/json: 27 | schema: 28 | $ref: './schemas/Error.yaml' 29 | 30 | 404NotFound: 31 | description: The resource is not found 32 | content: 33 | application/json: 34 | schema: 35 | $ref: './schemas/Error.yaml' 36 | 37 | 409Conflict: 38 | description: The conflict occurs 39 | content: 40 | application/json: 41 | schema: 42 | $ref: './schemas/Error.yaml' 43 | 44 | 422UnprocessableEntity: 45 | description: | 46 | the syntax of the request entity is correct but was unable to process the contained instructions. 47 | content: 48 | application/json: 49 | schema: 50 | $ref: './schemas/Error.yaml' 51 | 52 | 500InternalError: 53 | description: Server internal error 54 | content: 55 | application/json: 56 | schema: 57 | $ref: './schemas/Error.yaml' 58 | -------------------------------------------------------------------------------- /ui/src/apis/tag.ts: -------------------------------------------------------------------------------- 1 | import { StatusCodes } from 'http-status-codes'; 2 | 3 | import { instance, headers } from './setting'; 4 | import { _fetch } from './_base'; 5 | import { Tag, HttpNotFoundError } from '../models'; 6 | 7 | export const listTags = async ( 8 | namespace: string, 9 | name: string, 10 | page = 1, 11 | perPage = 30 12 | ): Promise
25 |
34 |