Automate releasing with Github Actions

Cover

March 28, 2022

Are you a lazy human like me? Great because then this is for you.

XClicker has existed for some time now and everytime I would create a new release, I would go through the same flow:

    0.
  1. Change the version in the makefile
  2. 1.
  3. Update version in packages and code with
    make version
  4. 2.
  5. Push to Github
  6. 3.
  7. Create new release
  8. 4.
  9. Build AppImage and deb package.
  10. 5.
  11. Upload assets.

Being tired of doing the same procedure for every release and needing to build for other architectures, I created a workflow to do everything for me.

Before creating the release workflow, let's explain what the h*ll Github actions, workflows, and CI/CD is, and how to use them. (If you feel very big brain you can scroll straight to

Creating releases with Github Actions
)

What is CI/CD?

CI/CD stands for Continuous Integration/Continuous Delivery. The XClicker workflow used a mix of both since the code gets compiled automatically (CI) and released (CD). Basically CI/CD is for automating tasks, and a workflow is the work CI/CD should do.

CI/CD is very often used for automating unit tests (ex. jest, cargo). An example is this rust workflow that builds, runs, and tests check code formatting every time a push to master happens, or when a pull request is opened.

1name: Rust 2 3on: 4 push: 5 branches: [ master ] 6 pull_request: 7 branches: [ master ] 8 9env: 10 CARGO_TERM_COLOR: always 11 12jobs: 13 build: 14 15 runs-on: ubuntu-latest 16 17 steps: 18 - uses: actions/checkout@v2 19 - name: Build 20 run: cargo build --verbose 21 - name: Test command 22 run: cargo run -- -c "echo test" 23 - name: Run tests 24 run: cargo test 25 - name: Clippy 26 run: cargo clippy --workspace -- -D warnings

Using CI/CD

Github provides a very epic way of automating your workflows with Github Actions. There are also CI/CD pipelines for other services like Azure Repos.

Let's create an incredibly simple rust application with some tests and a workflow.

1➜ cargo new rust-simple-workflow

Create a function called calculate_difficult_math like this and use it in the main function.

1fn calculate_difficult_math(a: i32, b: i32) -> i32 { 2 a + b 3} 4 5fn main() { 6 println!("Hello, world! {}", calculate_difficult_math(5, 5)); 7}

Now run the app and it should output something like this. Running app example

Now we can create a module called tests with a function called test_difficult_math.

1#[cfg(test)] 2mod tests { 3 // Importing all functions in the super scope 4 use super::*; 5 6 #[test] 7 fn test_difficult_math() { 8 // Panics if the left value is not equals to the right 9 assert_eq!(calculate_difficult_math(10, 5), 15); 10 } 11} 12

Tests

Full file

1fn calculate_difficult_math(a: i32, b: i32) -> i32 { 2 a + b 3} 4 5fn main() { 6 println!("Hello, world! {}", calculate_difficult_math(5, 5)); 7} 8 9#[cfg(test)] 10mod tests { 11 // Importing all functions in the super scope 12 use super::*; 13 14 #[test] 15 fn test_difficult_math() { 16 // Panics if the left value is not equals to the right 17 assert_eq!(calculate_difficult_math(10, 5), 15); 18 } 19}

Create a repository on Github with a readme, so it sets a main branch. Then press Actions and search Rust

/actions/new?category=none&query=Rust
. This is a simple way for getting started with a simple workflow template. Then click Configure .

Then press

Start commit
and
Commit new file
. Now the workflow is finished.

Now initialize a Github repository in rust-simple-workflow and push it to Github.

1git init 2git remote add origin https://github.com/username/repo 3git pull origin master # Or HEAD:main 4git add . 5git commit -m "Initial commit" 6git push origin master # Or HEAD:main

Now go to the Github repository and you will see a small yellow dot. Press this and then

Details
. Here you will be presented with everything that is going on in the workflow.

Hopefully, everything succeeded. And this is how to make a simple CI unit testing workflow.

Creating releases with Github Actions

Now to the fun part, let's create a workflow to automate releasing the rust project created before.

Open up the

.github/workflows/rust.yml
locally. Most stuff will be replaced here, but you can also create a new file called something along the lines of
release.yml
.

Here is the new content. The comments should describe what happens.

1# Everytime a new tag is created that starts with v, It will run this action 2on: 3 push: 4 tags: 5 - 'v*' 6 7name: Create Release 8 9env: 10 CARGO_TERM_COLOR: always 11 12jobs: 13 build: 14 runs-on: ubuntu-latest 15 16 steps: 17 - uses: actions/checkout@v3 18 19 # First check that tests succeed 20 - name: Run tests 21 run: cargo test --verbose 22 23 # Build it 24 - name: Build 25 run: cargo build --verbose --release 26 27 # Create a github release with automatic generated release notes 28 - name: Create Release 29 uses: softprops/action-gh-[email protected] 30 env: 31 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 with: 33 generate_release_notes: true 34 draft: false 35 prerelease: false 36 files: | 37 target/release/rust-simple-workflow

You can create a new tag that starts with v and push it now when you have this workflow.

1git tag v1.0.0 2git push origin --tags

Now go to the Github repository and you will see the yellow dot again. Click details and you will be presented with what happens. After a bit of time, you will see a new release is created by github-actions with the compiled asset. Now, this is just for the platform the ubuntu container is running, which in this case is amd64. If you would like to build it for other platforms you would have to look into cross or uraimo/run-on-arch-action (used for XClicker)


Thanks for reading and I hope you learned something new!

Copyright © 2024 Robiot. All rights reserved.Made without ♥ in Next.js ;) Source Code