Using Fake With GitHub Actions
I have been working on an F# project that I will be sharing soon. One of the tasks that I have left is setting up CI/CD for the application. Since I am using F#, the natural choice is to leverage Fake. Fake is a build tool that leverages F# to write your build scripts. Getting started is easy, and I would recommend installing it as a local tool. I will walk you through all the steps of creating an empty F# project, configuring Fake, and making your GitHub Actions YAML file.
Creating your F# Project
Let’s create a new F# project using the .NET CLI.
$ dotnet new console -o fakegithubactions --language F#
The template "Console Application" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on fakegithubactions/fakegithubactions.fsproj...
Determining projects to restore...
Restored /home/phillipsj/code/fakegithubactions/fakegithubactions.fsproj (in 285 ms).
Restore succeeded.
Now let’s change into the directory and run a build to make sure everything is okay.
$ cd fakegithubactions && dotnet build
Microsoft (R) Build Engine version 16.7.0+7fb82e5b2 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.
Determining projects to restore...
All projects are up-to-date for restore.
fakegithubactions -> /home/phillipsj/code/fakegithubactions/bin/Debug/netcoreapp3.1/fakegithubactions.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:03.75
Adding Fake as a local tool
We are going to bootstrap Fake using the template that is provided. Make sure you are in the project directory then execute the following command. You will be asked a few questions, and I have included those in the output below.
$ dotnet new -i "fake-template::*" && dotnet new fake
The template "FAKE - Template" was created successfully.
Processing post-creation actions...
Template is configured to run the following action:
Description: Make scripts executable
Manual instructions: Run 'chmod +x *.sh'
Actual command: /bin/sh -c "chmod +x *.sh"
Do you want to run this action (Y|N)?
Y
Running command '/bin/sh -c "chmod +x *.sh"'...
Command succeeded.
Template is configured to run the following action:
Description: update to latest version
Manual instructions: Run 'dotnet tool update fake-cli'
Actual command: dotnet tool update fake-cli
Do you want to run this action (Y|N)?
Y
Running command 'dotnet tool update fake-cli'...
Command succeeded.
Now we have Fake installed as a local tool, let’s execute a build with Fake.
$ dotnet fake build
The last restore is still up to date. Nothing left to do.
run All
Building project with version: LocalBuild
Shortened DependencyGraph for Target All:
<== All
<== Build
<== Clean
The running order is:
Group - 1
- Clean
Group - 2
- Build
Group - 3
- All
Starting target 'Clean'
Finished (TagStatus.Success) 'Clean' in 00:00:00.0133164
Starting target 'Build'
Finished (TagStatus.Success) 'Build' in 00:00:00.0003516
Starting target 'All'
Finished (TagStatus.Success) 'All' in 00:00:00.0001141
---------------------------------------------------------------------
Build Time Report
---------------------------------------------------------------------
Target Duration
------ --------
Clean 00:00:00.0095657
Build 00:00:00.0002969
All 00:00:00.0000547
Total: 00:00:00.1599943
Status: Okay
---------------------------------------------------------------------
Performance:
- Cli parsing: 250 milliseconds
- Packages: 55 milliseconds
- Script analyzing: 15 milliseconds
- Script running: 316 milliseconds
- Script cleanup: 1 millisecond
- Runtime: 960 milliseconds
Great! We now have Fake installed, and we are using it to build our project. When you add this to source control, don’t forget to include the .config folder containing the local tool manifest file. Let’s create our GitHub Actions workflow.
The GitHub Actions Workflow
Now we need to create our workflow YAML file. These go in a directory named .github. Here is the single line to make it.
$ mkdir -p .github/workflows && touch .github/workflows/build.yml
Now open the build.yml file and add the following to define our workflow name and triggers. We will only trigger our build on pushes to main and pull requests to main.
name: Build
on:
# Trigger the workflow on push or pull request,
# but only for the main branch
push:
branches:
- main
pull_request:
branches:
- main
Now we need to define our jobs, which we are only going to have one, and that is to build.
jobs:
build:
name: Build
We need to define what operating system we want to build our application on. After looking at the one used by Cake, I decided to build against Windows, Ubuntu, and MacOS as those are the platforms I plan to support. This goes right after the name attribute.
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
Next are the steps that need to occur during the job. We will need to check out our code and get all of our tags and branches, which will be leveraged later.
steps:
- name: Get the sources
uses: actions/checkout@v2
- name: Fetch all history for all tags and branches
run: git fetch --prune --unshallow
We will need to install the .NET SDK and install our Fake .NET local tool.
- name: Install .NET Core SDK 3.1.402
uses: actions/setup-dotnet@v1
with:
dotnet-version: '3.1.402'
- name: Install Dotnet Tools
run: dotnet tool restore
Finally, we can execute our Fake build.
- name: Run Fake
run: dotnet fake build
Here is the build.yml file in its entirety.
name: Build
on:
# Trigger the workflow on push or pull request,
# but only for the main branch
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
name: Build
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
steps:
- name: Get the sources
uses: actions/checkout@v2
- name: Fetch all history for all tags and branches
run: git fetch --prune --unshallow
- name: Install .NET Core SDK 3.1.402
uses: actions/setup-dotnet@v1
with:
dotnet-version: '3.1.402'
- name: Install Dotnet Tools
run: dotnet tool restore
- name: Run Fake
run: dotnet fake build
Push to GitHub
The excitement is building at this point in time. We push to GitHub to see if our build works as expected.
All three operating systems were built successfully. You are now bootstrapped for being able to extend the Fake build to meet your needs.
Conclusion
I was hesitant to learn GitHub Actions. After configuring it, I will say that it is way better than Azure DevOps YAML. Do I think it is as clean as some other implementations? No, that is just a personal thing.
I look forward to diving in and learning more about what I can do as I get this new application published.
Thanks for reading,
Jamie
If you enjoy the content, then consider buying me a coffee.