{"id":21216043,"url":"https://github.com/krystal/go-runner","last_synced_at":"2025-07-10T11:32:06.388Z","repository":{"id":40386333,"uuid":"489348786","full_name":"krystal/go-runner","owner":"krystal","description":"Go package exposing a simple interface for executing commands, enabling easy mocking and wrapping of executed commands.","archived":false,"fork":false,"pushed_at":"2023-10-13T12:48:58.000Z","size":52,"stargazers_count":10,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-05T13:02:48.091Z","etag":null,"topics":["exec","execution","go","golang","testing"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/krystal/go-runner","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/krystal.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-06T12:37:40.000Z","updated_at":"2025-03-14T19:55:19.000Z","dependencies_parsed_at":"2024-06-21T15:36:10.699Z","dependency_job_id":null,"html_url":"https://github.com/krystal/go-runner","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/krystal/go-runner","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krystal%2Fgo-runner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krystal%2Fgo-runner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krystal%2Fgo-runner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krystal%2Fgo-runner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/krystal","download_url":"https://codeload.github.com/krystal/go-runner/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krystal%2Fgo-runner/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264573077,"owners_count":23630411,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["exec","execution","go","golang","testing"],"created_at":"2024-11-20T21:49:22.488Z","updated_at":"2025-07-10T11:32:06.161Z","avatar_url":"https://github.com/krystal.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  go-runner\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003e\n    Go package exposing a simple interface for executing commands, enabling easy\n    mocking and wrapping of executed commands.\n  \u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://pkg.go.dev/github.com/krystal/go-runner\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/%E2%80%8B-reference-387b97.svg?logo=go\u0026logoColor=white\"\n  alt=\"Go Reference\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/krystal/go-runner/releases\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/v/tag/krystal/go-runner?label=release\" alt=\"GitHub tag (latest SemVer)\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/krystal/go-runner/actions\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/actions/workflow/status/krystal/go-runner/ci.yml?logo=github\" alt=\"Actions Status\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://codeclimate.com/github/krystal/go-runner\"\u003e\n    \u003cimg src=\"https://img.shields.io/codeclimate/coverage/krystal/go-runner.svg?logo=code%20climate\" alt=\"Coverage\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/krystal/go-runner/commits/main\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/last-commit/krystal/go-runner.svg?style=flat\u0026logo=github\u0026logoColor=white\"\nalt=\"GitHub last commit\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/krystal/go-runner/issues\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/issues-raw/krystal/go-runner.svg?style=flat\u0026logo=github\u0026logoColor=white\"\nalt=\"GitHub issues\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/krystal/go-runner/pulls\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/issues-pr-raw/krystal/go-runner.svg?style=flat\u0026logo=github\u0026logoColor=white\" alt=\"GitHub pull requests\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/krystal/go-runner/blob/master/LICENSE\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/license/krystal/go-runner.svg?style=flat\" alt=\"License Status\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nThe Runner interface is basic and minimal, but it is sufficient for most use\ncases. This makes it easy to mock Runner for testing purposes.\n\nIt's also easy to create wrapper runners which modify commands before executing\nthem. The `Sudo` struct is a simple example of this.\n\n## Import\n\n```go\nimport \"github.com/krystal/go-runner\"\n```\n\n## Interface\n\n```go\ntype Runner interface {\n\tRun(\n\t\tstdin io.Reader,\n\t\tstdout, stderr io.Writer,\n\t\tcommand string,\n\t\targs ...string,\n\t) error\n\tRunContext(\n\t\tctx context.Context,\n\t\tstdin io.Reader,\n\t\tstdout, stderr io.Writer,\n\t\tcommand string,\n\t\targs ...string,\n\t) error\n\tEnv(env ...string)\n}\n```\n\n## Usage\n\nBasic:\n\n```go\nvar stdout bytes.Buffer\n\nr := runner.New()\n_ = r.Run(nil, \u0026stdout, nil, \"echo\", \"Hello world!\")\n\nfmt.Print(stdout.String())\n```\n\n```\nHello world!\n```\n\nEnvironment:\n\n```go\nvar stdout bytes.Buffer\n\nr := runner.New()\nr.Env(\"USER=johndoe\", \"HOME=/home/johnny\")\n_ = r.Run(nil, \u0026stdout, nil, \"sh\", \"-c\", `echo \"Hi, ${USER} (${HOME})\"`)\n\nfmt.Print(stdout.String())\n```\n\n```\nHi, johndoe (/home/johnny)\n```\n\nStdin, Stdout, and Stderr:\n\n```go\nstdin := bytes.NewBufferString(\"Hello world!\")\nvar stdout, stderr bytes.Buffer\n\nr := runner.New()\nerr := r.Run(\n\tstdin, \u0026stdout, \u0026stderr,\n\t\"sh\", \"-c\", \"cat; echo 'Oh noes! :(' \u003e\u00262\",\n)\nif err != nil {\n\tfmt.Println(err)\n}\n\nfmt.Print(stderr.String())\nfmt.Print(stdout.String())\n```\n\n```\nOh noes! :(\nHello world!\n```\n\nFailure:\n\n```go\nvar stdout, stderr bytes.Buffer\n\nr := runner.New()\nerr := r.Run(\n\tnil, \u0026stdout, \u0026stderr,\n\t\"sh\", \"-c\", \"echo 'Hello world!'; echo 'Oh noes! :(' \u003e\u00262; exit 3\",\n)\nif err != nil {\n\tfmt.Printf(\"%s: %s\", err.Error(), stderr.String())\n}\n```\n\n```\nexit status 3: Oh noes! :(\n```\n\nContext:\n\n```go\nvar stdout bytes.Buffer\n\nctx, cancel := context.WithTimeout(\n\tcontext.Background(), 1*time.Second,\n)\ndefer cancel()\n\nr := runner.New()\nerr := r.RunContext(\n\tctx, nil, \u0026stdout, nil,\n\t\"sh\", \"-c\", \"sleep 0.5 \u0026\u0026 echo 'Hello world!'\",\n)\nif err != nil {\n\tfmt.Println(err)\n}\n\nfmt.Print(stdout.String())\n```\n\n```\nHello world!\n```\n\nSudo (requires `NOPASS` in sudoers file):\n\n```go\nvar stdout bytes.Buffer\nr := runner.New()\n\nsudo := \u0026runner.Sudo{Runner: r}\n_ = sudo.Run(nil, \u0026stdout, nil, \"whoami\")\n\nsudo.User = \"web\"\n_ = sudo.Run(nil, \u0026stdout, nil, \"whoami\")\n\nfmt.Print(stdout.String())\n```\n\n```\nroot\nweb\n```\n\n## Documentation\n\nPlease see the\n[Go Reference](https://pkg.go.dev/github.com/krystal/go-runner#section-documentation)\nfor documentation and examples.\n\n## License\n\n[MIT](https://github.com/krystal/go-runner/blob/main/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrystal%2Fgo-runner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkrystal%2Fgo-runner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrystal%2Fgo-runner/lists"}