This is an automated email from the ASF dual-hosted git repository.

lynwee pushed a commit to branch dev-multi-env
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git


The following commit(s) were added to refs/heads/dev-multi-env by this push:
     new bd6a0467c feat(githubgraphql): add releases
bd6a0467c is described below

commit bd6a0467c8718b190fe7d5fd049d375e0cd68795
Author: d4x1 <[email protected]>
AuthorDate: Tue May 14 19:47:45 2024 +0800

    feat(githubgraphql): add releases
---
 .../core/models/domainlayer/devops/cicd_release.go |  53 +++++++++
 .../migrationscripts/20240514_add_cicd_release.go  |  69 +++++++++++
 backend/core/models/migrationscripts/register.go   |   1 +
 .../20240514_add_github_release.go                 |  66 +++++++++++
 .../github/models/migrationscripts/register.go     |   1 +
 backend/plugins/github/models/release.go           |  50 ++++++++
 backend/plugins/github/tasks/release_convertor.go  | 103 ++++++++++++++++
 backend/plugins/github_graphql/impl/impl.go        |   5 +
 .../github_graphql/tasks/release_collector.go      | 130 +++++++++++++++++++++
 .../github_graphql/tasks/release_extractor.go      | 105 +++++++++++++++++
 10 files changed, 583 insertions(+)

diff --git a/backend/core/models/domainlayer/devops/cicd_release.go 
b/backend/core/models/domainlayer/devops/cicd_release.go
new file mode 100644
index 000000000..f9ed74012
--- /dev/null
+++ b/backend/core/models/domainlayer/devops/cicd_release.go
@@ -0,0 +1,53 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 devops
+
+import (
+       "github.com/apache/incubator-devlake/core/models/domainlayer"
+       "time"
+)
+
+type CicdRelease struct {
+       domainlayer.DomainEntity
+       PublishedAt time.Time `json:"publishedAt"`
+
+       CicdScopeId string `gorm:"index;type:varchar(255)"`
+
+       Name         string `gorm:"type:varchar(255)"`
+       DisplayTitle string `gorm:"type:varchar(255)"`
+       Description  string `json:"description"`
+       URL          string `json:"url"`
+
+       IsDraft      bool `json:"isDraft"`
+       IsLatest     bool `json:"isLatest"`
+       IsPrerelease bool `json:"isPrerelease"`
+
+       AuthorID string `json:"id" gorm:"type:varchar(255)"`
+
+       RepoId string `gorm:"type:varchar(255)"`
+       //RepoUrl string `gorm:"index;not null"`
+
+       TagName string `json:"tagName"`
+       //CommitSha string `gorm:"primaryKey;type:varchar(255)"`
+       //CommitMsg string
+       //RefName   string `gorm:"type:varchar(255)"`
+}
+
+func (CicdRelease) TableName() string {
+       return "cicd_releases"
+}
diff --git a/backend/core/models/migrationscripts/20240514_add_cicd_release.go 
b/backend/core/models/migrationscripts/20240514_add_cicd_release.go
new file mode 100644
index 000000000..9f6d22fcd
--- /dev/null
+++ b/backend/core/models/migrationscripts/20240514_add_cicd_release.go
@@ -0,0 +1,69 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 migrationscripts
+
+import (
+       
"github.com/apache/incubator-devlake/core/models/migrationscripts/archived"
+       "time"
+
+       "github.com/apache/incubator-devlake/core/context"
+       "github.com/apache/incubator-devlake/core/errors"
+       "github.com/apache/incubator-devlake/core/plugin"
+)
+
+var _ plugin.MigrationScript = (*addCicdRelease)(nil)
+
+type cicdRelease20240514 struct {
+       archived.DomainEntity
+       PublishedAt time.Time `json:"publishedAt"`
+
+       CicdScopeId string `gorm:"index;type:varchar(255)"`
+
+       Name         string `gorm:"type:varchar(255)"`
+       DisplayTitle string `gorm:"type:varchar(255)"`
+       Description  string `json:"description"`
+       URL          string `json:"url"`
+
+       IsDraft      bool `json:"isDraft"`
+       IsLatest     bool `json:"isLatest"`
+       IsPrerelease bool `json:"isPrerelease"`
+
+       AuthorID string `json:"id" gorm:"type:varchar(255)"`
+
+       RepoId string `gorm:"type:varchar(255)"`
+
+       TagName string `json:"tagName"`
+}
+
+func (cicdRelease20240514) TableName() string {
+       return "cicd_releases"
+}
+
+type addCicdRelease struct{}
+
+func (*addCicdRelease) Up(basicRes context.BasicRes) errors.Error {
+       return basicRes.GetDal().AutoMigrate(cicdRelease20240514{})
+}
+
+func (*addCicdRelease) Version() uint64 {
+       return 20240514181200
+}
+
+func (*addCicdRelease) Name() string {
+       return "add cicd_releases table"
+}
diff --git a/backend/core/models/migrationscripts/register.go 
b/backend/core/models/migrationscripts/register.go
index b79d0bc4c..ac7f66fc9 100644
--- a/backend/core/models/migrationscripts/register.go
+++ b/backend/core/models/migrationscripts/register.go
@@ -113,5 +113,6 @@ func All() []plugin.MigrationScript {
                new(addSubtaskField),
                new(addDisplayTitleAndUrl),
                new(addSubtaskStates),
+               new(addCicdRelease),
        }
 }
