diff --git a/.devcontainer/devcontainer-lock.json b/.devcontainer/devcontainer-lock.json index 7cf79cbf33..12e368eeed 100644 --- a/.devcontainer/devcontainer-lock.json +++ b/.devcontainer/devcontainer-lock.json @@ -1,5 +1,10 @@ { "features": { + "ghcr.io/devcontainers-extra/features/mise:1": { + "version": "1.0.0", + "resolved": "ghcr.io/devcontainers-extra/features/mise@sha256:5c389ab1e3c8e44e5e0ff119f6868d54dbb781bc860bd8587dc66209cb8c4a8c", + "integrity": "sha256:5c389ab1e3c8e44e5e0ff119f6868d54dbb781bc860bd8587dc66209cb8c4a8c" + }, "ghcr.io/devcontainers/features/node:2": { "version": "2.1.0", "resolved": "ghcr.io/devcontainers/features/node@sha256:586c9a6f7dd40bd3ba2cd41e7f2f88dcc31fbe5d1442afcbf07ffbc66b686857", @@ -10,12 +15,6 @@ "resolved": "ghcr.io/skevetter/features/curl@sha256:51d9731e398d4d80fb0adf41725f3fb141186f7e28b3bb000a737abcdc8dace4", "integrity": "sha256:51d9731e398d4d80fb0adf41725f3fb141186f7e28b3bb000a737abcdc8dace4" }, - "ghcr.io/skevetter/features/go-task:1": { - "version": "1.0.0", - "resolved": "ghcr.io/skevetter/features/go-task@sha256:347d13ba8faa01a1073d237eae5fe21897cad4bfe2cd6404a97cdda466812c71", - "integrity": "sha256:347d13ba8faa01a1073d237eae5fe21897cad4bfe2cd6404a97cdda466812c71", - "dependsOn": ["ghcr.io/skevetter/features/picolayer:1"] - }, "ghcr.io/skevetter/features/picolayer:1": { "version": "1.0.1", "resolved": "ghcr.io/skevetter/features/picolayer@sha256:0e3ba730535d31b899c5e6d55c3aa9392c593b9ac636692c08c6fa6396d87885", diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 671a39aa51..95aa220076 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,11 +1,12 @@ { "image": "mcr.microsoft.com/devcontainers/go:1.26", "features": { - "ghcr.io/skevetter/features/go-task:1": {}, + "ghcr.io/devcontainers-extra/features/mise:1": {}, "ghcr.io/skevetter/features/prek:1": {}, "ghcr.io/skevetter/features/uv:1": {}, "ghcr.io/devcontainers/features/node:2": { "version": "24" } - } + }, + "postCreateCommand": "mise trust && mise install" } diff --git a/.github/workflows/act.yml b/.github/workflows/act.yml index b67a597f39..00f6e7da26 100644 --- a/.github/workflows/act.yml +++ b/.github/workflows/act.yml @@ -20,13 +20,8 @@ jobs: with: node-version: "24" - - name: setup Go - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 - with: - go-version-file: go.mod - - - name: install task - run: go install github.com/go-task/task/v3/cmd/task@latest + - name: setup mise tools + uses: jdx/mise-action@5228313ee0372e111a38da051671ca30fc5a96db # v3 - name: install goreleaser uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7 @@ -39,7 +34,7 @@ jobs: run: docker version && docker ps -a - name: build test binary - run: task cli:test:e2e:build + run: mise run cli:test:e2e:build - name: generate GitHub App token id: app-token @@ -61,7 +56,7 @@ jobs: KUBECONFIG="${KUBECONFIG:-$HOME/.kube/config}" \ PATH="${PATH}" \ GOROOT="${GOROOT}" \ - ${{ github.event.inputs.test_focus == '' && 'task cli:test:e2e' || format('task cli:test:e2e:focus -- "{0}"', github.event.inputs.test_focus) }} + ${{ github.event.inputs.test_focus == '' && 'mise run cli:test:e2e' || format('mise run cli:test:e2e:focus -- "{0}"', github.event.inputs.test_focus) }} build-ui: name: Build User Interface diff --git a/.github/workflows/devcontainer.yml b/.github/workflows/devcontainer.yml index fb66f2a145..eafd4207a8 100644 --- a/.github/workflows/devcontainer.yml +++ b/.github/workflows/devcontainer.yml @@ -16,13 +16,13 @@ on: runCmd: description: "Command to run inside the devcontainer" required: false - default: for c in go task prek uv node; do command -v "$c" >/dev/null 2>&1 || { echo "missing $c" >&2; exit 1; }; done + default: for c in go mise prek uv node; do command -v "$c" >/dev/null 2>&1 || { echo "missing $c" >&2; exit 1; }; done permissions: contents: read env: - DEFAULT_RUN_CMD: for c in go task prek uv node; do command -v "$c" >/dev/null 2>&1 || { echo "missing $c" >&2; exit 1; }; done + DEFAULT_RUN_CMD: for c in go mise prek uv node; do command -v "$c" >/dev/null 2>&1 || { echo "missing $c" >&2; exit 1; }; done jobs: build: diff --git a/.github/workflows/pr-ci.yml b/.github/workflows/pr-ci.yml index 48320e405e..61e481d8dd 100644 --- a/.github/workflows/pr-ci.yml +++ b/.github/workflows/pr-ci.yml @@ -45,7 +45,9 @@ jobs: steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - - uses: j178/prek-action@4e14d07f9231acabce116ccfca13b13dd9755ece # v3.0.0 + - uses: jdx/mise-action@5228313ee0372e111a38da051671ca30fc5a96db # v3 + + - run: prek run --all-files agent-skill: name: Agent Skill diff --git a/.golangci-version b/.golangci-version deleted file mode 100644 index 095c2a17d9..0000000000 --- a/.golangci-version +++ /dev/null @@ -1 +0,0 @@ -v2.13.2 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index acb61bed63..0000000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,77 +0,0 @@ -repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 - hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - - id: check-yaml - args: ["--allow-multiple-documents"] - - id: check-added-large-files - exclude: "^(sites/docs-devsy-sh/)" - - id: check-merge-conflict - - repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook - rev: v9.26.0 - hooks: - - id: commitlint - stages: [commit-msg] - language_version: lts - additional_dependencies: - - "@commitlint/config-conventional" - verbose: true - - repo: https://github.com/shellcheck-py/shellcheck-py - rev: v0.11.0.1 - hooks: - - id: shellcheck - args: - [ - "-e", - "SC1091,SC1103,SC2148,SC2034,SC1090,SC1009,SC1054,SC1056,SC1072,SC1073,SC1083,SC2329", - ] - - repo: https://github.com/scop/pre-commit-shfmt - rev: v3.12.0-2 - hooks: - - id: shfmt - args: ["-i", "4", "-ci", "-w"] - - repo: https://github.com/rhysd/actionlint - rev: v1.7.12 - hooks: - - id: actionlint - files: '^\.github/workflows/' - # actionlint v1.7.12 does not yet recognize the background/wait/ - # wait-all/cancel/parallel step keywords GitHub Actions shipped - # 2026-06-25 (https://github.blog/changelog/2026-06-25-actions-steps-can-now-be-run-in-parallel/). - # Tracked upstream: https://github.com/rhysd/actionlint/issues/693 - args: ["-ignore", "unexpected key \"background\" for step"] - - repo: https://github.com/biomejs/pre-commit - rev: v2.5.13 - hooks: - - id: biome-format - exclude: '^(\.github/actions/|\.vscode/|sites/|examples/)' - - id: biome-ci - exclude: '^(\.github/actions/|\.vscode/|sites/|examples/)' - - repo: https://github.com/gitleaks/gitleaks - rev: v8.30.1 - hooks: - - id: gitleaks - - repo: https://github.com/commitizen-tools/commitizen - rev: v4.18.1 - hooks: - - id: commitizen - stages: [commit-msg] - - repo: https://github.com/golangci/golangci-lint - rev: v2.13.2 - hooks: - - id: golangci-lint - language_version: 1.26.9 - args: ["--timeout=10m"] - - id: golangci-lint-fmt - language_version: 1.26.9 - - repo: local - hooks: - - id: golangci-lint-ci-parity - name: golangci-lint (CI parity, new-from-patch) - entry: task cli:lint:ci - language: system - types: [go] - pass_filenames: false - stages: [pre-push] diff --git a/AGENTS.md b/AGENTS.md index 3010d4418e..a60735be0a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,21 +14,21 @@ Toolchain is managed by mise. Install mise using `curl https://mise.run | sh`. I ## Common Developer Commands -`task --list` shows developer commands. The most common tasks: +`mise tasks` shows developer commands. The most common tasks: ### CLI (Go) Development -- **Tidy Go modules**: `task cli:tidy` -- **Lint CLI**: `task cli:lint` and `task cli:lint:ci` (or `task cli:lint:fix` to apply fixes) -- **Format CLI**: `task cli:format` -- **Run unit tests**: `task cli:test` (writes coverage to `dist/profile.out`; a `dist` directory is required, e.g. `mkdir -p dist`) -- **Build development binary**: `task cli:build:dev` (output under `dist/devsy-dev_linux_amd64_v1/`) +- **Tidy Go modules**: `mise run cli:tidy` +- **Lint CLI**: `mise run cli:lint` and `mise run cli:lint:ci` (or `mise run cli:lint:fix` to apply fixes) +- **Format CLI**: `mise run cli:format` +- **Run unit tests**: `mise run cli:test` (writes coverage to `dist/profile.out`; a `dist` directory is required, e.g. `mkdir -p dist`) +- **Build development binary**: `mise run cli:build:dev` (output under `dist/devsy-dev_linux_amd64_v1/`) ### Desktop (Electron/Svelte 5) Development -- **Verify desktop code quality**: `task desktop:check` (Svelte check and TypeScript compiler) -- **Run desktop unit tests**: `task desktop:test` -- **Run desktop E2E (Playwright) tests**: `task desktop:test:e2e` +- **Verify desktop code quality**: `mise run desktop:check` (Svelte check and TypeScript compiler) +- **Run desktop unit tests**: `mise run desktop:test` +- **Run desktop E2E (Playwright) tests**: `mise run desktop:test:e2e` ### Local Development: Agent Binary URL (`DEVSY_AGENT_URL`) @@ -42,7 +42,7 @@ Local setup: ```bash # 1. Build the agent binary for the workspace's Linux arch (output: dist/devsy-dev_linux_amd64_v1/devsy-linux-amd64). -task cli:build:dev +mise run cli:build:dev # 2. Serve the built binary over HTTP. mkdir -p bin @@ -64,18 +64,18 @@ The agent binary runs inside the (Linux) workspace, so it is a Linux binary (`de Desktop tests run inside an Electron browser environment. In headless or container environments, Electron commands require an `xvfb-run` prefix to emulate a display server: ```bash -xvfb-run task desktop:test # Desktop unit tests headlessly +xvfb-run mise run desktop:test # Desktop unit tests headlessly -xvfb-run task desktop:test:e2e # Desktop E2E tests headlessly +xvfb-run mise run desktop:test:e2e # Desktop E2E tests headlessly ``` ### E2E (Ginkgo) Tests Devsy uses [Ginkgo](https://onsi.github.io/ginkgo/) for Go E2E and integration tests. -- **All E2E tests**: `task cli:test:e2e` -- **A focused test suite**: `task cli:test:e2e:suite -- "suite-name"` -- **A specific test pattern**: `task cli:test:e2e:focus -- "test-pattern"` +- **All E2E tests**: `mise run cli:test:e2e` +- **A focused test suite**: `mise run cli:test:e2e:suite "suite-name"` +- **A specific test pattern**: `mise run cli:test:e2e:focus "test-pattern"` --- @@ -86,7 +86,7 @@ Devsy uses [Ginkgo](https://onsi.github.io/ginkgo/) for Go E2E and integration t - **Idiomatic**: Focus on simplicity, reliability, and efficiency when writing clear, idiomatic Go code. - **Style Guide**: Use the Uber style guide https://github.com/uber-go/guide/blob/master/style.md. - **Unit Testing**: Prefer using [testify suite](https://github.com/stretchr/testify#suite-package) (`testify/suite`) for writing unit tests. -- **Linter**: `golangci-lint` via `task cli:lint` (or `task cli:lint:fix`). Run `task cli:lint:ci` before pushing changes. +- **Linter**: `golangci-lint` via `mise run cli:lint` (or `mise run cli:lint:fix`). Run `mise run cli:lint:ci` before pushing changes. ### TypeScript / Svelte Code Style diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3d983bb65e..38bd0ebd47 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ posting a comment on the pull request with the exact text the bot provides. **CLI Development:** - [Go 1.26+](https://go.dev/doc/install) -- [Task](https://taskfile.dev/) (optional, but recommended for running tasks) +- [mise](https://mise.jdx.dev/) (installs the pinned toolchain and runs project tasks via `mise run `) **Desktop Application Development:** @@ -34,24 +34,24 @@ posting a comment on the pull request with the exact text the bot provides. 2. If you want to change Devsy agent code: - Exchange the URL in [DefaultAgentDownloadURL](./pkg/config/repo.go) with a custom public repository release - - Build devsy via: `task cli:build:dev` + - Build devsy via: `mise run cli:build:dev` - Upload `dist/devsy-dev_linux_amd64_v1/devsy-linux-amd64` and ARM64 variant to your public repository release assets ## Building from Source ### CLI -**Using Task (recommended):** +**Using mise (recommended):** ```bash # Build CLI for development -task cli:build:dev +mise run cli:build:dev # Build CLI for production -task cli:build +mise run cli:build # Build with Pro features -task cli:build:dev:pro +mise run cli:build:dev:pro ``` **Using Go directly:** @@ -64,17 +64,17 @@ The binary will be output as `devsy` in the current directory. ### Desktop Application -**Using Task (recommended):** +**Using mise (recommended):** ```bash # Setup Electron environment (first time only) -task desktop:setup +mise run desktop:setup # Run in development mode -task desktop:dev +mise run desktop:dev # Build the application -task desktop:build +mise run desktop:build ``` **Manual build:** @@ -93,16 +93,16 @@ The packaged application will be in `desktop/release/` ```bash # Tidy dependencies -task cli:tidy +mise run cli:tidy # Run linters -task cli:lint +mise run cli:lint # Run unit tests -task cli:test +mise run cli:test # Build for development -task cli:build:dev +mise run cli:build:dev ``` ### Desktop Development @@ -123,35 +123,35 @@ cd desktop npm ci # Check code quality (type check + svelte-check) -task desktop:check +mise run desktop:check # Run unit tests -task desktop:test +mise run desktop:test # Run e2e tests -task desktop:test:e2e +mise run desktop:test:e2e ``` ### E2E Testing ```bash # Build for e2e tests -task cli:test:e2e:build +mise run cli:test:e2e:build # Run all e2e tests -task cli:test:e2e +mise run cli:test:e2e # Run specific test suite -task cli:test:e2e:suite -- "suite-name" +mise run cli:test:e2e:suite "suite-name" # Run focused tests -task cli:test:e2e:focus -- "test-pattern" +mise run cli:test:e2e:focus "test-pattern" # Setup kind cluster for testing -task cli:test:e2e:kind:setup +mise run cli:test:e2e:kind:setup # Teardown kind cluster -task cli:test:e2e:kind:teardown +mise run cli:test:e2e:kind:teardown ``` ### gRPC Development @@ -159,7 +159,7 @@ task cli:test:e2e:kind:teardown If you need to modify the gRPC tunnel code: ```bash -task cli:build:grpc +mise run cli:build:grpc ``` This requires: @@ -172,7 +172,7 @@ This requires: 1. Build Devsy: ```bash - task cli:build:dev + mise run cli:build:dev ``` 2. Add a provider: @@ -194,16 +194,16 @@ This requires: ```bash # Build UI using act -task desktop:act:build:ui +mise run desktop:act:build:ui # Build desktop app using act -task desktop:act:build:app +mise run desktop:act:build:app # Build flatpak using act -task desktop:act:build:flatpak +mise run desktop:act:build:flatpak # Run e2e tests with focus -task cli:test:e2e:act:focus -- "test-pattern" +mise run cli:test:e2e:act:focus "test-pattern" ``` ## Developing Providers diff --git a/THIRD_PARTY_LICENSES.md b/THIRD_PARTY_LICENSES.md index 967aa10fb3..2872b199f5 100644 --- a/THIRD_PARTY_LICENSES.md +++ b/THIRD_PARTY_LICENSES.md @@ -1,5 +1,5 @@ - + # Third-Party Licenses @@ -7,7 +7,7 @@ The Devsy CLI is built with the open-source Go modules listed below. Each entry links to the module and notes the license it is distributed under. Some dependencies are only included on certain operating systems or architectures. -To regenerate this file after changing dependencies, run `task cli:licenses`. +To regenerate this file after changing dependencies, run `mise run cli:licenses`. ## Dependencies diff --git a/Taskfile.yml b/Taskfile.yml deleted file mode 100644 index c0210cdcb3..0000000000 --- a/Taskfile.yml +++ /dev/null @@ -1,310 +0,0 @@ -version: "3" - -tasks: - agent-skill:validate: - desc: validate the end-user Devsy skill and installer discovery (requires Node 22.20+ and Python 3.11+) - cmd: go run ./hack/validate_agent_skill - - cli:tidy: - desc: tidy go.mod and go.sum - cmd: go mod tidy - - cli:licenses: - desc: regenerate THIRD_PARTY_LICENSES.md and enforce the license allowlist - cmd: go run ./hack/licenses - - cli:licenses:check: - desc: verify THIRD_PARTY_LICENSES.md is in sync and all licenses are allowed (CI) - cmd: go run ./hack/licenses --check - - cli:lint: - desc: lint go code using golangci-lint - deps: [cli:lint:version] - cmd: golangci-lint run ./... - - cli:lint:ci: - desc: lint using golangci-lint with CI parity - deps: [cli:lint:version] - cmds: - - golangci-lint config verify - - git fetch --quiet origin main - - | - patch="$(mktemp)" - trap 'rm -f "$patch"' EXIT - git diff "$(git merge-base HEAD origin/main)" > "$patch" - golangci-lint run --new-from-patch="$patch" --new=false ./... - - cli:lint:version: - desc: assert the local golangci-lint matches .golangci-version (the version CI uses) - cmd: | - want="$(sed 's/^v//' .golangci-version | tr -d '[:space:]')" - cur="$(golangci-lint --version 2>&1 | sed -n 's/.*version \([0-9][0-9A-Za-z.+-]*\).*/\1/p')" - if [ "$cur" != "$want" ]; then - echo "golangci-lint version mismatch: local=${cur:-}, expected=${want}. Install golangci-lint v${want}." >&2 - exit 1 - fi - silent: true - - cli:lint:fix: - desc: fix lint issues using golangci-lint - deps: [cli:lint:version] - cmd: golangci-lint run --fix ./... - - cli:format: - desc: format go code using golangci-lint formatters - deps: [cli:lint:version] - cmd: golangci-lint fmt ./... - - cli:act:lint: - desc: run devsy linters using act - cmd: act workflow_dispatch -W .github/workflows/lint.yml - - cli:build: - desc: build devsy CLI - env: - GITHUB_REPOSITORY_OWNER: devsy-org - cmd: go tool goreleaser build --id devsy --snapshot --clean - - cli:build:dev: - desc: build devsy CLI for development - env: - GITHUB_REPOSITORY_OWNER: devsy-org - DEVSY_CLI_VERSION: v0.0.0 - cmd: go tool goreleaser build --id devsy-dev --snapshot --clean - - cli:build:dev:pro: - desc: build devsy CLI for pro feature - vars: - NS: '{{.NS | default "default"}}' - cmd: go tool goreleaser build --id devsy-pro-dev --snapshot --clean - env: - GITHUB_REPOSITORY_OWNER: devsy-org - DEVSY_PRO_NS: "{{.NS}}" - - cli:build:setup-cache: - desc: setup cache for CLI builds - deps: - - cli:build:dev - cmds: - - task: cli:build:teardown-cache - - mkdir -p "${TMPDIR:-/tmp/}devsy-cache" - - cp dist/devsy-dev_linux_amd64_v1/devsy-linux-amd64 "${TMPDIR:-/tmp/}devsy-cache/devsy-linux-amd64" - - cli:build:teardown-cache: - desc: teardown cache for CLI builds - cmds: - - rm -rf "${TMPDIR:-/tmp/}devsy-cache" - - cli:build:grpc: - desc: build devsy gRPC code - dir: pkg/agent/tunnel - cmd: | - # sudo apt install protobuf-compiler - # protoc invokes protoc-gen-go and protoc-gen-go-grpc from PATH, so install the plugins to GOBIN first. - go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.6.2 - go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.11 - export PATH="$(go env GOPATH)/bin:$PATH" - protoc -I . tunnel.proto --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative - - cli:test: - desc: run devsy unit tests - cmd: | - set -euo pipefail - packages="$(go run ./hack/unit_test_packages)" - go test -race -coverprofile=dist/profile.out -covermode=atomic $packages - - cli:test:e2e:build: - desc: build devsy for e2e tests - cmds: - - task: cli:build:dev - - mkdir -p e2e/bin - - cp dist/devsy-dev_linux_amd64_v1/devsy-linux-amd64 e2e/bin/devsy-linux-amd64 - - | - host_os="$(go env GOOS)" - host_arch="$(go env GOARCH)" - host_binary="devsy-${host_os}-${host_arch}" - if [ "$host_os" = "windows" ]; then - host_binary="${host_binary}.exe" - fi - host_dir="" - for candidate in dist/devsy-dev_${host_os}_${host_arch}_*; do - if [ -d "$candidate" ]; then - if [ -n "$host_dir" ]; then - echo "multiple host build directories match ${host_os}/${host_arch}" >&2 - exit 1 - fi - host_dir="$candidate" - fi - done - test -n "$host_dir" - test -f "${host_dir}/${host_binary}" - cp "${host_dir}/${host_binary}" "e2e/bin/${host_binary}" - - cli:test:e2e: - desc: run e2e tests - deps: - - cli:test:e2e:build - dir: e2e - cmd: go tool ginkgo - - cli:test:e2e:suite: - # usage: task cli:test:e2e:suite -- "test suite name" - desc: run e2e tests suite - deps: - - cli:test:e2e:build - dir: e2e - cmd: go tool ginkgo --label-filter {{ .CLI_ARGS }} - - cli:test:e2e:focus: - # usage: task cli:test:e2e:focus -- "test suite pattern" - desc: run focused e2e tests - deps: - - cli:test:e2e:build - dir: e2e - cmd: go tool ginkgo --focus {{ .CLI_ARGS }} - - cli:test:e2e:kind:setup: - desc: setup kind cluster for e2e tests - cmd: | - kind_version="$(kind version -q)" - kind_version="${kind_version#v}" - kind_major="${kind_version%%.*}" - kind_minor_patch="${kind_version#*.}" - kind_minor="${kind_minor_patch%%.*}" - kind_patch="${kind_minor_patch#*.}" - kind_version_valid=true - case "$kind_version" in - *.*.*) ;; - *) kind_version_valid=false ;; - esac - case "$kind_major" in - ''|*[!0-9]*) kind_version_valid=false ;; - esac - case "$kind_minor" in - ''|*[!0-9]*) kind_version_valid=false ;; - esac - case "$kind_patch" in - ''|*[!0-9]*) kind_version_valid=false ;; - esac - if [ "$kind_version_valid" != true ]; then - echo "kind v0.33.0 or newer is required for Kubernetes v1.36.4 (found $kind_version)" >&2 - exit 1 - fi - case "$kind_major" in - 0) - if [ "$kind_minor" -lt 33 ]; then - echo "kind v0.33.0 or newer is required for Kubernetes v1.36.4 (found $kind_version)" >&2 - exit 1 - fi - ;; - [1-9]|[1-9][0-9]*) ;; - *) - echo "kind v0.33.0 or newer is required for Kubernetes v1.36.4 (found $kind_version)" >&2 - exit 1 - ;; - esac - kind create cluster --image kindest/node:v1.36.4@sha256:099e049362a1526b2db71494e1947aae99bd16290d7c895f2b7ea312e3cbfaed - - cli:test:e2e:kind:teardown: - desc: teardown kind cluster for e2e tests - cmd: kind delete cluster - - cli:test:e2e:ginkgo:install: - desc: install ginkgo for e2e tests - env: - GOPROXY: direct - status: [command -v ginkgo >/dev/null 2>&1] - cmd: go install github.com/onsi/ginkgo/v2/ginkgo - - cli:test:e2e:act:focus: - # usage: task cli:test:e2e:act:focus -- "test focus pattern" - desc: run e2e tests using act with focus - cmd: act workflow_dispatch -W .github/workflows/act.yml -j e2e-test --input test_focus={{ .CLI_ARGS }} - - desktop:deps: - desc: install Linux desktop runtime dependencies for Electron and Playwright - cmds: - - cmd: sudo apt-get update - - cmd: >- - sudo apt-get install -y - libglib2.0-0 libnspr4 libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 libxkbcommon0 - libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2t64 libpango-1.0-0 - libcairo2 libxshmfence1 libgtk-3-0 libxss1 libatspi2.0-0 libnotify4 libxtst6 xdg-utils - libuuid1 xvfb - - desktop:setup: - desc: setup Electron desktop application - dir: desktop - deps: - - desktop:deps - cmds: - - task: cli:build:dev - - cmd: mkdir -p resources/bin - - cmd: cp ../dist/devsy-dev_linux_amd64_v1/devsy-linux-amd64 ./resources/bin/devsy - - cmd: chmod +x ./resources/bin/devsy - - cmd: npm ci - - desktop:dev: - desc: run desktop application in dev mode - dir: desktop - cmd: npm run electron:dev - - desktop:build: - desc: build desktop application - dir: desktop - cmds: - - cmd: npm ci - - task: desktop:check - - cmd: npm run build - - desktop:check: - desc: check desktop application - dir: desktop - cmds: - - cmd: npm run check - - cmd: npm run lint:check - - desktop:test: - desc: run desktop unit tests - dir: desktop - cmd: npm run test - - desktop:test:e2e: - desc: run desktop e2e tests - deps: - - desktop:deps - dir: desktop - cmd: | - export DISPLAY=:99 - if [ ! -f /tmp/.X99-lock ]; then - Xvfb :99 -screen 0 1280x720x24 >/tmp/devsy-xvfb.log 2>&1 & - # Wait for Xvfb to be ready (max 10 seconds) - for i in $(seq 1 50); do - if [ -f /tmp/.X99-lock ]; then - break - fi - sleep 0.2 - done - fi - npm run test:e2e - - desktop:act:build:ui: - desc: build desktop ui using act - cmd: act workflow_dispatch -W .github/workflows/act.yml -j build-ui - - desktop:act:build:app: - desc: build desktop application using act - cmd: act workflow_dispatch -W .github/workflows/act.yml -j build-desktop - - desktop:act:build:flatpak: - desc: build desktop flatpak using act - cmd: act workflow_dispatch -W .github/workflows/act.yml -j build-flatpak - - github:dev-release:upload: - desc: upload dev binaries to GitHub release tag v0.0.0-10 for testing - cmds: - - cmd: | - TMP_DIR="$(mktemp -d)" - cp dist/devsy-dev_linux_amd64_v1/devsy-linux-amd64 "$TMP_DIR/devsy-linux-amd64" - gh release upload v0.0.0-10 dist/devsy-dev_linux_amd64_v1/devsy-linux-amd64 --repo devsy-org/devsy --clobber - rm -rf "$TMP_DIR" diff --git a/e2e/README.md b/e2e/README.md index 1c259bbbd2..1ed95b0591 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -5,30 +5,30 @@ commands below from the repository root. ## Prerequisites -- Go and [Task](https://taskfile.dev) +- Go and [mise](https://mise.jdx.dev) - Docker, for the Docker-based suites - [kind](https://kind.sigs.k8s.io/) v0.33.0 or newer, for Kubernetes suites -The `task` commands run Ginkgo through `go tool ginkgo`, which uses the version +The `mise run` tasks run Ginkgo through `go tool ginkgo`, which uses the version pinned in `go.mod`. To install a `ginkgo` binary on your `PATH`, run -`task cli:test:e2e:ginkgo:install`. +`mise run cli:test:e2e:ginkgo:install`. ## Build -`task cli:test:e2e:build` builds Devsy and copies the Linux amd64 and host +`mise run cli:test:e2e:build` builds Devsy and copies the Linux amd64 and host binaries into `e2e/bin/`. The run tasks below do this automatically. ## Run ```bash # all suites -task cli:test:e2e +mise run cli:test:e2e # suites selected by label -task cli:test:e2e:suite -- up-docker-compose +mise run cli:test:e2e:suite up-docker-compose # specs selected by name pattern -task cli:test:e2e:focus -- "pattern" +mise run cli:test:e2e:focus "pattern" ``` `cli:test:e2e:act:focus` runs a focused pattern through [act](https://github.com/nektos/act). @@ -40,13 +40,13 @@ checks the kind version and creates a cluster from `kindest/node:v1.36.4@sha256:099e049362a1526b2db71494e1947aae99bd16290d7c895f2b7ea312e3cbfaed`: ```bash -task cli:test:e2e:kind:setup +mise run cli:test:e2e:kind:setup ``` Remove the cluster afterwards: ```bash -task cli:test:e2e:kind:teardown +mise run cli:test:e2e:kind:teardown ``` #### CI helpers diff --git a/hack/ci/agent-skill-evaluation.md b/hack/ci/agent-skill-evaluation.md index 6c26b9e168..6ed4a40a73 100644 --- a/hack/ci/agent-skill-evaluation.md +++ b/hack/ci/agent-skill-evaluation.md @@ -1,6 +1,6 @@ # Devsy skill behavioral evaluation -`task agent-skill:validate` checks the skill's specification conformance, installer discovery, and installed copies for Codex and Claude Code. It does not test agent behavior, so run this evaluation when the skill changes. +`mise run agent-skill:validate` checks the skill's specification conformance, installer discovery, and installed copies for Codex and Claude Code. It does not test agent behavior, so run this evaluation when the skill changes. ## Procedure diff --git a/hack/licenses/main.go b/hack/licenses/main.go index 7fcb32a63d..0217c2ca4a 100644 --- a/hack/licenses/main.go +++ b/hack/licenses/main.go @@ -97,7 +97,7 @@ func checkInSync(hackDir, outFile string, deps []byte) error { _ = diff.Run() fmt.Fprintln( os.Stderr, - "warning: THIRD_PARTY_LICENSES.md is out of date; run 'task cli:licenses' and commit the result", + "warning: THIRD_PARTY_LICENSES.md is out of date; run 'mise run cli:licenses' and commit the result", ) return nil } diff --git a/hack/licenses/third-party-licenses.md.tmpl b/hack/licenses/third-party-licenses.md.tmpl index f88458523f..44fe47217e 100644 --- a/hack/licenses/third-party-licenses.md.tmpl +++ b/hack/licenses/third-party-licenses.md.tmpl @@ -6,7 +6,7 @@ {{ end -}} {{- end -}} - + # Third-Party Licenses @@ -14,7 +14,7 @@ The Devsy CLI is built with the open-source Go modules listed below. Each entry links to the module and notes the license it is distributed under. Some dependencies are only included on certain operating systems or architectures. -To regenerate this file after changing dependencies, run `task cli:licenses`. +To regenerate this file after changing dependencies, run `mise run cli:licenses`. ## Dependencies diff --git a/mise.lock b/mise.lock index 19ea81842d..bc403dc5c6 100644 --- a/mise.lock +++ b/mise.lock @@ -93,18 +93,3 @@ url_api = "https://api.github.com/repos/protocolbuffers/protobuf/releases/assets checksum = "sha256:de56d57afe30c5d191b11d24ff93dd4025728d7fb43b773886b2d3613e0bdbb2" url = "https://github.com/protocolbuffers/protobuf/releases/download/v36.1/protoc-36.1-osx-aarch_64.zip" url_api = "https://api.github.com/repos/protocolbuffers/protobuf/releases/assets/538583189" - -[[tools.task]] -version = "3.53.1" -backend = "aqua:go-task/task" -specifiers = ["3.53.1"] - -[tools.task."platforms.linux-x64"] -checksum = "sha256:a54a408f6861ff921f6e87774180db31bacd8c1e7c944ca696db9fea49a82fc7" -url = "https://github.com/go-task/task/releases/download/v3.53.1/task_linux_amd64.tar.gz" -url_api = "https://api.github.com/repos/go-task/task/releases/assets/519645449" - -[tools.task."platforms.macos-arm64"] -checksum = "sha256:85d2d96c2380b33d7855b07b3f7a20dc7ca0eda999a26efa0fb5f6f32b366cd7" -url = "https://github.com/go-task/task/releases/download/v3.53.1/task_darwin_arm64.tar.gz" -url_api = "https://api.github.com/repos/go-task/task/releases/assets/519645491" diff --git a/mise.toml b/mise.toml index 936bca3b76..f521d0415a 100644 --- a/mise.toml +++ b/mise.toml @@ -9,7 +9,6 @@ locked = true [tools] go = "1.26.9" node = "24" -task = "3.53.1" golangci-lint = "2.13.2" prek = "0.5.3" protoc = "36.1" @@ -29,3 +28,292 @@ npm ci run = ''' prek install ''' + +[tasks."agent-skill:validate"] +description = "validate the end-user Devsy skill and installer discovery (requires Node 22.20+ and Python 3.11+)" +run = "go run ./hack/validate_agent_skill" + +[tasks."cli:tidy"] +description = "tidy go.mod and go.sum" +run = "go mod tidy" + +[tasks."cli:licenses"] +description = "regenerate THIRD_PARTY_LICENSES.md and enforce the license allowlist" +run = "go run ./hack/licenses" + +[tasks."cli:licenses:check"] +description = "verify THIRD_PARTY_LICENSES.md is in sync and all licenses are allowed (CI)" +run = "go run ./hack/licenses --check" + +[tasks."cli:lint"] +description = "lint go code using golangci-lint" +run = "golangci-lint run ./..." + +[tasks."cli:lint:ci"] +description = "lint using golangci-lint with CI parity" +run = ''' +golangci-lint config verify +git fetch --quiet origin main +patch="$(mktemp)" +trap 'rm -f "$patch"' EXIT +git diff "$(git merge-base HEAD origin/main)" > "$patch" +golangci-lint run --new-from-patch="$patch" --new=false ./... +''' + +[tasks."cli:lint:fix"] +description = "fix lint issues using golangci-lint" +run = "golangci-lint run --fix ./..." + +[tasks."cli:format"] +description = "format go code using golangci-lint formatters" +run = "golangci-lint fmt ./..." + +[tasks."cli:act:lint"] +description = "run devsy linters using act" +run = "act workflow_dispatch -W .github/workflows/lint.yml" + +[tasks."cli:build"] +description = "build devsy CLI" +env = { GITHUB_REPOSITORY_OWNER = "devsy-org" } +run = "go tool goreleaser build --id devsy --snapshot --clean" + +[tasks."cli:build:dev"] +description = "build devsy CLI for development" +env = { GITHUB_REPOSITORY_OWNER = "devsy-org", DEVSY_CLI_VERSION = "v0.0.0" } +run = "go tool goreleaser build --id devsy-dev --snapshot --clean" + +[tasks."cli:build:dev:pro"] +description = "build devsy CLI for pro feature (namespace from NS, default: default)" +env = { GITHUB_REPOSITORY_OWNER = "devsy-org" } +run = 'DEVSY_PRO_NS="${NS:-default}" go tool goreleaser build --id devsy-pro-dev --snapshot --clean' + +[tasks."cli:build:setup-cache"] +description = "setup cache for CLI builds" +depends = ["cli:build:dev"] +run = [ + { task = "cli:build:teardown-cache" }, + 'mkdir -p "${TMPDIR:-/tmp/}devsy-cache"', + 'cp dist/devsy-dev_linux_amd64_v1/devsy-linux-amd64 "${TMPDIR:-/tmp/}devsy-cache/devsy-linux-amd64"', +] + +[tasks."cli:build:teardown-cache"] +description = "teardown cache for CLI builds" +run = 'rm -rf "${TMPDIR:-/tmp/}devsy-cache"' + +[tasks."cli:build:grpc"] +description = "build devsy gRPC code" +dir = "pkg/agent/tunnel" +run = ''' +# protoc invokes protoc-gen-go and protoc-gen-go-grpc from PATH, so install the plugins to GOBIN first. +go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.6.2 +go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.11 +export PATH="$(go env GOPATH)/bin:$PATH" +protoc -I . tunnel.proto --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative +''' + +[tasks."cli:test"] +description = "run devsy unit tests" +shell = "bash -c" +run = ''' +set -euo pipefail +packages="$(go run ./hack/unit_test_packages)" +go test -race -coverprofile=dist/profile.out -covermode=atomic $packages +''' + +[tasks."cli:test:e2e:build"] +description = "build devsy for e2e tests" +run = [ + { task = "cli:build:dev" }, + "mkdir -p e2e/bin", + "cp dist/devsy-dev_linux_amd64_v1/devsy-linux-amd64 e2e/bin/devsy-linux-amd64", + ''' +host_os="$(go env GOOS)" +host_arch="$(go env GOARCH)" +host_binary="devsy-${host_os}-${host_arch}" +if [ "$host_os" = "windows" ]; then + host_binary="${host_binary}.exe" +fi +host_dir="" +for candidate in dist/devsy-dev_${host_os}_${host_arch}_*; do + if [ -d "$candidate" ]; then + if [ -n "$host_dir" ]; then + echo "multiple host build directories match ${host_os}/${host_arch}" >&2 + exit 1 + fi + host_dir="$candidate" + fi +done +test -n "$host_dir" +test -f "${host_dir}/${host_binary}" +cp "${host_dir}/${host_binary}" "e2e/bin/${host_binary}" +''', +] + +[tasks."cli:test:e2e"] +description = "run e2e tests" +depends = ["cli:test:e2e:build"] +dir = "e2e" +run = "go tool ginkgo" + +[tasks."cli:test:e2e:suite"] +description = "run e2e tests suite (usage: mise run cli:test:e2e:suite