-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8bfc72b
commit a756f2d
Showing
86 changed files
with
7,417 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
name: CD | ||
|
||
on: | ||
release: | ||
types: | ||
- released | ||
- prereleased | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
upload-cli-artifact-to-oss: | ||
strategy: | ||
matrix: | ||
include: | ||
- arch: amd64 | ||
os: linux | ||
- arch: amd64 | ||
os: darwin | ||
- arch: arm64 | ||
os: linux | ||
- arch: arm64 | ||
os: darwin | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: write | ||
steps: | ||
- name: Check if version is semantic | ||
run: echo "${{ github.ref_name }}" | grep -q -E '^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-((0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(\+([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*))?$' | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
- name: Set up go | ||
uses: actions/setup-go@v4 | ||
- name: Build cocli | ||
run: | | ||
make build-binary | ||
mv bin/cocli bin/cocli-${{ matrix.os }}-${{ matrix.arch }} | ||
- name: Upload release artifact | ||
uses: softprops/action-gh-release@v2 | ||
with: | ||
files: bin/cocli-${{ matrix.os }}-${{ matrix.arch }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
name: CI | ||
on: [push] | ||
jobs: | ||
build: | ||
runs-on: ubuntu-22.04 | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
- name: Set up go | ||
uses: actions/setup-go@v3 | ||
with: | ||
go-version: 1.22 | ||
- name: Cache | ||
if: success() | ||
uses: actions/cache@v3 | ||
with: | ||
path: | | ||
~/.cache/cocli/${{ runner.os }}/${{ runner.arch }}/go/pkg/mod | ||
key: ${{ runner.os }}-golang-${{ hashFiles('**/go.sum', 'make/**') }} | ||
restore-keys: | | ||
${{ runner.os }}-golang- | ||
- name: Lint | ||
run: make lint | ||
- name: Build | ||
run: make build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Autogenerated by makego. DO NOT EDIT. | ||
/.DS_Store | ||
/.env/ | ||
/.idea/ | ||
/.tmp/ | ||
/.vscode/ | ||
/bin/ | ||
/cmd/cocli/cocli |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
MAKEGO := make/go | ||
PROJECT := cocli | ||
GO_MODULE := github.com/coscene-io/cocli | ||
|
||
include make/cocli/all.mk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# coScene CLI (coCLI) | ||
|
||
`cocli` 是基于 [cobra](https://github.com/spf13/cobra) 开发的 coScene 命令行工具,用于与 coScene 平台进行交互,便于用户在终端中对 coScene 平台的资源进行管理。 | ||
|
||
具体的使用方法请参考 [coScene CLI 文档](https://docs.coscene.cn/docs/category/cli)。 | ||
|
||
另外,`cocli` 所有的命令都可以通过添加 `-h` 参数查看帮助文档。 | ||
|
||
## 本地安装 | ||
|
||
### 克隆代码 | ||
|
||
```shell | ||
git clone https://github.com/coscene-io/cocli.git | ||
``` | ||
### 本地构建可执行文件 | ||
|
||
```shell | ||
# 进入项目目录 | ||
cd cocli | ||
|
||
# 构建可执行文件, 生成的可执行文件在 `./bin` 目录下 | ||
make build-binary | ||
|
||
# 将可执行文件移动到任意系统路径 PATH 下以便全局使用,当前示例移动到 `/usr/local/bin/` 目录下 | ||
mv bin/cocli /usr/local/bin/ | ||
|
||
# 运行 cocli 命令, 查看帮助文档, 确认安装成功 | ||
cocli -h | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
// Copyright 2024 coScene | ||
// | ||
// Licensed 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 api | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"strings" | ||
|
||
openv1alpha1connect "buf.build/gen/go/coscene-io/coscene-openapi/connectrpc/go/coscene/openapi/dataplatform/v1alpha1/services/servicesconnect" | ||
openv1alpha1resource "buf.build/gen/go/coscene-io/coscene-openapi/protocolbuffers/go/coscene/openapi/dataplatform/v1alpha1/resources" | ||
openv1alpha1service "buf.build/gen/go/coscene-io/coscene-openapi/protocolbuffers/go/coscene/openapi/dataplatform/v1alpha1/services" | ||
"connectrpc.com/connect" | ||
"github.com/coscene-io/cocli/internal/constants" | ||
"github.com/coscene-io/cocli/internal/name" | ||
"github.com/samber/lo" | ||
) | ||
|
||
type ActionInterface interface { | ||
// GetByName gets an action by name. | ||
GetByName(ctx context.Context, actionName *name.Action) (*openv1alpha1resource.Action, error) | ||
|
||
// ListAllActions lists all actions in the current organization. | ||
ListAllActions(ctx context.Context, listOpts *ListActionsOptions) ([]*openv1alpha1resource.Action, error) | ||
|
||
// CreateActionRun creates an action run. | ||
CreateActionRun(ctx context.Context, action *openv1alpha1resource.Action, record *name.Record) error | ||
|
||
// ListAllActionRuns lists all action runs in the current organization. | ||
ListAllActionRuns(ctx context.Context, listOpts *ListActionRunsOptions) ([]*openv1alpha1resource.ActionRun, error) | ||
|
||
// ActionId2Name converts an action id or name to an action name. | ||
ActionId2Name(ctx context.Context, actionIdOrName string, projectNameStr *name.Project) (*name.Action, error) | ||
} | ||
|
||
type actionClient struct { | ||
actionServiceClient openv1alpha1connect.ActionServiceClient | ||
actionRunServiceClient openv1alpha1connect.ActionRunServiceClient | ||
} | ||
|
||
func NewActionClient( | ||
actionServiceClient openv1alpha1connect.ActionServiceClient, | ||
actionRunServiceClient openv1alpha1connect.ActionRunServiceClient, | ||
) ActionInterface { | ||
return &actionClient{ | ||
actionServiceClient: actionServiceClient, | ||
actionRunServiceClient: actionRunServiceClient, | ||
} | ||
} | ||
|
||
type ListActionsOptions struct { | ||
Parent string | ||
} | ||
|
||
type ListActionRunsOptions struct { | ||
Parent string | ||
RecordNames []*name.Record | ||
} | ||
|
||
func (c *actionClient) GetByName(ctx context.Context, actionName *name.Action) (*openv1alpha1resource.Action, error) { | ||
req := connect.NewRequest(&openv1alpha1service.GetActionRequest{ | ||
Name: actionName.String(), | ||
}) | ||
res, err := c.actionServiceClient.GetAction(ctx, req) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get action: %w", err) | ||
} | ||
|
||
return res.Msg, nil | ||
} | ||
|
||
func (c *actionClient) ListAllActions(ctx context.Context, listOpts *ListActionsOptions) ([]*openv1alpha1resource.Action, error) { | ||
filter := c.filter(listOpts) | ||
|
||
var ( | ||
skip = 0 | ||
ret []*openv1alpha1resource.Action | ||
) | ||
|
||
for { | ||
req := connect.NewRequest(&openv1alpha1service.ListActionsRequest{ | ||
Parent: listOpts.Parent, | ||
Filter: filter, | ||
Skip: int32(skip), | ||
PageSize: int32(constants.MaxPageSize), | ||
}) | ||
res, err := c.actionServiceClient.ListActions(ctx, req) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to list actions: %w", err) | ||
} | ||
|
||
ret = append(ret, res.Msg.Actions...) | ||
if len(res.Msg.Actions) < constants.MaxPageSize { | ||
break | ||
} | ||
skip += constants.MaxPageSize | ||
} | ||
|
||
return ret, nil | ||
} | ||
|
||
func (c *actionClient) filter(opt *ListActionsOptions) string { | ||
return "" | ||
} | ||
|
||
func (c *actionClient) CreateActionRun(ctx context.Context, action *openv1alpha1resource.Action, record *name.Record) error { | ||
req := connect.NewRequest(&openv1alpha1service.CreateActionRunRequest{ | ||
Parent: record.Project().String(), | ||
ActionRun: &openv1alpha1resource.ActionRun{ | ||
Action: action, | ||
Records: []*openv1alpha1resource.Record{ | ||
{ | ||
Name: record.String(), | ||
}, | ||
}, | ||
}, | ||
}) | ||
_, err := c.actionRunServiceClient.CreateActionRun(ctx, req) | ||
if err != nil { | ||
return fmt.Errorf("failed to create action run: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (c *actionClient) ListAllActionRuns(ctx context.Context, listOpts *ListActionRunsOptions) ([]*openv1alpha1resource.ActionRun, error) { | ||
filter := c.filterRun(listOpts) | ||
|
||
var ( | ||
skip = 0 | ||
ret []*openv1alpha1resource.ActionRun | ||
) | ||
|
||
for { | ||
req := connect.NewRequest(&openv1alpha1service.ListActionRunsRequest{ | ||
Parent: listOpts.Parent, | ||
Filter: filter, | ||
Skip: int32(skip), | ||
PageSize: int32(constants.MaxPageSize), | ||
}) | ||
res, err := c.actionRunServiceClient.ListActionRuns(ctx, req) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to list action runs: %w", err) | ||
} | ||
|
||
ret = append(ret, res.Msg.ActionRuns...) | ||
if len(res.Msg.ActionRuns) < constants.MaxPageSize { | ||
break | ||
} | ||
skip += constants.MaxPageSize | ||
} | ||
|
||
return ret, nil | ||
} | ||
|
||
func (c *actionClient) filterRun(opts *ListActionRunsOptions) string { | ||
var filters []string | ||
if opts.RecordNames != nil { | ||
filters = append( | ||
filters, | ||
fmt.Sprintf( | ||
"match.records==[%s]", | ||
strings.Join(lo.Map(opts.RecordNames, func(r *name.Record, _ int) string { return "\"" + r.String() + "\"" }), ","), | ||
), | ||
) | ||
} | ||
return strings.Join(filters, " && ") | ||
} | ||
|
||
func (c *actionClient) ActionId2Name(ctx context.Context, actionIdOrName string, projectName *name.Project) (*name.Action, error) { | ||
actionName, err := name.NewAction(actionIdOrName) | ||
if err == nil { | ||
return actionName, nil | ||
} | ||
|
||
if !name.IsUUID(actionIdOrName) { | ||
return nil, fmt.Errorf("invalid action id or name: %s", actionIdOrName) | ||
} | ||
|
||
// Try fetching assuming it's a project action | ||
if act, err := c.GetByName(ctx, &name.Action{ | ||
ProjectID: projectName.ProjectID, | ||
ID: actionIdOrName, | ||
}); err == nil { | ||
return name.NewAction(act.Name) | ||
} | ||
|
||
if act, err := c.GetByName(ctx, &name.Action{ | ||
ID: actionIdOrName, | ||
}); err == nil { | ||
return name.NewAction(act.Name) | ||
} | ||
|
||
return nil, fmt.Errorf("failed to convert action id to name: %s", actionIdOrName) | ||
} |
Oops, something went wrong.