diff --git 
a/backend/plugins/github/models/migrationscripts/20240514_add_github_release.go 
b/backend/plugins/github/models/migrationscripts/20240514_add_github_release.go
new file mode 100644
index 000000000..998aec2ff
--- /dev/null
+++ 
b/backend/plugins/github/models/migrationscripts/20240514_add_github_release.go
@@ -0,0 +1,66 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 migrationscripts
+
+import (
+       "github.com/apache/incubator-devlake/core/context"
+       "github.com/apache/incubator-devlake/core/errors"
+       
"github.com/apache/incubator-devlake/core/models/migrationscripts/archived"
+       "github.com/apache/incubator-devlake/helpers/migrationhelper"
+       "time"
+)
+
+type addReleaseTable struct{}
+
+type release20240514 struct {
+       archived.NoPKModel `json:"-" mapstructure:"-"`
+       ConnectionId       uint64    `json:"connection_id" gorm:"primaryKey"`
+       GithubId           int       `json:"github_id"`
+       Id                 string    `json:"id" 
gorm:"type:varchar(255);primaryKey"`
+       AuthorName         string    `json:"name"`
+       AuthorID           string    `json:"id"`
+       CreatedAt          time.Time `json:"createdAt"`
+       DatabaseID         int       `json:"databaseId"`
+       Description        string    `json:"description"`
+       DescriptionHTML    string    `json:"descriptionHTML"`
+       IsDraft            bool      `json:"isDraft"`
+       IsLatest           bool      `json:"isLatest"`
+       IsPrerelease       bool      `json:"isPrerelease"`
+       Name               string    `json:"name"`
+       PublishedAt        time.Time `json:"publishedAt"`
+       ResourcePath       string    `json:"resourcePath"`
+       TagName            string    `json:"tagName"`
+       UpdatedAt          time.Time `json:"updatedAt"`
+       URL                string    `json:"url"`
+}
+
+func (release20240514) TableName() string {
+       return "_tool_github_releases"
+}
+
+func (u *addReleaseTable) Up(baseRes context.BasicRes) errors.Error {
+       return migrationhelper.AutoMigrateTables(baseRes, &release20240514{})
+}
+
+func (*addReleaseTable) Version() uint64 {
+       return 20240514182300
+}
+
+func (*addReleaseTable) Name() string {
+       return "add table _tool_github_releases"
+}
diff --git a/backend/plugins/github/models/migrationscripts/register.go 
b/backend/plugins/github/models/migrationscripts/register.go
index 1f09898df..89ebfa429 100644
--- a/backend/plugins/github/models/migrationscripts/register.go
+++ b/backend/plugins/github/models/migrationscripts/register.go
@@ -48,5 +48,6 @@ func All() []plugin.MigrationScript {
                new(addEnvNamePattern),
                new(modifyIssueTypeLength),
                new(addWorkflowDisplayTitle),
+               new(addReleaseTable),
        }
 }
