{"id":20150712,"url":"https://github.com/luhring/funky","last_synced_at":"2026-06-12T07:32:45.796Z","repository":{"id":57623191,"uuid":"393939775","full_name":"luhring/funky","owner":"luhring","description":"A Go (golang) linter that finds mutations.","archived":false,"fork":false,"pushed_at":"2021-08-21T12:57:58.000Z","size":40,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-03T01:15:01.115Z","etag":null,"topics":["ast","functional-programming","golang","linter","mutations"],"latest_commit_sha":null,"homepage":"","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/luhring.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-08T11:19:12.000Z","updated_at":"2022-10-19T19:39:12.000Z","dependencies_parsed_at":"2022-08-26T23:51:43.052Z","dependency_job_id":null,"html_url":"https://github.com/luhring/funky","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/luhring/funky","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luhring%2Ffunky","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luhring%2Ffunky/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luhring%2Ffunky/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luhring%2Ffunky/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/luhring","download_url":"https://codeload.github.com/luhring/funky/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luhring%2Ffunky/sbom","scorecard":{"id":603325,"data":{"date":"2025-08-11","repo":{"name":"github.com/luhring/funky","commit":"5c65953372f51441a769a21fafad5c7656ddccfe"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Code-Review","score":0,"reason":"Found 0/8 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-21T00:57:57.775Z","repository_id":57623191,"created_at":"2025-08-21T00:57:57.776Z","updated_at":"2025-08-21T00:57:57.776Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34234557,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["ast","functional-programming","golang","linter","mutations"],"created_at":"2024-11-13T22:53:05.647Z","updated_at":"2026-06-12T07:32:45.778Z","avatar_url":"https://github.com/luhring.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# funky 🎸\n\nA Go (golang) linter that finds mutations.\n\n## Installation\n\n```\ngo install github.com/luhring/funky/cmd/funky@main\n```\n\n## Usage\n\n```\nfunky ./directory-with-go-files\n```\n\n(**Note:** Funky doesn't yet analyze directories _recursively_. 😳)\n\n### Example output\n\n```\nadd.go:134:3: mutation: \"destfi\" was assigned a new value: nil\nadd.go:155:5: mutation: \"d\" was assigned a new value: filepath.Join(dest, path.Base(url.Path))\nadd.go:157:7: mutation: \"err\" was assigned a new value: addURL(d, src, hostOwner, options.Hasher)\nadd.go:175:4: mutation: \"err\" was assigned a new value: os.Stat(esrc)\n```\n\n## What is a \"mutation\"?\n\nA mutation is when a variable's value changes. In the Go language, this means an assignment of a value to a variable anywhere **other than** where that variable is declared.\n\nFor example, here's some Go code that has a few mutations:\n\n```go\npackage main\n\nvar x = 1 // Not a mutation. This is where `x` is declared.\n\nfunc main() {\n    x = 7 // MUTATION! (... of `x`, which is declared as a package-level variable.)\n\n    var output string // Not a mutation. This is where `output` is declared, and it's implicitly being assigned the zero-value of the `string` type, which is \"\".\n\n    if someCondition {\n    \toutput = \"new value\" // MUTATION!\n    }\n\n    print(output)\n}\n```\n\n\n## The mission: functional programming for Go\n\nFunky's objective is to take the approaches of functional programming and apply them to the Go language.\n\nThe first task is to alert developers to the presence of **mutations**.\n\nMutations introduce complexity in code. Because of this, they make code more likely to introduce bugs and more difficult to comprehend. Funky alerts you to the mutations in your code so you can spot opportunities for making your code less complex and more predictable — presumably, by adjusting your implementation to avoid mutations.\n\n### \"...but Go isn't a functional programming language\"\n\nThat's true (to some extent). But more developers are realizing the benefits of applying coding practices _taken from the functional paradigm_ to more languages than just the esoteric FP languages.\n\n## Roadmap\n\n- [ ] support for recursive directory analysis (e.g. `./...`)\n- [ ] CI pipeline\n- [ ] release pipeline\n- [ ] **feature:** avoiding mutations\n  - [x] mutation detection\n  - [ ] failure on mutation detection\n  - [ ] configurable exceptions to mutation detection-based failing\n- [ ] **feature:** avoiding side effects\n  - [ ] side effect detection\n  - [ ] failure on side effect detection\n  - [ ] configurable exceptions to side effect detection-based failing\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluhring%2Ffunky","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fluhring%2Ffunky","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluhring%2Ffunky/lists"}