mirror of
https://github.com/ko-build/ko.git
synced 2025-11-06 09:19:12 +02:00
Move ko binary to root of project. (#257)
* Move ko binary to root of project. * go.mod says required golang version is 1.14 * go install uses the folder name * lint and copyright bump * moving the test file changed the test hash. * more refs of cmd/test * add deprecation message
This commit is contained in:
4
.github/workflows/kind-e2e.yaml
vendored
4
.github/workflows/kind-e2e.yaml
vendored
@@ -131,12 +131,12 @@ jobs:
|
|||||||
- name: Run Smoke Test
|
- name: Run Smoke Test
|
||||||
run: |
|
run: |
|
||||||
# Test with kind load
|
# Test with kind load
|
||||||
KO_DOCKER_REPO=kind.local ko apply --platform=all -f ./cmd/ko/test
|
KO_DOCKER_REPO=kind.local ko apply --platform=all -f ./test
|
||||||
kubectl wait --timeout=10s --for=condition=Ready pod/kodata
|
kubectl wait --timeout=10s --for=condition=Ready pod/kodata
|
||||||
kubectl delete pod kodata
|
kubectl delete pod kodata
|
||||||
|
|
||||||
# Test with registry
|
# Test with registry
|
||||||
ko apply --platform=all -f ./cmd/ko/test
|
ko apply --platform=all -f ./test
|
||||||
kubectl wait --timeout=60s --for=condition=Ready pod/kodata
|
kubectl wait --timeout=60s --for=condition=Ready pod/kodata
|
||||||
kubectl delete pod kodata
|
kubectl delete pod kodata
|
||||||
|
|
||||||
|
|||||||
22
README.md
22
README.md
@@ -13,10 +13,10 @@
|
|||||||
|
|
||||||
`ko` can be installed and upgraded by running:
|
`ko` can be installed and upgraded by running:
|
||||||
|
|
||||||
**Note**: Golang version `1.12.0` or higher is required.
|
**Note**: Golang version `1.14.0` or higher is required.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
GO111MODULE=on go get github.com/google/ko/cmd/ko
|
go get github.com/google/ko
|
||||||
```
|
```
|
||||||
|
|
||||||
## Authenticating
|
## Authenticating
|
||||||
@@ -49,7 +49,7 @@ like `github.com/google/ko/cmd`.
|
|||||||
|
|
||||||
**One of the goals of `ko` is to make containers invisible infrastructure.**
|
**One of the goals of `ko` is to make containers invisible infrastructure.**
|
||||||
Simply replace image references in your Kubernetes yaml with the import path for
|
Simply replace image references in your Kubernetes yaml with the import path for
|
||||||
your Go binary prefixed with `ko://` (e.g. `ko://github.com/google/ko/cmd/ko`),
|
your Go binary prefixed with `ko://` (e.g. `ko://github.com/google/ko/test`),
|
||||||
and `ko` will handle containerizing and publishing that container image as
|
and `ko` will handle containerizing and publishing that container image as
|
||||||
needed.
|
needed.
|
||||||
|
|
||||||
@@ -409,27 +409,27 @@ for referencing them should be through the `KO_DATA_PATH` environment variable.
|
|||||||
The intent of this is to enable users to test things outside of `ko` as follows:
|
The intent of this is to enable users to test things outside of `ko` as follows:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
KO_DATA_PATH=$PWD/cmd/ko/test/kodata go run ./cmd/ko/test/*.go
|
KO_DATA_PATH=$PWD/test/kodata go run ./test/*.go
|
||||||
2018/07/19 23:35:20 Hello there
|
2018/07/19 23:35:20 Hello there
|
||||||
```
|
```
|
||||||
|
|
||||||
This produces identical output to being run within the container locally:
|
This produces identical output to being run within the container locally:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
ko publish -L ./cmd/test
|
ko publish -L ./test
|
||||||
2018/07/19 23:36:11 Using base gcr.io/distroless/static:nonroot for github.com/google/ko/cmd/test
|
2018/07/19 23:36:11 Using base gcr.io/distroless/static:nonroot for github.com/google/ko/test
|
||||||
2018/07/19 23:36:12 Loading ko.local/github.com/google/ko/cmd/test:703c205bf2f405af520b40536b87aafadcf181562b8faa6690fd2992084c8577
|
2018/07/19 23:36:12 Loading ko.local/github.com/google/ko/test:703c205bf2f405af520b40536b87aafadcf181562b8faa6690fd2992084c8577
|
||||||
2018/07/19 23:36:13 Loaded ko.local/github.com/google/ko/cmd/test:703c205bf2f405af520b40536b87aafadcf181562b8faa6690fd2992084c8577
|
2018/07/19 23:36:13 Loaded ko.local/github.com/google/ko/test:703c205bf2f405af520b40536b87aafadcf181562b8faa6690fd2992084c8577
|
||||||
|
|
||||||
docker run -ti --rm ko.local/github.com/google/ko/cmd/test:703c205bf2f405af520b40536b87aafadcf181562b8faa6690fd2992084c8577
|
docker run -ti --rm ko.local/github.com/google/ko/test:703c205bf2f405af520b40536b87aafadcf181562b8faa6690fd2992084c8577
|
||||||
2018/07/19 23:36:25 Hello there
|
2018/07/19 23:36:25 Hello there
|
||||||
```
|
```
|
||||||
|
|
||||||
... or on cluster:
|
... or on cluster:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
ko apply -f cmd/ko/test/test.yaml
|
ko apply -f test/test.yaml
|
||||||
2018/07/19 23:38:24 Using base gcr.io/distroless/static:nonroot for github.com/google/ko/cmd/test
|
2018/07/19 23:38:24 Using base gcr.io/distroless/static:nonroot for github.com/google/ko/test
|
||||||
2018/07/19 23:38:25 Publishing us.gcr.io/my-project/test-294a7bdc57d85dc6ddeef5ba38a59fe9:latest
|
2018/07/19 23:38:25 Publishing us.gcr.io/my-project/test-294a7bdc57d85dc6ddeef5ba38a59fe9:latest
|
||||||
2018/07/19 23:38:26 mounted blob: sha256:988abcba36b5948da8baa1e3616b94c0b56da814b8f6ff3ae3ac316e375e093a
|
2018/07/19 23:38:26 mounted blob: sha256:988abcba36b5948da8baa1e3616b94c0b56da814b8f6ff3ae3ac316e375e093a
|
||||||
2018/07/19 23:38:26 mounted blob: sha256:57752e7f9593cbfb7101af994b136a369ecc8174332866622db32a264f3fbefd
|
2018/07/19 23:38:26 mounted blob: sha256:57752e7f9593cbfb7101af994b136a369ecc8174332866622db32a264f3fbefd
|
||||||
|
|||||||
@@ -14,6 +14,10 @@
|
|||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
// HEY! YOU! This file has moved to the root of the project.
|
||||||
|
// !! PLEASE DO NOT ADD NEW FEATURES HERE !!
|
||||||
|
// Only sync with the root/main.go.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@@ -25,6 +29,15 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const Deprecation258 = `NOTICE!
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Please install ko from github.com/google/ko.
|
||||||
|
|
||||||
|
For more information see:
|
||||||
|
https://github.com/google/ko/issues/258
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
`
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
logs.Warn.SetOutput(os.Stderr)
|
logs.Warn.SetOutput(os.Stderr)
|
||||||
logs.Progress.SetOutput(os.Stderr)
|
logs.Progress.SetOutput(os.Stderr)
|
||||||
@@ -49,6 +62,8 @@ func main() {
|
|||||||
// Just add a `ko login` command:
|
// Just add a `ko login` command:
|
||||||
cmds.AddCommand(cranecmd.NewCmdAuthLogin())
|
cmds.AddCommand(cranecmd.NewCmdAuthLogin())
|
||||||
|
|
||||||
|
log.Print(Deprecation258)
|
||||||
|
|
||||||
if err := cmds.Execute(); err != nil {
|
if err := cmds.Execute(); err != nil {
|
||||||
log.Fatalf("error during command execution: %v", err)
|
log.Fatalf("error during command execution: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
../../../../.git/HEAD
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../../../.git/refs
|
|
||||||
@@ -29,3 +29,4 @@ go mod vendor
|
|||||||
# Delete all vendored broken symlinks.
|
# Delete all vendored broken symlinks.
|
||||||
# From https://stackoverflow.com/questions/22097130/delete-all-broken-symbolic-links-with-a-line
|
# From https://stackoverflow.com/questions/22097130/delete-all-broken-symbolic-links-with-a-line
|
||||||
find vendor/ -type l -exec sh -c 'for x; do [ -e "$x" ] || rm "$x"; done' _ {} +
|
find vendor/ -type l -exec sh -c 'for x; do [ -e "$x" ] || rm "$x"; done' _ {} +
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ sed -i 's/Hello World/TEST/g' ./vendor/github.com/go-training/helloworld/main.go
|
|||||||
|
|
||||||
echo "Building ko"
|
echo "Building ko"
|
||||||
|
|
||||||
RESULT="$(GO111MODULE="on" GOFLAGS="-mod=vendor" go build ./cmd/ko)"
|
RESULT="$(GO111MODULE="on" GOFLAGS="-mod=vendor" go build .)"
|
||||||
|
|
||||||
echo "Beginning scenarios."
|
echo "Beginning scenarios."
|
||||||
|
|
||||||
|
|||||||
51
main.go
Normal file
51
main.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 Google LLC All Rights Reserved.
|
||||||
|
|
||||||
|
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 main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
cranecmd "github.com/google/go-containerregistry/cmd/crane/cmd"
|
||||||
|
"github.com/google/go-containerregistry/pkg/logs"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/google/ko/pkg/commands"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
logs.Warn.SetOutput(os.Stderr)
|
||||||
|
logs.Progress.SetOutput(os.Stderr)
|
||||||
|
|
||||||
|
// Parent command to which all subcommands are added.
|
||||||
|
cmds := &cobra.Command{
|
||||||
|
Use: "ko",
|
||||||
|
Short: "Rapidly iterate with Go, Containers, and Kubernetes.",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
cmd.Help()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
commands.AddKubeCommands(cmds)
|
||||||
|
|
||||||
|
// Also add the auth group from crane to facilitate logging into a
|
||||||
|
// registry.
|
||||||
|
cmds.AddCommand(cranecmd.NewCmdAuth())
|
||||||
|
|
||||||
|
if err := cmds.Execute(); err != nil {
|
||||||
|
log.Fatal("error during command execution:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -46,7 +46,7 @@ func TestGoBuildIsSupportedRef(t *testing.T) {
|
|||||||
|
|
||||||
// Supported import paths.
|
// Supported import paths.
|
||||||
for _, importpath := range []string{
|
for _, importpath := range []string{
|
||||||
"ko://github.com/google/ko/cmd/ko", // ko can build itself.
|
"ko://github.com/google/ko", // ko can build itself.
|
||||||
} {
|
} {
|
||||||
t.Run(importpath, func(t *testing.T) {
|
t.Run(importpath, func(t *testing.T) {
|
||||||
if err := ng.IsSupportedReference(importpath); err != nil {
|
if err := ng.IsSupportedReference(importpath); err != nil {
|
||||||
@@ -76,7 +76,7 @@ func TestGoBuildIsSupportedRefWithModules(t *testing.T) {
|
|||||||
|
|
||||||
mods := &modules{
|
mods := &modules{
|
||||||
main: &modInfo{
|
main: &modInfo{
|
||||||
Path: "github.com/google/ko/cmd/ko/test",
|
Path: "github.com/google/ko/test",
|
||||||
Dir: ".",
|
Dir: ".",
|
||||||
},
|
},
|
||||||
deps: map[string]*modInfo{
|
deps: map[string]*modInfo{
|
||||||
@@ -92,8 +92,8 @@ func TestGoBuildIsSupportedRefWithModules(t *testing.T) {
|
|||||||
withModuleInfo(mods),
|
withModuleInfo(mods),
|
||||||
withBuildContext(stubBuildContext{
|
withBuildContext(stubBuildContext{
|
||||||
// make all referenced deps commands
|
// make all referenced deps commands
|
||||||
"github.com/google/ko/cmd/ko/test": &gb.Package{Name: "main"},
|
"github.com/google/ko/test": &gb.Package{Name: "main"},
|
||||||
"github.com/some/module/cmd": &gb.Package{Name: "main"},
|
"github.com/some/module/cmd": &gb.Package{Name: "main"},
|
||||||
|
|
||||||
"github.com/google/ko/pkg/build": &gb.Package{Name: "build"},
|
"github.com/google/ko/pkg/build": &gb.Package{Name: "build"},
|
||||||
}),
|
}),
|
||||||
@@ -106,8 +106,8 @@ func TestGoBuildIsSupportedRefWithModules(t *testing.T) {
|
|||||||
|
|
||||||
// Supported import paths.
|
// Supported import paths.
|
||||||
for _, importpath := range []string{
|
for _, importpath := range []string{
|
||||||
"ko://github.com/google/ko/cmd/ko/test", // ko can build the test package.
|
"ko://github.com/google/ko/test", // ko can build the test package.
|
||||||
"ko://github.com/some/module/cmd", // ko can build commands in dependent modules
|
"ko://github.com/some/module/cmd", // ko can build commands in dependent modules
|
||||||
} {
|
} {
|
||||||
t.Run(importpath, func(t *testing.T) {
|
t.Run(importpath, func(t *testing.T) {
|
||||||
if err := ng.IsSupportedReference(importpath); err != nil {
|
if err := ng.IsSupportedReference(importpath); err != nil {
|
||||||
@@ -120,7 +120,7 @@ func TestGoBuildIsSupportedRefWithModules(t *testing.T) {
|
|||||||
for _, importpath := range []string{
|
for _, importpath := range []string{
|
||||||
"ko://github.com/google/ko/pkg/build", // not a command.
|
"ko://github.com/google/ko/pkg/build", // not a command.
|
||||||
"ko://github.com/google/ko/pkg/nonexistent", // does not exist.
|
"ko://github.com/google/ko/pkg/nonexistent", // does not exist.
|
||||||
"ko://github.com/google/ko/cmd/ko", // not in this module.
|
"ko://github.com/google/ko", // not in this module.
|
||||||
} {
|
} {
|
||||||
t.Run(importpath, func(t *testing.T) {
|
t.Run(importpath, func(t *testing.T) {
|
||||||
if err := ng.IsSupportedReference(importpath); err == nil {
|
if err := ng.IsSupportedReference(importpath); err == nil {
|
||||||
@@ -167,7 +167,7 @@ func TestGoBuildNoKoData(t *testing.T) {
|
|||||||
t.Fatalf("NewGo() = %v", err)
|
t.Fatalf("NewGo() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := ng.Build(context.Background(), StrictScheme+filepath.Join(importpath, "cmd", "ko"))
|
result, err := ng.Build(context.Background(), StrictScheme+importpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Build() = %v", err)
|
t.Fatalf("Build() = %v", err)
|
||||||
}
|
}
|
||||||
@@ -192,7 +192,7 @@ func TestGoBuildNoKoData(t *testing.T) {
|
|||||||
|
|
||||||
// Check that rebuilding the image again results in the same image digest.
|
// Check that rebuilding the image again results in the same image digest.
|
||||||
t.Run("check determinism", func(t *testing.T) {
|
t.Run("check determinism", func(t *testing.T) {
|
||||||
result2, err := ng.Build(context.Background(), StrictScheme+filepath.Join(importpath, "cmd", "ko"))
|
result2, err := ng.Build(context.Background(), StrictScheme+importpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Build() = %v", err)
|
t.Fatalf("Build() = %v", err)
|
||||||
}
|
}
|
||||||
@@ -409,7 +409,7 @@ func TestGoBuild(t *testing.T) {
|
|||||||
t.Fatalf("NewGo() = %v", err)
|
t.Fatalf("NewGo() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := ng.Build(context.Background(), StrictScheme+filepath.Join(importpath, "cmd", "ko", "test"))
|
result, err := ng.Build(context.Background(), StrictScheme+filepath.Join(importpath, "test"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Build() = %v", err)
|
t.Fatalf("Build() = %v", err)
|
||||||
}
|
}
|
||||||
@@ -423,7 +423,7 @@ func TestGoBuild(t *testing.T) {
|
|||||||
|
|
||||||
// Check that rebuilding the image again results in the same image digest.
|
// Check that rebuilding the image again results in the same image digest.
|
||||||
t.Run("check determinism", func(t *testing.T) {
|
t.Run("check determinism", func(t *testing.T) {
|
||||||
result2, err := ng.Build(context.Background(), StrictScheme+filepath.Join(importpath, "cmd", "ko", "test"))
|
result2, err := ng.Build(context.Background(), StrictScheme+filepath.Join(importpath, "test"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Build() = %v", err)
|
t.Fatalf("Build() = %v", err)
|
||||||
}
|
}
|
||||||
@@ -465,7 +465,7 @@ func TestGoBuildIndex(t *testing.T) {
|
|||||||
t.Fatalf("NewGo() = %v", err)
|
t.Fatalf("NewGo() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := ng.Build(context.Background(), StrictScheme+filepath.Join(importpath, "cmd", "ko", "test"))
|
result, err := ng.Build(context.Background(), StrictScheme+filepath.Join(importpath, "test"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Build() = %v", err)
|
t.Fatalf("Build() = %v", err)
|
||||||
}
|
}
|
||||||
@@ -494,7 +494,7 @@ func TestGoBuildIndex(t *testing.T) {
|
|||||||
|
|
||||||
// Check that rebuilding the image again results in the same image digest.
|
// Check that rebuilding the image again results in the same image digest.
|
||||||
t.Run("check determinism", func(t *testing.T) {
|
t.Run("check determinism", func(t *testing.T) {
|
||||||
result2, err := ng.Build(context.Background(), StrictScheme+filepath.Join(importpath, "cmd", "ko", "test"))
|
result2, err := ng.Build(context.Background(), StrictScheme+filepath.Join(importpath, "test"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Build() = %v", err)
|
t.Fatalf("Build() = %v", err)
|
||||||
}
|
}
|
||||||
@@ -536,7 +536,7 @@ func TestNestedIndex(t *testing.T) {
|
|||||||
t.Fatalf("NewGo() = %v", err)
|
t.Fatalf("NewGo() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = ng.Build(context.Background(), StrictScheme+filepath.Join(importpath, "cmd", "ko", "test"))
|
_, err = ng.Build(context.Background(), StrictScheme+filepath.Join(importpath, "test"))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("Build() expected err")
|
t.Fatal("Build() expected err")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDaemon(t *testing.T) {
|
func TestDaemon(t *testing.T) {
|
||||||
importpath := "github.com/google/ko/cmd/ko"
|
importpath := "github.com/google/ko"
|
||||||
img, err := random.Image(1024, 1)
|
img, err := random.Image(1024, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("random.Image() = %v", err)
|
t.Fatalf("random.Image() = %v", err)
|
||||||
@@ -65,7 +65,7 @@ func TestDaemon(t *testing.T) {
|
|||||||
func TestDaemonTags(t *testing.T) {
|
func TestDaemonTags(t *testing.T) {
|
||||||
Tags = nil
|
Tags = nil
|
||||||
|
|
||||||
importpath := "github.com/google/ko/cmd/ko"
|
importpath := "github.com/google/ko"
|
||||||
img, err := random.Image(1024, 1)
|
img, err := random.Image(1024, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("random.Image() = %v", err)
|
t.Fatalf("random.Image() = %v", err)
|
||||||
@@ -78,7 +78,7 @@ func TestDaemonTags(t *testing.T) {
|
|||||||
t.Errorf("Publish() = %v, wanted prefix %v", got, want)
|
t.Errorf("Publish() = %v, wanted prefix %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := []string{"ko.local/099ba5bcefdead87f92606265fb99ac0:v2.0.0", "ko.local/099ba5bcefdead87f92606265fb99ac0:v1.2.3", "ko.local/099ba5bcefdead87f92606265fb99ac0:production"}
|
expected := []string{"ko.local/98b8c7facdad74510a7cae0cd368eb4e:v2.0.0", "ko.local/98b8c7facdad74510a7cae0cd368eb4e:v1.2.3", "ko.local/98b8c7facdad74510a7cae0cd368eb4e:production"}
|
||||||
|
|
||||||
for i, v := range expected {
|
for i, v := range expected {
|
||||||
if Tags[i] != v {
|
if Tags[i] != v {
|
||||||
|
|||||||
1
test/kodata/HEAD
Symbolic link
1
test/kodata/HEAD
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../.git/HEAD
|
||||||
1
test/kodata/refs
Symbolic link
1
test/kodata/refs
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../.git/refs
|
||||||
@@ -18,5 +18,5 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: obiwan
|
- name: obiwan
|
||||||
image: ko://github.com/google/ko/cmd/ko/test
|
image: ko://github.com/google/ko/test
|
||||||
restartPolicy: Never
|
restartPolicy: Never
|
||||||
Reference in New Issue
Block a user