├── .genignore ├── .github └── workflows │ └── main.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── bootstrap.sh ├── cargo-generate.toml └── src └── main.rs /.genignore: -------------------------------------------------------------------------------- 1 | # do not include instructions for generating project with generated project 2 | README.md 3 | # let generated projects generate their own lock file 4 | Cargo.lock 5 | # this file is only used for github repo templates contexts 6 | bootstrap.sh -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Main 2 | 3 | on: push 4 | 5 | jobs: 6 | codestyle: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Set up Rust 10 | uses: hecrj/setup-rust-action@v1 11 | with: 12 | components: rustfmt 13 | - uses: actions/checkout@v2 14 | - run: cargo fmt --all -- --check 15 | 16 | lint: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Set up Rust 20 | uses: hecrj/setup-rust-action@v1 21 | with: 22 | components: clippy 23 | - uses: actions/checkout@v2 24 | - run: cargo clippy --all-targets --all-features -- -D clippy::all 25 | 26 | compile: 27 | runs-on: ubuntu-latest 28 | steps: 29 | - name: Set up Rust 30 | uses: hecrj/setup-rust-action@v1 31 | - uses: actions/checkout@v2 32 | - run: cargo check --all 33 | 34 | test: 35 | needs: [codestyle, lint, compile] 36 | strategy: 37 | matrix: 38 | os: [ubuntu-latest, windows-latest, macOS-latest] 39 | rust: [stable, beta, nightly] 40 | runs-on: ${{ matrix.os }} 41 | 42 | steps: 43 | - name: Setup Rust 44 | uses: hecrj/setup-rust-action@v1 45 | with: 46 | rust-version: ${{ matrix.rust }} 47 | - name: Checkout 48 | uses: actions/checkout@v2 49 | - name: Test 50 | run: cargo test --verbose 51 | 52 | release: 53 | needs: [test] 54 | strategy: 55 | matrix: 56 | os: [ubuntu-latest, macOS-latest, windows-latest] 57 | include: 58 | - os: ubuntu-latest 59 | rust: stable 60 | target: x86_64-unknown-linux-musl 61 | bin: '{{project-name}}' 62 | name: '{{project-name}}-Linux-x86_64.tar.gz' 63 | - os: windows-latest 64 | rust: stable 65 | target: x86_64-pc-windows-msvc 66 | bin: '{{project-name}}.exe' 67 | name: '{{project-name}}-Windows-x86_64.zip' 68 | - os: macOS-latest 69 | rust: stable 70 | target: x86_64-apple-darwin 71 | bin: '{{project-name}}' 72 | name: '{{project-name}}-Darwin-x86_64.tar.gz' 73 | runs-on: ${{ matrix.os }} 74 | steps: 75 | - name: Setup Rust 76 | uses: hecrj/setup-rust-action@v1 77 | with: 78 | rust-version: ${{ matrix.rust }} 79 | targets: ${{ matrix.target }} 80 | - name: Setup musl-gcc 81 | if: contains(matrix.target, 'musl') 82 | run: | 83 | sudo apt-get install musl-tools 84 | - name: Checkout 85 | uses: actions/checkout@v2 86 | - name: Build 87 | run: cargo build --release --target ${{ matrix.target }} 88 | - name: Package 89 | shell: bash 90 | run: | 91 | strip target/${{ matrix.target }}/release/${{ matrix.bin }} 92 | cd target/${{ matrix.target }}/release 93 | if [[ "${{ matrix.os }}" == "windows-latest" ]] 94 | then 95 | 7z a ../../../${{ matrix.name }} ${{ matrix.bin }} 96 | else 97 | tar czvf ../../../${{ matrix.name }} ${{ matrix.bin }} 98 | fi 99 | cd - 100 | - name: Publish 101 | uses: softprops/action-gh-release@v1 102 | if: startsWith(github.ref, 'refs/tags/') 103 | with: 104 | files: '{{project-name}}*' 105 | env: 106 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 107 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "rust-bin" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "{{project-name}}" 3 | version = "0.1.0" 4 | authors = ["{{authors}}"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 🗑️ 3 |
4 |

5 | rust bin 6 |

