This is an automated email from the ASF dual-hosted git repository. warren pushed a commit to branch feat-plugin-zentao in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
commit c1172d0054115354e782618d1aa1fb6816453d2f Author: yuqiangabab <[email protected]> AuthorDate: Sun Sep 25 13:40:52 2022 +0800 feat(zentao): add zentao stories --- plugins/zentao/impl/impl.go | 13 +- plugins/zentao/models/archived/stories.go | 163 +++++++++++++++++++++ .../migrationscripts/20220906_add_init_tables.go | 3 +- plugins/zentao/models/stories.go | 163 +++++++++++++++++++++ plugins/zentao/tasks/stories_collector.go | 77 ++++++++++ plugins/zentao/tasks/stories_convertor.go | 110 ++++++++++++++ plugins/zentao/tasks/stories_extractor.go | 65 ++++++++ plugins/zentao/tasks/task_data.go | 2 + plugins/zentao/zentao.go | 2 + 9 files changed, 592 insertions(+), 6 deletions(-) diff --git a/plugins/zentao/impl/impl.go b/plugins/zentao/impl/impl.go index b4004753..9b6b8f0b 100644 --- a/plugins/zentao/impl/impl.go +++ b/plugins/zentao/impl/impl.go @@ -52,11 +52,14 @@ func (plugin Zentao) Init(config *viper.Viper, logger core.Logger, db *gorm.DB) func (plugin Zentao) SubTaskMetas() []core.SubTaskMeta { // TODO add your sub task here return []core.SubTaskMeta{ - tasks.CollectProjectMeta, - tasks.ExtractProjectsMeta, - tasks.CollectExecutionMeta, - tasks.ExtractExecutionsMeta, - tasks.ConvertExecutionsMeta, + //tasks.CollectProjectMeta, + //tasks.ExtractProjectsMeta, + //tasks.CollectExecutionMeta, + //tasks.ExtractExecutionsMeta, + //tasks.ConvertExecutionsMeta, + tasks.CollectStoriesMeta, + tasks.ExtractStoriesMeta, + tasks.ConvertStoriesMeta, } } diff --git a/plugins/zentao/models/archived/stories.go b/plugins/zentao/models/archived/stories.go new file mode 100644 index 00000000..cd608682 --- /dev/null +++ b/plugins/zentao/models/archived/stories.go @@ -0,0 +1,163 @@ +/* +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 archived + +import ( + "github.com/apache/incubator-devlake/models/migrationscripts/archived" + "github.com/apache/incubator-devlake/plugins/helper" +) + +type ZentaoStories struct { + archived.NoPKModel + ConnectionId uint64 `gorm:"primaryKey;type:BIGINT NOT NULL"` + ID int `json:"id"gorm:"primaryKey;type:BIGINT NOT NULL"` + Vision string `json:"vision"` + Parent int `json:"parent"` + Product int `json:"product"` + Branch int `json:"branch"` + Module int `json:"module"` + Plan string `json:"plan"` + Source string `json:"source"` + SourceNote string `json:"sourceNote"` + FromBug int `json:"fromBug"` + Feedback int `json:"feedback"` + Title string `json:"title"` + Keywords string `json:"keywords"` + Type string `json:"type"` + Category string `json:"category"` + Pri int `json:"pri"` + Estimate int `json:"estimate"` + Status string `json:"status"` + SubStatus string `json:"subStatus"` + Color string `json:"color"` + Stage string `json:"stage"` + StagedBy string `json:"stagedBy"` + //Mailto []interface{} `json:"mailto" gorm:"-:all"` + Lib int `json:"lib"` + FromStory int `json:"fromStory"` + FromVersion int `json:"fromVersion"` + OpenedBy `json:"openedBy"` + OpenedDate *helper.Iso8601Time `json:"openedDate"` + AssignedTo `json:"assignedTo"` + AssignedDate *helper.Iso8601Time `json:"assignedDate"` + ApprovedDate string `json:"approvedDate"` + LastEditedBy `json:"lastEditedBy"` + LastEditedDate *helper.Iso8601Time `json:"lastEditedDate"` + ChangedBy string `json:"changedBy"` + ChangedDate string `json:"changedDate"` + ReviewedBy interface{} `json:"reviewedBy" gorm:"-:all"` + ReviewedDate *helper.Iso8601Time `json:"reviewedDate"` + ClosedBy `json:"closedBy"` + ClosedDate *helper.Iso8601Time `json:"closedDate"` + ClosedReason string `json:"closedReason"` + ActivatedDate string `json:"activatedDate"` + ToBug int `json:"toBug"` + ChildStories string `json:"childStories"` + LinkStories string `json:"linkStories"` + LinkRequirements string `json:"linkRequirements"` + DuplicateStory int `json:"duplicateStory"` + Version int `json:"version"` + StoryChanged string `json:"storyChanged"` + FeedbackBy string `json:"feedbackBy"` + NotifyEmail string `json:"notifyEmail"` + URChanged string `json:"URChanged"` + Deleted bool `json:"deleted"` + Spec string `json:"spec"` + Verify string `json:"verify"` + Executions Executions `json:"executions" gorm:"-:all"` + Tasks []Tasks `json:"tasks" gorm:"-:all"` + //Stages []interface{} `json:"stages" gorm:"-:all"` + PlanTitle []string `json:"planTitle" gorm:"-:all"` + //Children []interface{} `json:"children" gorm:"-:all"` + //Files []interface{} `json:"files" gorm:"-:all"` + ProductName string `json:"productName"` + ProductStatus string `json:"productStatus"` + ModuleTitle string `json:"moduleTitle"` + Bugs []Bugs `json:"bugs" gorm:"-:all"` + Cases []Cases `json:"cases" gorm:"-:all"` + //Requirements []interface{} `json:"requirements" gorm:"-:all"` + Actions []Actions `json:"actions" gorm:"-:all"` + PreAndNext `json:"preAndNext"` +} +type Executions struct { + Num1 struct { + Project int `json:"project"` + Name string `json:"name"` + Status string `json:"status"` + Type string `json:"type"` + } `json:"1"` +} +type Tasks struct { + ID int `json:"id"` + Name string `json:"name"` + Type string `json:"type"` + Status string `json:"status"` + AssignedTo struct { + ID int `json:"id"` + Account string `json:"account"` + Avatar string `json:"avatar"` + Realname string `json:"realname"` + } `json:"assignedTo"` +} +type Bugs struct { + ID int `json:"id"` + Title string `json:"title"` + Status string `json:"status"` + Pri int `json:"pri"` + Severity int `json:"severity"` +} +type Cases struct { + ID int `json:"id"` + Title string `json:"title"` + Pri int `json:"pri"` + Status string `json:"status"` +} + +type Actions struct { + ID int `json:"id"` + ObjectType string `json:"objectType"` + ObjectID int `json:"objectID"` + Product string `json:"product"` + Project int `json:"project"` + Execution int `json:"execution"` + Actor string `json:"actor"` + Action string `json:"action"` + Date string `json:"date"` + Comment string `json:"comment"` + Extra string `json:"extra"` + Read string `json:"read"` + Vision string `json:"vision"` + Efforted int `json:"efforted"` + //History []interface{} `json:"history"` + Desc string `json:"desc"` +} +type AssignedTo struct { + ID int `json:"id"` + Account string `json:"account"` + Avatar string `json:"avatar"` + Realname string `json:"realname"` +} + +type PreAndNext struct { + Pre string `json:"pre"` + Next string `json:"next"` +} + +func (ZentaoStories) TableName() string { + return "_tool_zentao_stories" +} diff --git a/plugins/zentao/models/migrationscripts/20220906_add_init_tables.go b/plugins/zentao/models/migrationscripts/20220906_add_init_tables.go index 6635dda3..2213d937 100644 --- a/plugins/zentao/models/migrationscripts/20220906_add_init_tables.go +++ b/plugins/zentao/models/migrationscripts/20220906_add_init_tables.go @@ -29,7 +29,8 @@ func (u *addInitTables) Up(ctx context.Context, db *gorm.DB) error { return db.Migrator().AutoMigrate( //archived.ZentaoConnection{}, //archived.ZentaoProject{}, - archived.ZentaoExecution{}, + //archived.ZentaoExecution{}, + archived.ZentaoStories{}, ) } diff --git a/plugins/zentao/models/stories.go b/plugins/zentao/models/stories.go new file mode 100644 index 00000000..be198bbf --- /dev/null +++ b/plugins/zentao/models/stories.go @@ -0,0 +1,163 @@ +/* +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 ( + "github.com/apache/incubator-devlake/models/common" + "github.com/apache/incubator-devlake/plugins/helper" +) + +type ZentaoStories struct { + common.NoPKModel + ConnectionId uint64 `gorm:"primaryKey;type:BIGINT NOT NULL"` + ID int `json:"id"gorm:"primaryKey;type:BIGINT NOT NULL"` + Vision string `json:"vision"` + Parent int `json:"parent"` + Product int `json:"product"` + Branch int `json:"branch"` + Module int `json:"module"` + Plan string `json:"plan"` + Source string `json:"source"` + SourceNote string `json:"sourceNote"` + FromBug int `json:"fromBug"` + Feedback int `json:"feedback"` + Title string `json:"title"` + Keywords string `json:"keywords"` + Type string `json:"type"` + Category string `json:"category"` + Pri int `json:"pri"` + Estimate int `json:"estimate"` + Status string `json:"status"` + SubStatus string `json:"subStatus"` + Color string `json:"color"` + Stage string `json:"stage"` + StagedBy string `json:"stagedBy"` + //Mailto []interface{} `json:"mailto" gorm:"-:all"` + Lib int `json:"lib"` + FromStory int `json:"fromStory"` + FromVersion int `json:"fromVersion"` + OpenedBy `json:"openedBy"` + OpenedDate *helper.Iso8601Time `json:"openedDate"` + AssignedTo `json:"assignedTo"` + AssignedDate *helper.Iso8601Time `json:"assignedDate"` + ApprovedDate string `json:"approvedDate"` + LastEditedBy `json:"lastEditedBy"` + LastEditedDate *helper.Iso8601Time `json:"lastEditedDate"` + ChangedBy string `json:"changedBy"` + ChangedDate string `json:"changedDate"` + ReviewedBy interface{} `json:"reviewedBy" gorm:"-:all"` + ReviewedDate *helper.Iso8601Time `json:"reviewedDate"` + ClosedBy `json:"closedBy"` + ClosedDate *helper.Iso8601Time `json:"closedDate"` + ClosedReason string `json:"closedReason"` + ActivatedDate string `json:"activatedDate"` + ToBug int `json:"toBug"` + ChildStories string `json:"childStories"` + LinkStories string `json:"linkStories"` + LinkRequirements string `json:"linkRequirements"` + DuplicateStory int `json:"duplicateStory"` + Version int `json:"version"` + StoryChanged string `json:"storyChanged"` + FeedbackBy string `json:"feedbackBy"` + NotifyEmail string `json:"notifyEmail"` + URChanged string `json:"URChanged"` + Deleted bool `json:"deleted"` + Spec string `json:"spec"` + Verify string `json:"verify"` + Executions Executions `json:"executions" gorm:"-:all"` + Tasks []Tasks `json:"tasks" gorm:"-:all"` + //Stages []interface{} `json:"stages" gorm:"-:all"` + PlanTitle []string `json:"planTitle" gorm:"-:all"` + //Children []interface{} `json:"children" gorm:"-:all"` + //Files []interface{} `json:"files" gorm:"-:all"` + ProductName string `json:"productName"` + ProductStatus string `json:"productStatus"` + ModuleTitle string `json:"moduleTitle"` + Bugs []Bugs `json:"bugs" gorm:"-:all"` + Cases []Cases `json:"cases" gorm:"-:all"` + //Requirements []interface{} `json:"requirements" gorm:"-:all"` + Actions []Actions `json:"actions" gorm:"-:all"` + PreAndNext `json:"preAndNext"` +} +type Executions struct { + Num1 struct { + Project int `json:"project"` + Name string `json:"name"` + Status string `json:"status"` + Type string `json:"type"` + } `json:"1"` +} +type Tasks struct { + ID int `json:"id"` + Name string `json:"name"` + Type string `json:"type"` + Status string `json:"status"` + AssignedTo struct { + ID int `json:"id"` + Account string `json:"account"` + Avatar string `json:"avatar"` + Realname string `json:"realname"` + } `json:"assignedTo"` +} +type Bugs struct { + ID int `json:"id"` + Title string `json:"title"` + Status string `json:"status"` + Pri int `json:"pri"` + Severity int `json:"severity"` +} +type Cases struct { + ID int `json:"id"` + Title string `json:"title"` + Pri int `json:"pri"` + Status string `json:"status"` +} + +type Actions struct { + ID int `json:"id"` + ObjectType string `json:"objectType"` + ObjectID int `json:"objectID"` + Product string `json:"product"` + Project int `json:"project"` + Execution int `json:"execution"` + Actor string `json:"actor"` + Action string `json:"action"` + Date string `json:"date"` + Comment string `json:"comment"` + Extra string `json:"extra"` + Read string `json:"read"` + Vision string `json:"vision"` + Efforted int `json:"efforted"` + //History []interface{} `json:"history"` + Desc string `json:"desc"` +} +type AssignedTo struct { + ID int `json:"id"` + Account string `json:"account"` + Avatar string `json:"avatar"` + Realname string `json:"realname"` +} + +type PreAndNext struct { + Pre string `json:"pre"` + Next string `json:"next"` +} + +func (ZentaoStories) TableName() string { + return "_tool_zentao_stories" +} diff --git a/plugins/zentao/tasks/stories_collector.go b/plugins/zentao/tasks/stories_collector.go new file mode 100644 index 00000000..6ba58924 --- /dev/null +++ b/plugins/zentao/tasks/stories_collector.go @@ -0,0 +1,77 @@ +/* +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" + "fmt" + "github.com/apache/incubator-devlake/plugins/core" + "github.com/apache/incubator-devlake/plugins/helper" + "io" + "net/http" + "net/url" +) + +const RAW_STORIES_TABLE = "zentao_stories" + +var _ core.SubTaskEntryPoint = CollectExecution + +func CollectStories(taskCtx core.SubTaskContext) error { + data := taskCtx.GetData().(*ZentaoTaskData) + collector, err := helper.NewApiCollector(helper.ApiCollectorArgs{ + RawDataSubTaskArgs: helper.RawDataSubTaskArgs{ + Ctx: taskCtx, + Params: ZentaoApiParams{ + StoriesId: data.Options.StoriesId, + }, + Table: RAW_STORIES_TABLE, + }, + ApiClient: data.ApiClient, + Incremental: false, + PageSize: 100, + // TODO write which api would you want request + UrlTemplate: "/stories/{{ .Params.StoriesId }}", + Query: func(reqData *helper.RequestData) (url.Values, error) { + query := url.Values{} + query.Set("page", fmt.Sprintf("%v", reqData.Pager.Page)) + query.Set("limit", fmt.Sprintf("%v", reqData.Pager.Size)) + return query, nil + }, + GetTotalPages: GetTotalPagesFromResponse, + ResponseParser: func(res *http.Response) ([]json.RawMessage, error) { + body, err := io.ReadAll(res.Body) + res.Body.Close() + if err != nil { + return nil, err + } + return []json.RawMessage{body}, nil + }, + }) + if err != nil { + return err + } + + return collector.Execute() +} + +var CollectStoriesMeta = core.SubTaskMeta{ + Name: "CollectStories", + EntryPoint: CollectStories, + EnabledByDefault: true, + Description: "Collect Stories data from Zentao api", +} diff --git a/plugins/zentao/tasks/stories_convertor.go b/plugins/zentao/tasks/stories_convertor.go new file mode 100644 index 00000000..a41a1868 --- /dev/null +++ b/plugins/zentao/tasks/stories_convertor.go @@ -0,0 +1,110 @@ +/* +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 ( + "github.com/apache/incubator-devlake/models/domainlayer" + "github.com/apache/incubator-devlake/models/domainlayer/didgen" + "github.com/apache/incubator-devlake/models/domainlayer/ticket" + "github.com/apache/incubator-devlake/plugins/core" + "github.com/apache/incubator-devlake/plugins/core/dal" + "github.com/apache/incubator-devlake/plugins/helper" + "github.com/apache/incubator-devlake/plugins/zentao/models" + "reflect" +) + +var _ core.SubTaskEntryPoint = ConvertExecutions + +var ConvertStoriesMeta = core.SubTaskMeta{ + Name: "convertStories", + EntryPoint: ConvertStories, + EnabledByDefault: true, + Description: "convert Zentao stories", + DomainTypes: []string{core.DOMAIN_TYPE_TICKET}, +} + +func ConvertStories(taskCtx core.SubTaskContext) error { + data := taskCtx.GetData().(*ZentaoTaskData) + db := taskCtx.GetDal() + boardIdGen := didgen.NewDomainIdGenerator(&models.ZentaoStories{}) + cursor, err := db.Cursor( + dal.From(&models.ZentaoStories{}), + dal.Where(`_tool_zentao_stories.id = ? and + _tool_zentao_stories.connection_id = ?`, data.Options.StoriesId, data.Options.ConnectionId), + ) + if err != nil { + return err + } + defer cursor.Close() + convertor, err := helper.NewDataConverter(helper.DataConverterArgs{ + InputRowType: reflect.TypeOf(models.ZentaoStories{}), + Input: cursor, + RawDataSubTaskArgs: helper.RawDataSubTaskArgs{ + Ctx: taskCtx, + Params: ZentaoApiParams{ + StoriesId: data.Options.StoriesId, + }, + Table: RAW_STORIES_TABLE, + }, + Convert: func(inputRow interface{}) ([]interface{}, error) { + toolStories := inputRow.(*models.ZentaoStories) + + domainBoard := &ticket.Issue{ + DomainEntity: domainlayer.DomainEntity{ + Id: boardIdGen.Generate(toolStories.ConnectionId, toolStories.ID), + }, + Url: "", + IconURL: "", + IssueKey: "", + Title: toolStories.Title, + Description: toolStories.Spec, + EpicKey: "", + Type: toolStories.Type, + Status: toolStories.Status, + OriginalStatus: "", + StoryPoint: 0, + ResolutionDate: nil, + CreatedDate: toolStories.OpenedDate.ToNullableTime(), + UpdatedDate: toolStories.LastEditedDate.ToNullableTime(), + LeadTimeMinutes: 0, + ParentIssueId: "", + Priority: "", + OriginalEstimateMinutes: 0, + TimeSpentMinutes: 0, + TimeRemainingMinutes: 0, + CreatorId: "", + CreatorName: toolStories.OpenedBy.OpenedByRealname, + AssigneeId: "", + AssigneeName: toolStories.AssignedTo.Realname, + Severity: "", + Component: "", + DeploymentId: "", + } + + results := make([]interface{}, 0) + results = append(results, domainBoard) + return results, nil + }, + }) + + if err != nil { + return err + } + + return convertor.Execute() +} diff --git a/plugins/zentao/tasks/stories_extractor.go b/plugins/zentao/tasks/stories_extractor.go new file mode 100644 index 00000000..aaadfb84 --- /dev/null +++ b/plugins/zentao/tasks/stories_extractor.go @@ -0,0 +1,65 @@ +/* +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/plugins/core" + "github.com/apache/incubator-devlake/plugins/helper" + "github.com/apache/incubator-devlake/plugins/zentao/models" +) + +var _ core.SubTaskEntryPoint = ExtractStories + +var ExtractStoriesMeta = core.SubTaskMeta{ + Name: "extractStories", + EntryPoint: ExtractStories, + EnabledByDefault: true, + Description: "extract Zentao stories", + DomainTypes: []string{core.DOMAIN_TYPE_TICKET}, +} + +func ExtractStories(taskCtx core.SubTaskContext) error { + data := taskCtx.GetData().(*ZentaoTaskData) + extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{ + RawDataSubTaskArgs: helper.RawDataSubTaskArgs{ + Ctx: taskCtx, + Params: ZentaoApiParams{ + StoriesId: data.Options.StoriesId, + }, + Table: RAW_STORIES_TABLE, + }, + Extract: func(row *helper.RawData) ([]interface{}, error) { + stories := &models.ZentaoStories{} + err := json.Unmarshal(row.Data, stories) + if err != nil { + return nil, err + } + stories.ConnectionId = data.Options.ConnectionId + results := make([]interface{}, 0) + results = append(results, stories) + return results, nil + }, + }) + + if err != nil { + return err + } + + return extractor.Execute() +} diff --git a/plugins/zentao/tasks/task_data.go b/plugins/zentao/tasks/task_data.go index a2d88f22..ae51908f 100644 --- a/plugins/zentao/tasks/task_data.go +++ b/plugins/zentao/tasks/task_data.go @@ -27,6 +27,7 @@ type ZentaoApiParams struct { ProductId uint64 ExecutionId uint64 ProjectId uint64 + StoriesId uint64 } type ZentaoOptions struct { @@ -40,6 +41,7 @@ type ZentaoOptions struct { ProjectId uint64 Tasks []string `json:"tasks,omitempty"` Since string + StoriesId uint64 } type ZentaoTaskData struct { diff --git a/plugins/zentao/zentao.go b/plugins/zentao/zentao.go index 32845c90..3768b5d9 100644 --- a/plugins/zentao/zentao.go +++ b/plugins/zentao/zentao.go @@ -34,6 +34,7 @@ func main() { executionId := cmd.Flags().IntP("executionId", "e", 8, "execution id") productId := cmd.Flags().IntP("productId", "o", 8, "product id") projectId := cmd.Flags().IntP("projectId", "p", 8, "project id") + storiesId := cmd.Flags().IntP("storiesId", "s", 1, "stories id") cmd.Run = func(cmd *cobra.Command, args []string) { runner.DirectRun(cmd, args, PluginEntry, map[string]interface{}{ @@ -41,6 +42,7 @@ func main() { "executionId": *executionId, "productId": *productId, "projectId": *projectId, + "storiesId": *storiesId, }) } runner.RunCmd(cmd)
