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
6 changes: 3 additions & 3 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
Expand All @@ -54,7 +54,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v3

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
Expand All @@ -68,4 +68,4 @@ jobs:
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v3
2 changes: 1 addition & 1 deletion .github/workflows/docker-description.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:

- name: Sync Docker Hub Description
if: github.ref == 'refs/heads/main' && github.repository == 'kool-dev/kool'
uses: peter-evans/dockerhub-description@v2
uses: peter-evans/dockerhub-description@v4
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@master
uses: actions/checkout@v4

- uses: olegtarasov/get-tag@v2.1
id: tagName
Expand Down
11 changes: 5 additions & 6 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@ jobs:
name: lint
runs-on: ubuntu-latest
steps:
# ref: https://github.com/golangci/golangci-lint-action/issues/442#issuecomment-1203786890
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
cache-dependency-path: go.sum
- name: Install golangci-lint
run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.1
- name: Run golangci-lint
run: golangci-lint run --version --verbose --out-format=github-actions
uses: golangci/golangci-lint-action@v7
with:
version: v2.11.4
2 changes: 1 addition & 1 deletion .github/workflows/release-drafter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ jobs:
issues: write
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v5
- uses: release-drafter/release-drafter@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4 changes: 2 additions & 2 deletions .github/workflows/scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@master
uses: actions/checkout@v4

- name: Build image
run: docker build --pull -t kooldev/kool:4scan .

- name: Scan image
uses: anchore/scan-action@v2
uses: anchore/scan-action@v6
with:
image: "kooldev/kool:4scan"
fail-build: true
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ jobs:
test:
strategy:
matrix:
go-version: [1.21.x]
go-version: [1.25.x]
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Install Go
uses: actions/setup-go@v2
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
Expand Down
18 changes: 18 additions & 0 deletions .grype.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Grype config for the kooldev/kool Docker image scan (.github/workflows/scan.yml).
#
# The ignore list below is reserved for CVEs we inherit from upstream images
# and cannot fix ourselves — each entry must link to the upstream tracker and
# be revisited (and ideally removed) when upstream rebuilds.
#
# See docs/01-Getting-Started/5-CI-Integration.md#known-security-caveat for the
# user-facing context.

ignore:
# Inherited from docker:29-cli (Docker 29.4.1). The bundled
# /usr/local/libexec/docker/cli-plugins/{docker-compose,docker-buildx}
# are Go binaries built with go1.25.8; CVE-2026-27143 is fixed in go1.25.9.
# Will clear automatically when docker-library/docker rebuilds the 29-cli
# image with a newer Go toolchain. Tracked upstream:
# https://github.com/docker-library/docker
# Remove this entry once `grype kooldev/kool:<tag>` no longer reports it.
- vulnerability: CVE-2026-27143
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.21 AS build
FROM golang:1.25 AS build

ARG BUILD_VERSION=0.0.0-auto

Expand All @@ -11,7 +11,7 @@ RUN go build -a \
-ldflags '-X kool-dev/kool/commands.version='$BUILD_VERSION' -extldflags "-static"' \
-o kool

FROM docker:27-cli
FROM docker:29-cli

ENV DOCKER_HOST=tcp://docker:2375

Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ curl -fsSL https://kool.dev/install | bash