7 | 8 |
9 | A recipe for Rust bins built, tested, and published with GitHub Actions. 10 |
11 | 12 |
13 | 14 | > **⚠️ Note:** To use GitHub Actions, you must have access to the [GitHub Actions](https://github.com/features/actions) feature. GitHub Actions are currently only available in public beta. You can [apply for the GitHub Actions beta here](https://github.com/features/actions/signup/). 15 | 16 | ## Goals 17 | 18 | * ♻️ 🚚 Create a repeatable process for making it as easy as possible to get Rust binaries into the hands of people as early and often as possible 19 | 20 | As rewarding of a language as Rust is to program in, it means little if you don't **use it** to improve the lives of others with applications. 21 | 22 | * 👩‍🎤 Inspire others to think about increasing Rust's potential reach 23 | 24 | There are many ways we could make Rust more accessible to others. This is one way. I'm excited to see others. 25 | 26 | ## Non-Goals 27 | 28 | * 🚫 😵 Not be complete by default. 29 | 30 | Rust supports a very [wide array](https://forge.rust-lang.org/platform-support.html) of compilation targets. Including all of these by default will inevitably put more burden on common case people trying figuring out which binaries to download and be a burden on new Rustaceans writing application that want the simplest thing that could be possible work for the majority of cases. 31 | 32 | > **⚠️ Note:** If you need to support more cases, you can make changes to `.github/workflows/main.yml` 33 | 34 | ## How to use this repo 35 | 36 | This repository is meant to use as a template for new Rust projects intended to produce 37 | a binary for users to run. 38 | 39 | ### cargo generate 40 | 41 | This repository works well with the [`cargo generate`](https://github.com/ashleygwilliams/cargo-generate) plugin. 42 | 43 | You can install `cargo generate` with the following 44 | 45 | ```sh 46 | $ cargo install cargo-generate \ 47 | --features vendored-openssl 48 | ``` 49 | 50 | Then generate a new rust bin project with run the following providing a `--name` option with the name of the binary 51 | you want to generate 52 | 53 | ```sh 54 | $ cargo generate \ 55 | --git https://github.com/softprops/rust-bin.git \ 56 | --name my-awesome-rust-bin 57 | ``` 58 | 59 | 60 | [Create a new git repository](https://help.github.com/en/articles/create-a-repo) on GitHub.com 61 | 62 | In your generated project, complete the repository setup process and push to GitHub 63 | 64 | ```sh 65 | git add . 66 | git commit -m "init to winit" 67 | git remote add origin git@github.com:{you}/{my-awesome-rust-bin}.git 68 | git push -u origin master 69 | ``` 70 | 71 | ### GitHub repository template 72 | 73 | This repository is configured to be a GitHub repository template. 74 | 75 | > **⚠️ Note:** You can learn more about repository templates [here](https://help.github.com/en/articles/creating-a-repository-from-a-template) 76 | 77 | Simply click the `Use this template` button on this repository's GitHub page and follow the problems. 78 | 79 | Clone your new repository to your local computer and run the `./bootstrap.sh` script. This will update some cargo placeholders that `cargo generate` would fill in for you. Commit these and push the changes to GitHub. 80 | 81 | > **⚠️ Note:** You will likely also want to update the `README.md` file to reflect your new projects contents. 82 | 83 | ### Start the action 84 | 85 | Assumming you have already [applied for the GitHub Actions beta here](https://github.com/features/actions/signup/) and received 86 | your invite you should find GitHub already going to work for you on your first `push` by visiting 87 | 88 | ``` 89 | https://github.com/{you}/{my-awesome-rust-bin}/actions 90 | ``` 91 | 92 | > **⚠️ Note:** This may take a few seconds on the first push. GitHub will take a few seconds to register push events with your newly provided workflow. 93 | 94 | You'll find GitHub is doing the following for you 95 | 96 | * checking your codestyle with rustfmt 97 | * linting your code with clippy 98 | * doing a quick compile check 99 | * running tests against Rust channels `nightly`, `beta`, `stable` on `linux`, `osx`, and `windows` virtual hosts 100 | 101 | ### Releasing 102 | 103 | You'll notice this workflow ends with a publish step but does **not** actually publish anything yet. 104 | 105 | The reason why is that you typically only want to publish a release with a [git tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging). 106 | 107 | Let's try that. 108 | 109 | ```sh 110 | git tag -a v0.1.0 -m "initial release" 111 | git push origin v0.1.0 112 | ``` 113 | 114 | Visit `https://github.com/{you}/{my-awesome-rust-bin}/actions` once more and you should find another workflow run has started. This time the workflow will end with a publish step that will create a new GitHub release named after the tag. 115 | 116 | You can find your GitHub releases here. 117 | 118 | ``` 119 | https://github.com/{you}/{my-awesome-rust-bin}/releases 120 | ``` 121 | 122 | 🎁 You should find 3 assets attached to your GitHub release. One for `linux`, one for `OSX`, and one for `windows`. Download the one for the type of operating system you are using by clicking the link. 123 | 124 | Unpack the asset locally and run it... 125 | 126 | 🎉 Congradulations. You've just shipped your first release 🚀! Now you can share your awesome Rust binaries with all your friends. 127 | 128 | ⭐ You can also communicate with the world that your project is in a stable state by creating a `README.md` file adding a [workflow badge](https://help.github.com/en/articles/configuring-a-workflow#adding-a-workflow-status-badge-to-your-repository). 129 | 130 | ``` 131 | ![](https://github.com/actions/{you}/{my-awesome-rust-bin}/main/badge.svg) 132 | ``` 133 | 134 | > **⚠️ Note:** You can extend your GitHub workflow by editing the `.github/workflows/main.yml` file in your project. You can also create separate workflows for separate GitHub events. Learn more [here](https://help.github.com/en/categories/automating-your-workflow-with-github-actions). 135 | 136 | 137 | ## Resources 138 | 139 | * [setup-rust action](https://github.com/hecrj/setup-rust-action) 140 | * [gh-release action](https://github.com/softprops/action-gh-release) 141 | * [GitHub actions docs](https://help.github.com/en/categories/automating-your-workflow-with-github-actions) 142 | -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Note: This file should only be used in GitHub template contexts 4 | # it will not be included in cargo generate output 5 | 6 | set -e 7 | 8 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 9 | PROJECT_NAME=$(basename $DIR) 10 | AUTHORS="$(git config user.name) <$(git config user.email)>" 11 | 12 | replace() { 13 | sed "s/{{$1}}/$2/g" 14 | } 15 | 16 | cat "$DIR/Cargo.toml" \ 17 | | replace project-name "$PROJECT_NAME" \ 18 | | replace authors "$AUTHORS" \ 19 | > $DIR/Cargo.toml 20 | 21 | cat "$DIR/.github/workflows/main.yml" \ 22 | | sed "s/project-name/$PROJECT_NAME/g" \ 23 | > $DIR/Cargo.toml 24 | 25 | rm .genignore 2>/dev/null || true 26 | rm cargo-generate.toml 2>/dev/null || true -------------------------------------------------------------------------------- /cargo-generate.toml: -------------------------------------------------------------------------------- 1 | [template] 2 | exclude = ["bootstrap.sh", "README.md"] -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("Hello, world!"); 3 | } 4 | --------------------------------------------------------------------------------