{"id":13446217,"url":"https://github.com/cole-wilson/sailboat","last_synced_at":"2025-10-09T09:39:31.451Z","repository":{"id":54590404,"uuid":"320031850","full_name":"cole-wilson/sailboat","owner":"cole-wilson","description":"🐍 A quick and easy way to distribute your Python projects!","archived":false,"fork":false,"pushed_at":"2023-10-24T18:24:45.000Z","size":28857,"stargazers_count":163,"open_issues_count":2,"forks_count":6,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-08-23T09:59:54.357Z","etag":null,"topics":["build","developer-tools","distribute","package","packaging","pypi","python","python3","release","sail","sailboat","ship","tool","wizard"],"latest_commit_sha":null,"homepage":"https://cole-wilson.github.io/sailboat/","language":"Python","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/cole-wilson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-12-09T17:34:35.000Z","updated_at":"2025-07-04T13:28:29.000Z","dependencies_parsed_at":"2024-01-13T17:15:30.770Z","dependency_job_id":"a3a89b48-b1ac-47e5-8b7d-1f1ea9940900","html_url":"https://github.com/cole-wilson/sailboat","commit_stats":{"total_commits":10,"total_committers":1,"mean_commits":10.0,"dds":0.0,"last_synced_commit":"74b56bd7a49452503acedf0e82e7bb7ebf38f264"},"previous_names":[],"tags_count":126,"template":false,"template_full_name":null,"purl":"pkg:github/cole-wilson/sailboat","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cole-wilson%2Fsailboat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cole-wilson%2Fsailboat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cole-wilson%2Fsailboat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cole-wilson%2Fsailboat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cole-wilson","download_url":"https://codeload.github.com/cole-wilson/sailboat/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cole-wilson%2Fsailboat/sbom","scorecard":{"id":299292,"data":{"date":"2025-08-11","repo":{"name":"github.com/cole-wilson/sailboat","commit":"6cca304267f533bd0dba24795700e9759d919912"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.9,"checks":[{"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":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","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":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: dist/pypi/sailboat-0.26.2-py3-none-any.whl:1"],"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":"Security-Policy","score":4,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Warn: no linked content found","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/codeql-analysis.yml:1","Warn: no topLevel permission defined: .github/workflows/sailboat.yml:1","Info: no jobLevel write permissions found"],"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":"Code-Review","score":0,"reason":"Found 0/11 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":"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":"SAST","score":10,"reason":"SAST tool detected: CodeQL","details":["Info: SAST configuration detected: CodeQL","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":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/cole-wilson/sailboat/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/cole-wilson/sailboat/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/cole-wilson/sailboat/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:67: update your workflow using https://app.stepsecurity.io/secureworkflow/cole-wilson/sailboat/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/sailboat.yml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/cole-wilson/sailboat/sailboat.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/sailboat.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/cole-wilson/sailboat/sailboat.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/sailboat.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/cole-wilson/sailboat/sailboat.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/sailboat.yml:62: update your workflow using https://app.stepsecurity.io/secureworkflow/cole-wilson/sailboat/sailboat.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/sailboat.yml:42","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned","Info:   0 out of   1 pipCommand dependencies pinned"],"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":"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":"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"}},{"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":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"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":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v0.26.2 not signed: https://api.github.com/repos/cole-wilson/sailboat/releases/42920756","Warn: release artifact v0.26.1 not signed: https://api.github.com/repos/cole-wilson/sailboat/releases/42110837","Warn: release artifact v0.26.0 not signed: https://api.github.com/repos/cole-wilson/sailboat/releases/41980003","Warn: release artifact v0.25.5 not signed: https://api.github.com/repos/cole-wilson/sailboat/releases/41954610","Warn: release artifact v0.25.1 not signed: https://api.github.com/repos/cole-wilson/sailboat/releases/37764137","Warn: release artifact v0.26.2 does not have provenance: https://api.github.com/repos/cole-wilson/sailboat/releases/42920756","Warn: release artifact v0.26.1 does not have provenance: https://api.github.com/repos/cole-wilson/sailboat/releases/42110837","Warn: release artifact v0.26.0 does not have provenance: https://api.github.com/repos/cole-wilson/sailboat/releases/41980003","Warn: release artifact v0.25.5 does not have provenance: https://api.github.com/repos/cole-wilson/sailboat/releases/41954610","Warn: release artifact v0.25.1 does not have provenance: https://api.github.com/repos/cole-wilson/sailboat/releases/37764137"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}}]},"last_synced_at":"2025-08-17T20:16:00.379Z","repository_id":54590404,"created_at":"2025-08-17T20:16:00.379Z","updated_at":"2025-08-17T20:16:00.379Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279001118,"owners_count":26083022,"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","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"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":["build","developer-tools","distribute","package","packaging","pypi","python","python3","release","sail","sailboat","ship","tool","wizard"],"created_at":"2024-07-31T05:00:48.601Z","updated_at":"2025-10-09T09:39:31.409Z","avatar_url":"https://github.com/cole-wilson.png","language":"Python","funding_links":[],"categories":["Developer Utilities","Python"],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\u003cimg src=\"https://www.pinclipart.com/picdir/big/383-3832964_im-on-a-boat-stamp-sailboat-stencil-clipart.png\" width=\"70px\"\u003e\n\u003cbr\u003e\nsailboat\n\u003cbr\u003e\n\u003ca href=\"https://github.com/cole-wilson/sailboat\"\u003e\u003cimg alt=\"GitHub Repo stars\" src=\"https://img.shields.io/github/stars/cole-wilson/sailboat?style=social\"\u003e\u003c/a\u003e\n\u003ca href=\"https://twitter.com/intent/tweet?text=Wow:\u0026url=https%3A%2F%2Fgithub.com%2Fsole-wilson%2Fsailboat\"\u003e\u003cimg alt=\"Twitter\" src=\"https://img.shields.io/twitter/url?style=social\u0026url=https%3A%2F%2Fgithub.com%2Fsole-wilson%2Fsailboat\"\u003e\u003c/a\u003e\n\u003cbr\u003e\n\u003cimg alt=\"GitHub commit activity\" src=\"https://img.shields.io/github/commit-activity/m/cole-wilson/sailboat\"\u003e\n\u003cimg alt=\"GitHub Release Date\" src=\"https://img.shields.io/github/release-date/cole-wilson/sailboat?label=latest%20release\"\u003e\n\u003cimg alt=\"GitHub Workflow Status\" src=\"https://img.shields.io/github/workflow/status/cole-wilson/sailboat/Publish%20release%20files%20for%20Sailboat.\"\u003e\n\u003cimg alt=\"GitHub code size in bytes\" src=\"https://img.shields.io/github/languages/code-size/cole-wilson/sailboat\"\u003e\n\u003cimg alt=\"GitHub release (latest SemVer including pre-releases)\" src=\"https://img.shields.io/github/v/release/cole-wilson/sailboat?include_prereleases\"\u003e\n\u003cimg alt=\"GitHub\" src=\"https://img.shields.io/github/license/cole-wilson/sailboat\"\u003e\n\u003cimg alt=\"PyPI - Downloads\" src=\"https://img.shields.io/pypi/dm/sailboat\"\u003e\n\n\u003c/h1\u003e\n\n\u003ca style=\"display:inline-block;\" align=\"center\" href=\"https://cole-wilson.github.io/sailboat/\"\u003eView Documentation Site\u003c/a\u003e, \u003ca href=\"https://www.youtube.com/watch?v=zQQ3B5MDV0s\"\u003eView YouTube Demo\u003c/a\u003e\n\npresented at PyCon USA\n\n\u003e **Note:** While this program is still in early stages of development,\n\u003e it is suitable for use in production.\n\u003e If you have any problems/suggestions/questions please let me know in a GitHub Issue.\n\u003e This is my first big open-source project, so feel free to submit a pull-request!\n\u003e Thanks!\n\u003e \\- Cole Wilson\n\n## About\nSailboat is a Python developer's best friend. It's a Python build tool that can do anything you need it to! It suports a countless number of plugins — you can even [make your own](#plugins). Sailboat is made for anyone, whether you are a beginner on your very first project, or a senior software engineer with years of experience. \n\nLet's say that that you have created a basic game, **Guess My Number**, and you want to send it to all of your friends. There are a lot of different ways you can do this, but using Sailboat is the easiest. All you have to do is type three commands: `sail quickstart`, `sail build`, and `sail release`, and you can have a Homebrew file, a `pip` installable package, and a [PyInstaller](https://www.pyinstaller.org/) desktop app. So easy!\n\nSailboat also supports custom subcommands. These don't build your project, but they can add features such as a todo list that help speed up your development process.\n\n## Installation\n### Pip:\n```bash\npip3 install sailboat\n```\n### Binary:\nDownload from [latest release](https://github.com/cole-wilson/sailboat/releases/latest).\n### Homebrew:\n```bash\nbrew install cole-wilson/taps/Sailboat\n```\n### Build From Source:\n```bash\ngit clone https://github.com/cole-wilson/sailboat\ncd sailboat\npython3 setup.py install\n```\n## Usage:\nSailboat is intended to be used from the command line/terminal.\n\nIt is suggested to run `sail quickstart` to get started. Then, use `sail build` to build your project, and `sail release` to release it! Be sure to to look at the subcommand docs for more detail. \n*(look in table below)*\n\nThere are two base commands that can be used: `sail` and `sailboat`. These both do exactly the same thing, there is no difference. `sail` will be used in the documentation, as it's shorter easier to type, but you can do whatever.\n\nTo get a list of the availible subcommands type `sail help`.\nTo refresh the plugin list, type `sail -r`.\n\nThere are countless subcommands, but these are the core ones:\n\n|subcommand|description|\n|----------|-----------|\n|\tadd | Add a plugin to your project. |\n|\tbuild | Build your project for release. |\n|\tdev | Run your project without building it. |\n|\tgit | Manage git for your project. |\n|\tgithub | Manage git for your project. |\n|\tplugins | Plugin manager. |\n|\tquickstart | Get your project up and running. |\n|\trelease | Release your project. |\n|\tremove | Remove a plugin from you project. |\n|\twizard | Configure you project or a plugin. |\n|\tworkflow | Generate a GitHub actions workflow file. |\n|\thelp | Display this message. |\n\n## Plugins:\nSailboat uses a plugin based architecture. Every single command or subcommand is a plugin, even the core features. Plugins are registered using the [Python entry points system](https://amir.rachum.com/blog/2017/07/28/python-entry-points/), using the group name `sailboat_plugins`. There are four types of plugins:\n### `core`\nThis type of plugin is reserved for 1st party plugins - plugins that are part of the actual Sailboat source. They have unreserved access to all project data, and therefore this type should not be used in custom plugins.\n### `command`\n`command` plugins are most basic form of a plugin. They are called by typing `sail \u003cname of plugin\u003e`. They are standalone python scripts that add to the project, like a task list manager.\n### `build`\nThis is perhaps the most common type of plugin, they are run with the `build` core plugin, and are used to generate or edit project files. An example would be the PyInstaller plugin, which generates frozen binaries of the project. These should store output in the top level `dist` folder, in a subfolder with the name of the project. For example: the PyInstaller plugin saves output in `./dist/pyinstaller`. Build plugins can also contain `release` plugins within them.\n### `release`\nThis group of plugins is used by the `release` core plugin. They are used to distribute files. For example: the `homebrew` release plugin uploads the Homebrew formula to a GitHub repo.\n\nAll plugins should be a subclass of `sailboat.plugins.Plugin`, a basic class that provide the neccesary functions and registration features. An example `command` plugin might look like this:\n```python\nfrom sailboat.plugins import Plugin\n\nclass Echo(Plugin):\n\tdescription = \"A basic command plugin that echos it's input.\"\n\t_type = 'command'\n\tsetup = {\"string_to_echo\":\"What string should I echo? \"}  # Used by wizard\n    \n\tdef run(self):\n\t\tstring = self.getData('string_to_echo')  # Get string to echo.\n\t\tprint(string)\n\t\treturn\n```\nPlugins store their data in the `sailboat.toml` file, under their type namespace. For example, the above example will store it's data like so:\n```toml\n...\n[command.echo]\nstring_to_echo = \"Testing...\"\n...\n```\nA plugin should ***NEVER*** edit the `sailboat.toml` file on it's own. Instead plugins should use the provided functions OR edit `self.data`, a dictionary of the file. Only data stored in the plugins namespace will be preserved. However, a plugin can read from the top level data.\n\nPlugins can get very complex, and therefore useful, but it is too long to put here. Please look at the [`sailboat.colewilson.xyz/plugins.html`](//sailboat.colewilson.xyz/plugins.html) file for details.\n\n## Acknowledgements:\nThanks to all the people at PyInstaller, dmgbuild, twine, and GitHub actions who provided ways for me to create this. \n\n## Stargazers\n[![Stargazers repo roster for @cole-wilson/sailboat](https://reporoster.com/stars/cole-wilson/sailboat)](https://github.com/cole-wilson/sailboat/stargazers)\n\n\n## Contributors\n - Cole Wilson\n \n## Contact\nPlease submit an issue if you have any questions or need help or find a bug. I'm happy to help!\n\n\u003ccole@colewilson.xyz\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcole-wilson%2Fsailboat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcole-wilson%2Fsailboat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcole-wilson%2Fsailboat/lists"}