Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module github.com/zeropsio/zcli

go 1.26

require github.com/zeropsio/zerops-go v1.0.18
require github.com/zeropsio/zerops-go v1.0.23

require (
github.com/charmbracelet/bubbles v0.20.0
Expand All @@ -22,9 +22,9 @@ require (
github.com/spf13/viper v1.20.0
github.com/stretchr/testify v1.10.0
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8
golang.org/x/mod v0.26.0
golang.org/x/term v0.28.0
golang.org/x/text v0.28.0
golang.org/x/mod v0.35.0
golang.org/x/term v0.43.0
golang.org/x/text v0.37.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
gopkg.in/yaml.v3 v3.0.1
)
Expand All @@ -42,7 +42,7 @@ require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
Expand All @@ -61,8 +61,8 @@ require (
github.com/subosito/gotenv v1.6.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.32.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/sys v0.35.0 // indirect
golang.org/x/crypto v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.45.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)
30 changes: 16 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
Expand Down Expand Up @@ -113,29 +115,29 @@ github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSW
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/zeropsio/zerops-go v1.0.18 h1:UZMbyfg1ZEgLmDeBTTvyfH5v02juf6TMjAL0ZoTWGgA=
github.com/zeropsio/zerops-go v1.0.18/go.mod h1:SY4o+4jAIrsDTwWACooogf1OyY1jNK8NqWBe9KFcjAA=
github.com/zeropsio/zerops-go v1.0.23 h1:BtGSONtULSlcwjfF3t3ytq4t2BuFEFc6u+7Dy5/R5Qk=
github.com/zeropsio/zerops-go v1.0.23/go.mod h1:SY4o+4jAIrsDTwWACooogf1OyY1jNK8NqWBe9KFcjAA=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand All @@ -148,17 +150,17 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4=
golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
Expand Down
22 changes: 9 additions & 13 deletions src/cmd/projectList_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,17 @@ import (
"github.com/stretchr/testify/require"
)

// TestProjectListCommand checks that `zcli project list` walks GetUserInfo →
// org filtering (ACTIVE only) → PostProjectSearch and renders a table that
// TestProjectListCommand checks that `zcli project list` walks GetUserClientList →
// org filtering (ACTIVE only) → GetClientProject and renders a table that
// contains the project id, name, and org name.
func TestProjectListCommand(t *testing.T) {
f := newFixture(t)
f.SeedLogin("test-token")

// GetAllOrgs reads UserAuthorize.clientUserList. Only ACTIVE clients are
// queried for projects.
f.HandleJSON("/api/rest/public/user/info", 200, map[string]any{
"email": "tester@example.com",
"fullName": "Test User",
"clientUserList": []map[string]any{{
// GetAllOrgs lists the user's active client memberships.
f.HandleJSON("/api/rest/public/user/client-list", 200, map[string]any{
"total": 1,
"list": []map[string]any{{
"id": "00000000-0000-0000-0000-000000000001",
"clientId": "00000000-0000-0000-0000-0000000000aa",
"userId": "00000000-0000-0000-0000-000000000002",
Expand All @@ -32,11 +30,9 @@ func TestProjectListCommand(t *testing.T) {
}},
})

f.HandleJSON("/api/rest/public/project/search", 200, map[string]any{
"limit": 50,
"offset": 0,
"totalHits": 1,
"items": []map[string]any{{
f.HandleJSON("/api/rest/public/client/00000000-0000-0000-0000-0000000000aa/project", 200, map[string]any{
"total": 1,
"list": []map[string]any{{
"id": "00000000-0000-0000-0000-0000000000bb",
"clientId": "00000000-0000-0000-0000-0000000000aa",
"name": "demo-project",
Expand Down
9 changes: 4 additions & 5 deletions src/cmd/serviceCreate.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"github.com/zeropsio/zerops-go/apiError"
"github.com/zeropsio/zerops-go/errorCode"
"github.com/zeropsio/zerops-go/types"
"github.com/zeropsio/zerops-go/types/enum"
"github.com/zeropsio/zerops-go/types/stringId"
)

Expand All @@ -37,7 +36,7 @@ func serviceCreateCmd() *cmdBuilder.Cmd {
StringFlag("zerops-yaml-path", "", i18n.T(i18n.ZeropsYamlLocation)).
StringFlag("working-dir", "./", i18n.T(i18n.BuildWorkingDir)).
StringFlag("name", "", "Service name").
StringFlag("mode", enumDefaultForFlag(enum.ServiceStackModeEnumNonHa), "Service mode "+enumValuesForFlag(enum.ServiceStackModeEnumAllPublic())).
StringFlag("mode", enumDefaultForFlag(entity.ServiceModeNonHa), "Service mode "+enumValuesForFlag(entity.ServiceModeAll())).
StringFlag("out", "", "Output format of command, using golang's text/template engine. Entity fields: "+formatAllowedTemplateFields(entity.ServiceFields)).
StringFlag("env-file", "", "File with envs (will be set as secrets, runtime envs can be defined in zerops.yml). Max file size is "+units.ByteCountIEC(maxEnvFileSize)).
StringFlag("env-isolation", "service", "Env isolation rule [service, none] for more info see docs https://docs.zerops.io/features/env-variables#isolation-modes").
Expand All @@ -57,8 +56,8 @@ func serviceCreateCmd() *cmdBuilder.Cmd {

mode := cmdData.Params.GetString("mode")
mode = strings.ToUpper(mode)
if !enum.ServiceStackModeEnum(mode).Is(enum.ServiceStackModeEnumAllPublic()...) {
return errors.Errorf("Invalid --mode, expected one of %s, got %s", enum.ServiceStackModeEnumAllPublic(), mode)
if !entity.ServiceMode(mode).Is(entity.ServiceModeAll()...) {
return errors.Errorf("Invalid --mode, expected one of %s, got %s", entity.ServiceModeAll(), mode)
}

envFile, err := readServiceEnvFile(cmdData)
Expand Down Expand Up @@ -102,7 +101,7 @@ func serviceCreateCmd() *cmdBuilder.Cmd {
postService := entity.PostService{
ProjectId: project.Id,
Name: types.NewString(name),
Mode: enum.ServiceStackModeEnum(mode),
Mode: entity.ServiceMode(mode),
EnvFile: envFile,
StartWithoutCode: types.NewBool(startWithoutCode),
SshIsolation: types.NewStringNull(cmdData.Params.GetString("ssh-isolation")),
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/serviceLog.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func serviceLogCmd() *cmdBuilder.Cmd {
)

serviceId := service.Id
if cmdData.Params.GetBool("showBuildLogs") {
if cmdData.Params.GetBool("show-build-logs") {
appVersions, err := repository.GetLatestAppVersionByService(ctx, cmdData.RestApiClient, service)
if err != nil {
return err
Expand Down
3 changes: 1 addition & 2 deletions src/cmdBuilder/scopeService.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/zeropsio/zerops-go/apiError"
"github.com/zeropsio/zerops-go/errorCode"
"github.com/zeropsio/zerops-go/types"
"github.com/zeropsio/zerops-go/types/enum"
"github.com/zeropsio/zerops-go/types/uuid"
)

Expand Down Expand Up @@ -199,7 +198,7 @@ func createNewService(ctx context.Context, project entity.Project, cmdData *Logg
entity.PostService{
ProjectId: project.Id,
Name: types.NewString(name),
Mode: enum.ServiceStackModeEnumNonHa,
Mode: entity.ServiceModeNonHa,
// Location: location.Id.LocationIdNull(),
},
)
Expand Down
103 changes: 21 additions & 82 deletions src/entity/repository/appVersion.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,83 +5,22 @@ import (

"github.com/zeropsio/zcli/src/entity"
"github.com/zeropsio/zcli/src/zeropsRestApiClient"
"github.com/zeropsio/zerops-go/dto/input/body"
"github.com/zeropsio/zerops-go/dto/input/path"
"github.com/zeropsio/zerops-go/dto/input/query"
"github.com/zeropsio/zerops-go/dto/output"
"github.com/zeropsio/zerops-go/types"
)

func GetAllAppVersionByService(
ctx context.Context,
restApiClient *zeropsRestApiClient.Handler,
service entity.Service,
) ([]entity.AppVersion, error) {
esFilter := body.EsFilter{
Search: []body.EsSearchItem{
{
Name: "clientId",
Operator: "eq",
Value: service.OrgId.TypedString(),
}, {
Name: "serviceStackId",
Operator: "eq",
Value: service.Id.TypedString(),
}, {
Name: "build.serviceStackId",
Operator: "ne",
Value: "",
},
},
}

response, err := restApiClient.PostAppVersionSearch(ctx, esFilter)
if err != nil {
return nil, err
}

resOutput, err := response.Output()
if err != nil {
return nil, err
}

appVersions := make([]entity.AppVersion, 0, len(resOutput.Items))
for _, appVersion := range resOutput.Items {
appVersions = append(appVersions, appVersionFromEsSearch(appVersion))
}

return appVersions, nil
}

func GetLatestAppVersionByService(
ctx context.Context,
restApiClient *zeropsRestApiClient.Handler,
service entity.Service,
) ([]entity.AppVersion, error) {
esFilter := body.EsFilter{
Search: []body.EsSearchItem{
{
Name: "clientId",
Operator: "eq",
Value: service.OrgId.TypedString(),
}, {
Name: "serviceStackId",
Operator: "eq",
Value: service.Id.TypedString(),
}, {
Name: "build.serviceStackId",
Operator: "ne",
Value: "",
},
},
Sort: []body.EsSortItem{
{
Name: "sequence",
Ascending: types.NewBoolNull(false),
},
},
Limit: types.NewIntNull(1),
}

response, err := restApiClient.PostAppVersionSearch(ctx, esFilter)
response, err := restApiClient.GetServiceStackAppVersion(ctx, path.ServiceStackId{Id: service.Id}, query.ListServiceStackAppVersions{
Limit: types.NewIntNull(1),
HasBuild: types.NewBoolNull(true),
Sort: types.NewStringArrayNull(types.StringArray{"-sequence"}),
})
if err != nil {
return nil, err
}
Expand All @@ -90,25 +29,25 @@ func GetLatestAppVersionByService(
return nil, err
}

appVersions := make([]entity.AppVersion, 0, len(resOutput.Items))
for _, appVersion := range resOutput.Items {
appVersions = append(appVersions, appVersionFromEsSearch(appVersion))
appVersions := make([]entity.AppVersion, 0, len(resOutput.List))
for _, appVersion := range resOutput.List {
appVersions = append(appVersions, appVersionFromApiOutput(appVersion))
}

return appVersions, nil
}

func appVersionFromEsSearch(esAppVersion output.EsAppVersion) entity.AppVersion {
func appVersionFromApiOutput(appVersion output.GetAppVersion) entity.AppVersion {
return entity.AppVersion{
Id: esAppVersion.Id,
OrgId: esAppVersion.ClientId,
ProjectId: esAppVersion.ProjectId,
ServiceId: esAppVersion.ServiceStackId,
Source: esAppVersion.Source,
Sequence: esAppVersion.Sequence,
Status: esAppVersion.Status,
Created: esAppVersion.Created,
LastUpdate: esAppVersion.LastUpdate,
Build: esAppVersion.Build,
Id: appVersion.Id,
OrgId: appVersion.ClientId,
ProjectId: appVersion.ProjectId,
ServiceId: appVersion.ServiceStackId,
Source: appVersion.Source,
Sequence: appVersion.Sequence,
Status: appVersion.Status,
Created: appVersion.Created,
LastUpdate: appVersion.LastUpdate,
Build: appVersion.Build,
}
}
Loading