diff --git a/backend/plugins/github/models/release.go 
b/backend/plugins/github/models/release.go
new file mode 100644
index 000000000..453db7dda
--- /dev/null
+++ b/backend/plugins/github/models/release.go
@@ -0,0 +1,50 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 models
+
+import (
+       "time"
+
+       "github.com/apache/incubator-devlake/core/models/common"
+)
+
+type GithubRelease struct {
+       common.NoPKModel `json:"-" mapstructure:"-"`
+       ConnectionId     uint64    `json:"connection_id" gorm:"primaryKey"`
+       GithubId         int       `json:"github_id"`
+       Id               string    `json:"id" 
gorm:"type:varchar(255);primaryKey"`
+       AuthorName       string    `json:"name"`
+       AuthorID         string    `json:"id"`
+       CreatedAt        time.Time `json:"createdAt"`
+       DatabaseID       int       `json:"databaseId"`
+       Description      string    `json:"description"`
+       DescriptionHTML  string    `json:"descriptionHTML"`
+       IsDraft          bool      `json:"isDraft"`
+       IsLatest         bool      `json:"isLatest"`
+       IsPrerelease     bool      `json:"isPrerelease"`
+       Name             string    `json:"name"`
+       PublishedAt      time.Time `json:"publishedAt"`
+       ResourcePath     string    `json:"resourcePath"`
+       TagName          string    `json:"tagName"`
+       UpdatedAt        time.Time `json:"updatedAt"`
+       URL              string    `json:"url"`
+}
+
+func (GithubRelease) TableName() string {
+       return "_tool_github_releases"
+}
diff --git a/backend/plugins/github/tasks/release_convertor.go 
b/backend/plugins/github/tasks/release_convertor.go
new file mode 100644
index 000000000..bcf4914ac
--- /dev/null
+++ b/backend/plugins/github/tasks/release_convertor.go
@@ -0,0 +1,103 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 tasks
+
+import (
+       "reflect"
+
+       "github.com/apache/incubator-devlake/core/dal"
+       "github.com/apache/incubator-devlake/core/errors"
+       "github.com/apache/incubator-devlake/core/models/domainlayer"
+       "github.com/apache/incubator-devlake/core/models/domainlayer/devops"
+       "github.com/apache/incubator-devlake/core/models/domainlayer/didgen"
+       "github.com/apache/incubator-devlake/core/plugin"
+       "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+       "github.com/apache/incubator-devlake/plugins/github/models"
+)
+
+func init() {
+       RegisterSubtaskMeta(&ConvertReleasesMeta)
+}
+
+const (
+       RAW_RELEASE_TABLE = "github_graphql_release"
+)
+
+var ConvertReleasesMeta = plugin.SubTaskMeta{
+       Name:             "Convert Releases",
+       EntryPoint:       ConvertRelease,
+       EnabledByDefault: true,
+       Description:      "Convert tool layer table github_releases into domain 
layer table releases",
+       DomainTypes:      []string{plugin.DOMAIN_TYPE_CICD},
+       DependencyTables: []string{models.GithubRelease{}.TableName()},
+       ProductTables:    []string{devops.CicdRelease{}.TableName()},
+}
+
+func ConvertRelease(taskCtx plugin.SubTaskContext) errors.Error {
+       db := taskCtx.GetDal()
+       rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, 
RAW_RELEASE_TABLE)
+       cursor, err := db.Cursor(
+               dal.From(&models.GithubRelease{}),
+               dal.Where("connection_id = ? and github_id = ?", 
data.Options.ConnectionId, data.Options.GithubId),
+       )
+       if err != nil {
+               return err
+       }
+       defer cursor.Close()
+
+       releaseIdGen := didgen.NewDomainIdGenerator(&models.GithubRelease{})
+       releaseScopeIdGen := didgen.NewDomainIdGenerator(&models.GithubRepo{})
+
+       converter, err := api.NewDataConverter(api.DataConverterArgs{
+               InputRowType:       reflect.TypeOf(models.GithubRelease{}),
+               Input:              cursor,
+               RawDataSubTaskArgs: *rawDataSubTaskArgs,
+               Convert: func(inputRow interface{}) ([]interface{}, 
errors.Error) {
+                       githubRelease := inputRow.(*models.GithubRelease)
+                       release := &devops.CicdRelease{
+                               DomainEntity: domainlayer.DomainEntity{
+                                       Id: 
releaseIdGen.Generate(githubRelease.ConnectionId, githubRelease.Id),
+                               },
+                               PublishedAt:  githubRelease.PublishedAt,
+                               CicdScopeId:  
releaseScopeIdGen.Generate(githubRelease.ConnectionId, githubRelease.GithubId),
+                               Name:         githubRelease.Name,
+                               DisplayTitle: githubRelease.Name,
+                               Description:  githubRelease.Description,
+                               URL:          githubRelease.URL,
+                               IsDraft:      githubRelease.IsDraft,
+                               IsLatest:     githubRelease.IsLatest,
+                               IsPrerelease: githubRelease.IsPrerelease,
+                               TagName:      githubRelease.TagName,
+
+                               AuthorID: githubRelease.AuthorID,
+
+                               RepoId: 
releaseScopeIdGen.Generate(githubRelease.ConnectionId, githubRelease.GithubId),
+                       }
+
+                       return []interface{}{
+                               release,
+                       }, nil
+               },
+       })
+
+       if err != nil {
+               return err
+       }
+
+       return converter.Execute()
+}
diff --git a/backend/plugins/github_graphql/impl/impl.go 
b/backend/plugins/github_graphql/impl/impl.go
index 46dbe6fa0..58a8d04f6 100644
--- a/backend/plugins/github_graphql/impl/impl.go
+++ b/backend/plugins/github_graphql/impl/impl.go
@@ -132,6 +132,11 @@ func (p GithubGraphql) SubTaskMetas() []plugin.SubTaskMeta 
{
                tasks.CollectDeploymentsMeta,
                tasks.ExtractDeploymentsMeta,
                githubTasks.ConvertDeploymentsMeta,
+
+               // releases
+               tasks.CollectReleaseMeta,
+               tasks.ExtractReleasesMeta,
+               githubTasks.ConvertReleasesMeta,
        }
 }
 