You must run `kool` on Windows via [WSL - Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/install) - once you have a WSL environment properly set up, make sure you have [Docker available on it](https://docs.docker.com/desktop/wsl/), then you can install the CLI as you would in any Linux or MacOS (see above).

### In CI pipelines

For CI/CD use cases — most commonly **GitLab CI** with a `docker:dind` service — we publish a pre-built image at [**kooldev/kool**](https://hub.docker.com/r/kooldev/kool) that bundles `kool` together with `docker`, `docker compose`, `git`, and `bash`. See the [CI Integration guide](docs/01-Getting-Started/5-CI-Integration.md) for the DinD sidecar pattern and example `.gitlab-ci.yml` / GitHub Actions configs, plus a [known security caveat](docs/01-Getting-Started/5-CI-Integration.md#known-security-caveat) about CVEs inherited from the upstream `docker:X-cli` base image.

## Getting Started

It's really easy to get started with `kool`. Check out our [Getting Started documentation for a generic PHP web app](https://kool.dev/docs/getting-started/starting-new-project).
Expand Down Expand Up @@ -84,6 +88,8 @@ Our work is organized according to a loosely defined but clear roadmap. Check ou

If you find a security issue, please let us know right away, before making it public, by creating a GitHub issue. We'll take action as soon as possible. You can email questions and concerns to `contact@kool.dev`.

For known CVEs inherited by the `kooldev/kool` Docker image from its upstream `docker:X-cli` base, see the [known security caveat](docs/01-Getting-Started/5-CI-Integration.md#known-security-caveat) in the CI Integration guide. These affect only users running the published Docker image in CI pipelines — the native **kool** binary installed via `curl | bash` is unaffected.

## License

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
2 changes: 1 addition & 1 deletion build_artifacts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ if [ -f .env ]; then
source .env
fi

GO_IMAGE=${GO_IMAGE:-golang:1.21}
GO_IMAGE=${GO_IMAGE:-golang:1.25}

if [ "$BUILD_VERSION" == "" ]; then
echo "missing environment variable BUILD_VERSION"
Expand Down
4 changes: 2 additions & 2 deletions commands/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ func NewCloudCommand(cloud *Cloud) (cloudCmd *cobra.Command) {
PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) {
// calls root PersistentPreRunE
var (
requiredFlags bool = cmd.Use != "setup"
root *cobra.Command = cmd
requiredFlags = cmd.Use != "setup"
root = cmd
)

for root.HasParent() {
Expand Down
4 changes: 2 additions & 2 deletions commands/cloud_deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ func (d *KoolDeploy) Execute(args []string) (err error) {
timeout = time.Duration(min) * time.Minute
}

var finishes chan bool = make(chan bool)
var finishes = make(chan bool)

go func(deployCreated *api.DeployCreateResponse, finishes chan bool) {
var (
Expand Down Expand Up @@ -236,7 +236,7 @@ func (d *KoolDeploy) createReleaseFile() (filename string, err error) {
var allFiles []string

// new behavior - tarball only the required files
var possibleKoolDeployYmlFiles []string = []string{
var possibleKoolDeployYmlFiles = []string{
"kool.cloud.yml",
"kool.cloud.yaml",
"kool.deploy.yml",
Expand Down
2 changes: 1 addition & 1 deletion commands/cloud_deploy_exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestKoolDeployExec(t *testing.T) {
t.Errorf("expected: missing deploy domain; got something else")
}

var domain string = "example.com"
var domain = "example.com"
e.env.Set("KOOL_DEPLOY_DOMAIN", domain)

mock := e.cloud.(*fakeK8S)
Expand Down
10 changes: 5 additions & 5 deletions commands/cloud_setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (s *KoolCloudSetup) Execute(args []string) (err error) {
composeConfig *compose.DockerComposeConfig
serviceName string

deployConfig *cloud.CloudConfig = &cloud.CloudConfig{
deployConfig = &cloud.CloudConfig{
Version: "1.0",
Services: make(map[string]*cloud.DeployConfigService),
}
Expand Down Expand Up @@ -85,7 +85,7 @@ func (s *KoolCloudSetup) Execute(args []string) (err error) {

s.Shell().Info("Docker compose configuration loaded. Starting interactive setup:")

var hasPublicPort bool = false
var hasPublicPort = false

var serviceNames []string

Expand All @@ -98,7 +98,7 @@ func (s *KoolCloudSetup) Execute(args []string) (err error) {
for _, serviceName = range serviceNames {
var (
confirmed bool
isPublic bool = false
isPublic = false
answer string

composeService = composeConfig.Services[serviceName]
Expand Down Expand Up @@ -175,7 +175,7 @@ func (s *KoolCloudSetup) Execute(args []string) (err error) {
return
}

content.WriteString(fmt.Sprintf("FROM %s\n", (*composeService.Image).(string)))
fmt.Fprintf(&content, "FROM %s\n", (*composeService.Image).(string))

for _, vol := range composeService.Volumes {
volParts := strings.Split(vol, ":")
Expand All @@ -188,7 +188,7 @@ func (s *KoolCloudSetup) Execute(args []string) (err error) {
if confirmed, err = s.promptSelect.Confirm("Do you want to add folder '%s' onto '%s' in the Dockerfile for service '%s'?", volParts[0], volParts[1], serviceName); err != nil {
return
} else if confirmed {
content.WriteString(fmt.Sprintf("\nCOPY %s %s\n", volParts[0], volParts[1]))
fmt.Fprintf(&content, "\nCOPY %s %s\n", volParts[0], volParts[1])
}
}

Expand Down
2 changes: 1 addition & 1 deletion commands/completion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func expectedCompletionOutput(shellType string) (expected string, err error) {
func TestNewKoolCompletion(t *testing.T) {
k := NewKoolCompletion(rootCmd)

if _, ok := k.DefaultKoolService.shell.(*shell.DefaultShell); !ok {
if _, ok := k.shell.(*shell.DefaultShell); !ok {
t.Error("unexpected shell.Shell on default KoolCompletion instance")
}

Expand Down
6 changes: 3 additions & 3 deletions commands/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,14 @@ func (c *KoolCreate) Execute(args []string) (err error) {
}

if createDirectory == "" {
c.Shell().Error(fmt.Errorf("Please enter a valid folder name"))
c.Shell().Error(fmt.Errorf("please enter a valid folder name"))
continue
} else if _, err = os.Stat(createDirectory); !os.IsNotExist(err) {
c.Shell().Error(fmt.Errorf("Folder %s already exists.", createDirectory))
c.Shell().Error(fmt.Errorf("folder %s already exists", createDirectory))
continue
} else {
if err = os.MkdirAll(filepath.Join(os.TempDir(), createDirectory), 0755); err != nil {
c.Shell().Error(fmt.Errorf("Please enter a valid folder name"))
c.Shell().Error(fmt.Errorf("please enter a valid folder name"))
continue
} else {
// ok we created, let's just have it removed if we fail
Expand Down
2 changes: 1 addition & 1 deletion commands/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func newFakeKoolCreate() *KoolCreate {
func TestNewKoolCreate(t *testing.T) {
k := NewKoolCreate()

if _, ok := k.DefaultKoolService.shell.(*shell.DefaultShell); !ok {
if _, ok := k.shell.(*shell.DefaultShell); !ok {
t.Errorf("unexpected shell.Shell on default KoolCreate instance")
}

Expand Down
2 changes: 1 addition & 1 deletion commands/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func newFailedFakeKoolDocker() *KoolDocker {
func TestNewKoolDocker(t *testing.T) {
k := NewKoolDocker()

if _, ok := k.DefaultKoolService.shell.(*shell.DefaultShell); !ok {
if _, ok := k.shell.(*shell.DefaultShell); !ok {
t.Errorf("unexpected shell.Shell on default KoolDocker instance")
}

Expand Down
2 changes: 1 addition & 1 deletion commands/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func newFailedFakeKoolExec() *KoolExec {
func TestNewKoolExec(t *testing.T) {
k := NewKoolExec()

if _, ok := k.DefaultKoolService.shell.(*shell.DefaultShell); !ok {
if _, ok := k.shell.(*shell.DefaultShell); !ok {
t.Errorf("unexpected shell.Shell on default KoolExec instance")
}

Expand Down
4 changes: 2 additions & 2 deletions commands/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func AddKoolInfo(root *cobra.Command) {
// Execute executes info logic
func (i *KoolInfo) Execute(args []string) (err error) {
var (
filter string = "KOOL_"
filter = "KOOL_"
output string
)

Expand Down Expand Up @@ -84,7 +84,7 @@ func (i *KoolInfo) Execute(args []string) (err error) {
if output, err = i.Shell().Exec(i.cmdDockerCompose); err != nil {
// just alert missing docker compose, but don't elevate error
i.Shell().Warning("Docker Compose:", err.Error())
i.Shell().Error(fmt.Errorf("You need to have Docker Compose V2 available. Make sure to update your Docker installation."))
i.Shell().Error(fmt.Errorf("you need to have Docker Compose V2 available; make sure to update your Docker installation"))
return
} else {
i.Shell().Println(output)
Expand Down
4 changes: 2 additions & 2 deletions commands/kool_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (t *DefaultKoolTask) Run(args []string) (err error) {

t.originalOut = t.Shell().OutStream()
if t.termWidth, err = shell.GetTerminalWidth(t.originalOut); err != nil {
fmt.Fprintf(t.Shell().ErrStream(), "[bad TTY] %s", err.Error())
_, _ = fmt.Fprintf(t.Shell().ErrStream(), "[bad TTY] %s", err.Error())
err = nil
}
t.actualOut.SetOutStream(t.originalOut)
Expand All @@ -64,7 +64,7 @@ func (t *DefaultKoolTask) Run(args []string) (err error) {
donePrinting := t.printServiceOutput(lines)

err = <-t.execService(args)
pipeWriter.Close()
_ = pipeWriter.Close()
<-donePrinting
var statusMessage string
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion commands/logs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func newFakeFailedKoolLogs() *KoolLogs {
func TestNewKoolLogs(t *testing.T) {
k := NewKoolLogs()

if _, ok := k.DefaultKoolService.shell.(*shell.DefaultShell); !ok {
if _, ok := k.shell.(*shell.DefaultShell); !ok {
t.Errorf("unexpected shell.Shell on default KoolLogs instance")
}

Expand Down
2 changes: 1 addition & 1 deletion commands/preset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
func TestNewKoolPreset(t *testing.T) {
k := NewKoolPreset()

if _, ok := k.DefaultKoolService.shell.(*shell.DefaultShell); !ok {
if _, ok := k.shell.(*shell.DefaultShell); !ok {
t.Errorf("unexpected shell.Shell on default KoolPreset instance")
}

Expand Down
2 changes: 1 addition & 1 deletion commands/restart.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type KoolRestartFlags struct {

// NewRestartCommand initializes new kool start command
func NewRestartCommand(stop KoolService, start KoolService) (restartCmd *cobra.Command) {
var flags *KoolRestartFlags = &KoolRestartFlags{false, false}
var flags = &KoolRestartFlags{false, false}

restartCmd = &cobra.Command{
Use: "restart",
Expand Down
6 changes: 3 additions & 3 deletions commands/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ func TestAddCommands(t *testing.T) {

AddCommands(root)

var subcommands map[string]bool = map[string]bool{
var subcommands = map[string]bool{
"completion": false,
"create": false,
"cloud": false,
Expand Down Expand Up @@ -319,8 +319,8 @@ func TestDevelopmentVersionWarning(t *testing.T) {
} else {
root.SetOut(tty)

defer pty.Close()
defer tty.Close()
defer func() { _ = pty.Close() }()
defer func() { _ = tty.Close() }()
}
version = DEV_VERSION
if err := root.Execute(); err != nil {
Expand Down
Loading
Loading