diff --git a/backend/plugins/github_graphql/tasks/release_collector.go 
b/backend/plugins/github_graphql/tasks/release_collector.go
new file mode 100644
index 000000000..e80c13887
--- /dev/null
+++ b/backend/plugins/github_graphql/tasks/release_collector.go
@@ -0,0 +1,130 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 tasks
+
+import (
+       "strings"
+       "time"
+
+       "github.com/apache/incubator-devlake/core/errors"
+       "github.com/apache/incubator-devlake/core/plugin"
+       helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+       githubTasks "github.com/apache/incubator-devlake/plugins/github/tasks"
+       "github.com/merico-dev/graphql"
+)
+
+const RAW_RELEASE_TABLE = "github_graphql_release"
+
+type GraphqlQueryReleaseWrapper struct {
+       RateLimit struct {
+               Cost int
+       }
+       Repository struct {
+               Releases struct {
+                       TotalCount graphql.Int                  
`graphql:"totalCount"`
+                       PageInfo   *helper.GraphqlQueryPageInfo 
`graphql:"pageInfo"`
+                       Releases   []*GraphqlQueryRelease       
`graphql:"nodes"`
+               } `graphql:"releases(first: $pageSize, after: $skipCursor, 
orderBy: {field: CREATED_AT, direction: DESC})"`
+       } `graphql:"repository(owner: $owner, name: $name)"`
+}
+
+type GraphqlQueryReleaseAuthor struct {
+       Name *string `graphql:"name"`
+       ID   string  `graphql:"id"`
+}
+
+type GraphqlQueryRelease struct {
+       Author          GraphqlQueryReleaseAuthor `graphql:"author"`
+       DatabaseID      int                       `graphql:"databaseId"`
+       Id              string                    `graphql:"id"`
+       CreatedAt       time.Time                 `graphql:"createdAt"`
+       Description     string                    `graphql:"description"`
+       DescriptionHTML string                    `graphql:"descriptionHTML"`
+       IsDraft         bool                      `graphql:"isDraft"`
+       IsLatest        bool                      `graphql:"isLatest"`
+       IsPrerelease    bool                      `graphql:"isPrerelease"`
+       Name            string                    `graphql:"name"`
+       PublishedAt     time.Time                 `graphql:"publishedAt"`
+       ResourcePath    string                    `graphql:"resourcePath"`
+       TagName         string                    `graphql:"tagName"`
+       UpdatedAt       time.Time                 `graphql:"updatedAt"`
+       URL             string                    `graphql:"url"`
+}
+
+var CollectReleaseMeta = plugin.SubTaskMeta{
+       Name:             "Collect Releases",
+       EntryPoint:       CollectRelease,
+       EnabledByDefault: true,
+       Description:      "Collect Release data from GithubGraphql api, does 
not support either timeFilter or diffSync.",
+       DomainTypes:      []string{plugin.DOMAIN_TYPE_CICD},
+}
+
+var _ plugin.SubTaskEntryPoint = CollectRelease
+
+func CollectRelease(taskCtx plugin.SubTaskContext) errors.Error {
+       data := taskCtx.GetData().(*githubTasks.GithubTaskData)
+       apiCollector, err := 
helper.NewStatefulApiCollector(helper.RawDataSubTaskArgs{
+               Ctx: taskCtx,
+               Params: githubTasks.GithubApiParams{
+                       ConnectionId: data.Options.ConnectionId,
+                       Name:         data.Options.Name,
+               },
+               Table: RAW_RELEASE_TABLE,
+       })
+       if err != nil {
+               return err
+       }
+
+       err = apiCollector.InitGraphQLCollector(helper.GraphqlCollectorArgs{
+               GraphqlClient: data.GraphqlClient,
+               PageSize:      100,
+               BuildQuery: func(reqData *helper.GraphqlRequestData) 
(interface{}, map[string]interface{}, error) {
+                       query := &GraphqlQueryReleaseWrapper{}
+                       variables := make(map[string]interface{})
+                       if reqData == nil {
+                               return query, variables, nil
+                       }
+                       ownerName := strings.Split(data.Options.Name, "/")
+                       variables = map[string]interface{}{
+                               "pageSize":   graphql.Int(reqData.Pager.Size),
+                               "skipCursor": 
(*graphql.String)(reqData.Pager.SkipCursor),
+                               "owner":      graphql.String(ownerName[0]),
+                               "name":       graphql.String(ownerName[1]),
+                       }
+                       return query, variables, nil
+               },
+               GetPageInfo: func(iQuery interface{}, args 
*helper.GraphqlCollectorArgs) (*helper.GraphqlQueryPageInfo, error) {
+                       query := iQuery.(*GraphqlQueryReleaseWrapper)
+                       return query.Repository.Releases.PageInfo, nil
+               },
+               ResponseParser: func(iQuery interface{}, variables 
map[string]interface{}) ([]interface{}, error) {
+                       query := iQuery.(*GraphqlQueryReleaseWrapper)
+                       deployments := query.Repository.Releases.Releases
+                       for _, rawL := range deployments {
+                               if apiCollector.GetSince() != nil && 
!apiCollector.GetSince().Before(rawL.UpdatedAt) {
+                                       return nil, helper.ErrFinishCollect
+                               }
+                       }
+                       return nil, nil
+               },
+       })
+       if err != nil {
+               return err
+       }
+       return apiCollector.Execute()
+}
diff --git a/backend/plugins/github_graphql/tasks/release_extractor.go 
b/backend/plugins/github_graphql/tasks/release_extractor.go
new file mode 100644
index 000000000..4d019dcc8
--- /dev/null
+++ b/backend/plugins/github_graphql/tasks/release_extractor.go
@@ -0,0 +1,105 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 tasks
+
+import (
+       "encoding/json"
+       "github.com/apache/incubator-devlake/core/errors"
+       "github.com/apache/incubator-devlake/core/models/common"
+       "github.com/apache/incubator-devlake/core/plugin"
+       "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+       githubModels "github.com/apache/incubator-devlake/plugins/github/models"
+       githubTasks "github.com/apache/incubator-devlake/plugins/github/tasks"
+)
+
+var _ plugin.SubTaskEntryPoint = ExtractReleases
+
+var ExtractReleasesMeta = plugin.SubTaskMeta{
+       Name:             "Extract Releases",
+       EntryPoint:       ExtractReleases,
+       EnabledByDefault: true,
+       Description:      "extract raw release data into tool layer table 
github_releases",
+       DomainTypes:      []string{plugin.DOMAIN_TYPE_CICD},
+}
+
+func ExtractReleases(taskCtx plugin.SubTaskContext) errors.Error {
+       data := taskCtx.GetData().(*githubTasks.GithubTaskData)
+       extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{
+               RawDataSubTaskArgs: api.RawDataSubTaskArgs{
+                       Ctx: taskCtx,
+                       Params: githubTasks.GithubApiParams{
+                               ConnectionId: data.Options.ConnectionId,
+                               Name:         data.Options.Name,
+                       },
+                       Table: RAW_RELEASE_TABLE,
+               },
+               Extract: func(row *api.RawData) ([]interface{}, errors.Error) {
+                       apiDeployment := &GraphqlQueryReleaseWrapper{}
+                       err := errors.Convert(json.Unmarshal(row.Data, 
apiDeployment))
+                       if err != nil {
+                               return nil, err
+                       }
+
+                       releases := apiDeployment.Repository.Releases.Releases
+                       var results []interface{}
+                       for _, release := range releases {
+                               githubRelease, err := 
convertGitHubRelease(release, data.Options.ConnectionId, data.Options.GithubId)
+                               if err != nil {
+                                       return nil, errors.Convert(err)
+                               }
+                               results = append(results, githubRelease)
+                       }
+
+                       return results, nil
+               },
+       })
+
+       if err != nil {
+               return err
+       }
+
+       return extractor.Execute()
+}
+
+func convertGitHubRelease(release *GraphqlQueryRelease, connectionId uint64, 
githubId int) (*githubModels.GithubRelease, errors.Error) {
+       ret := &githubModels.GithubRelease{
+               ConnectionId: connectionId,
+               GithubId:     githubId,
+               NoPKModel:    common.NewNoPKModel(),
+
+               Id:              release.Id,
+               AuthorID:        release.Author.ID,
+               CreatedAt:       release.CreatedAt,
+               DatabaseID:      release.DatabaseID,
+               Description:     release.Description,
+               DescriptionHTML: release.Description,
+               IsDraft:         release.IsDraft,
+               IsLatest:        release.IsLatest,
+               IsPrerelease:    release.IsPrerelease,
+               Name:            release.Name,
+               PublishedAt:     release.PublishedAt,
+               ResourcePath:    release.ResourcePath,
+               TagName:         release.TagName,
+               UpdatedAt:       release.UpdatedAt,
+               URL:             release.URL,
+       }
+       if release.Author.Name != nil {
+               ret.AuthorName = *release.Author.Name
+       }
+       return ret, nil
+}

Reply via email to