Background
I have a small elixir project and I am trying to use GithubWorkflow to have a nice pipeline and automate some actions.
Problem
However I can't even get it started as I get the following error:
Setup elixir
1s
AUCTION_HOUSE_TOKEN: ***
Run actions/setup-elixir#v1
with:
elixir-version: 1.10-otp-22
otp-version: 22.1
install-hex: true
install-rebar: true
env:
COOKIE: ***
TOKEN: ***
##[error]Cannot read property 'includes' of undefined
Code
I think my workflow might be incorrect, could someone help figure out what's wrong?
name: build
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
env:
AUCTION_HOUSE_COOKIE: ${{ secrets.MARKET_MANAGER_WM_COOKIE }}
AUCTION_HOUSE_TOKEN: ${{ secrets.MARKET_MANAGER_WM_XCSRFTOKEN }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- name: Setup elixir
uses: actions/setup-elixir#v1
with:
elixir-version: '1.10-otp-22' # Define the elixir version [required]
otp-version: '22.1' # Define the OTP version [required]
- name: Install Dependencies
run: mix deps.get
- name: Run Tests
run: mix test
- name: Run credo code analyser
run: mix credo --strict
- name: Run typechecks
run: mix dialyzer
- name: Build executable
run: mix escript.build
env:
MIX_ENV: prod
Summary
The elixir version in the file was wrong. It should have:
with:
elixir-version: '1.10.4 # Define the elixir version [required]
otp-version: '22.1' # Define the OTP version [required]
Instead of the current content.
RCA
So this one was interesting. When it comes to elixir versions, because I use asdf as my version manager, I am allowed to pick the best version (the most optimized) for the erlang setup I have.
How do I know which elixir version is the best for, lets say, erlang 22.1?
Well, I use bob's list:
https://bobs-list.kobrakai.de/#version_v1.10
And while this is fine and it does work on my machine and in docker files and so on, Github Action wont accept it. Github Actions takes its elixir version's from here:
https://github.com/elixir-lang/elixir/releases
And as you can see, there no official release called "1.10-otp-22"
So, instead of the current content, the file should instead have:
with:
elixir-version: '1.10.4' # Define the elixir version [required]
otp-version: '22.1' # Define the OTP version [required]
Related
I am trying to setup my first GitHub Workflow and I am facing many YAML syntax issues even I am using the official documentation.
I am using the below YAML:
# This is a basic workflow to help you get started with Actions
name: TestWorkflowGithub
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the "main" branch
pull_request:
branches:
- 'testbranch/**'
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- name: Checkout the code
uses: actions/checkout#v3
- name: Install PMD
run: |
PMD_VERSION=`cat pmd/pmd-version.txt`
wget https://github.com/pmd/pmd/releases/download/pmd_releases%2F6.54.0/pmd-bin-6.54.0.zip
unzip pmd-bin-6.54.0.zip -d ~
mv ~/pmd-bin-$6.54.0 ~/pmd
~/pmd/bin/run.sh pmd --version
# Run PMD scandd
- name: Run PMD scan
run: ~/pmd/bin/run.sh pmd -d force-app -R pmd/ruleset.xml -f text
GitHub is showing me the below error:
You have an error in your yaml syntax on line 14
Note: the line 14 is "runs-on: ubuntu-latest"
Which is the syntax issue in the above YAML file?
You are missing the job identifier:
jobs:
foo: # <-- This
runs-on: ubuntu-latest
steps:
- name: Checkout the code
uses: actions/checkout#v3
steps:
You can use actionlint or vscode-yaml to avoid such syntax issues next time :)
If we were to use minimal resources, doing these steps would look something like:
setup --- checkout, install fixed versions via cache
then trigger in parallel 1 command to run:
lint
test
e2e
all in parallel.
Unfortunately, with the current options I've found out there, the best scenario I can find is to have a separate workflow file for lint, test, e2e that are called by a main workflow and upon success build an artifact.
The issue with this is.
checkout will run 3 times.
install command will run 3 times.
Which can be mitigated with caching, but you're still looking at 10-15 seconds extra per job for those steps.
Is there a way to optimise this and still keep the reusable steps?
Even if I would keep everything in 1 giant file, I'd still define the lint, test, e2e steps as separate jobs and not as 1 single step part of a job.
Can we call a 'workflow' and run it in the same environment on the spot somehow?
This example calls checkout and caches the repo using the $ {{ github.run_id }} to prevent the cache conflicting with other runs. The cache is then used by the child workflows in place of checking out. e2e, test and lint will wait for the cache to be created and then all run in parallel.
Depending on your use case it may be excessive to create a new cache for each run_id, you can adjust this as you need. If speed is what you're after I'd also suggest only caching the files that you need for your child workflows, and not take everything like I've done in the example below.
name: main_caller
on: workflow_dispatch
jobs:
cache_checkout:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v3
- uses: actions/upload-artifact#v3
with:
name: my-checkout-${{ github.run_id }}
path: ${{ github.workspace }}/**/*
run_lint:
needs: cache_checkout
uses: ./.github/workflows/lint.yml
run_test:
needs: cache_checkout
uses: ./.github/workflows/test.yml
./.github/workflows/lint.yml example: (e2e and test will follow this pattern)
name: lint
on: workflow_call
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Get Cached Checkout
uses: actions/download-artifact#v3
with:
name: my-checkout-${{ github.run_id }}
- name: Do linting things
run: echo "I'm linting!"
Edited as per comments - all jobs in GitHub run in parallel, but to have cleaner example you could use matrix strategy. To make it work you need it to depend on a 'setup' job that will install everything and create the artifacts (this is done using the needs keyword).
In the following example the install job would setup everything and then the example job, which uses matrix strategy, will run the lint/test/e2e flow in separate parallel jobs after it downloads the required artifacts.
jobs:
install:
runs-on: ubuntu-latest
- uses: actions/checkout#v3
- name: Compile artifacts
run: *install fixed versions/create artifacts*
- uses: actions/upload-artifact#v3
with:
name: my-artifact
path: path/to/my_artifact
example:
runs-on: ubuntu-latest
needs: install
strategy:
matrix:
action: [lint, test, e2e]
steps:
- uses: actions/download-artifact#v3
with:
name: my-artifact
path: path/to/artifact
- name: lint
if: ${{ matrix.lint }}
run: echo "lint"
- name: test
if: ${{ matrix.test }}
run: echo "test"
- name: e2e
if: ${{ matrix.e2e }}
run: echo "e2e"
It will create a workflow like this:
I'm trying to create automatic releases of a project using GitHub Actions where the release tag is based on the date. I don't want to use standard semantic versioning because this project is a fork of another project that uses date-based versioning. I've found posts about the getting the date in a workflow and have this so far:
name: Publish
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
publish:
name: Publish release of font files
runs-on: ubuntu-latest
steps:
- name: Create foo file
run: |
mkdir cascadios
> cascadios/foo.txt
- name: Get tag name from date
id: tag_name
run: echo "::set-output name=date::$(date +'%y%m.%d')"
- name: Zip font files
run: |
cd cascadios
zip ../cascadios-${{ steps.tag_name.outputs.date }}.zip *
cd ..
- name: Create tag
uses: mathieudutour/github-tag-action#v6.0
id: tag_version
with:
github_token: ${{ github.token }}
custom_tag: ${{ steps.tag_name.outputs.date }}
Note: I have it creating a blank file to release to save the 15 minutes of building.
This works great until I have two releases in one day (such as today where I am testing this workflow a lot). How can I get it so I can add a dynamic patch number to the tag, so it doesn't cause a conflict? An example might look like v2112.13.0.
You can use our versioning library - https://github.com/relizaio/versioning
Then you can declare version pattern to be something like: YYYY.0M.0D.Micro
Then the following command would produce a base version:
docker run --rm relizaio/versioning -s YYYY.0M.0D.Micro
Now, if you already have a version say 2021.12.14.1 and want to bump it up, you would do
docker run --rm relizaio/versioning -s YYYY.0M.0D.Micro -v 2021.12.14.1 -a bump
This would produce 2021.12.14.2 if you call it on December 14th, or something 2021.12.15.0 if you call this command on the December 15th.
I'm trying to make use of a workflow environment variable in a marketplace action, using a build matrix but it's not working for some reason.
I basically want to define the database versions just once to avoid repeating them in multiple place in my workflow.
Here's my workflow (minimal reproducible example):
name: dummy
on:
pull_request:
env:
MONGODB_3_6: 3.6.13
MONGODB_4_0: 4.0.13
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
MONGODB: [$MONGODB_4_0, $MONGODB_3_6]
steps:
- uses: actions/checkout#v2
- name: Start MongoDB
uses: supercharge/mongodb-github-action#1.3.0
with:
mongodb-version: ${{ matrix.MONGODB }}
And it's failing with the error below, as if the MONGODB_4_0 wasn't defined.
Interesting fact, without the strategy matrix, I'm able to make it work using the env context(doc):
- name: Start MongoDB
uses: supercharge/mongodb-github-action#1.3.0
with:
mongodb-version: ${{ env.MONGODB_4_0 }}
UPDATED: according tests and comments, I think matrix can't take environment variables and/or dynamic values.
so the best way will be :
matrix:
MONGODB: [3.6.13, 4.0.13]
As #max said you can use a variable for your workflow, so I guess your matrix should be wrong, maybe you can try like that :
MONGODB: [${{ env.MONGODB_4_0 }}, ${{ env.MONGODB_3_6 }}]
You have only one job (test) so you can define your env variables at the job level also.
Variables will be accessible for all the job :
jobs:
test:
runs-on: ubuntu-latest
env:
MONGODB_3_6: 3.6.13
MONGODB_4_0: 4.0.13
For further information : github doc
I have a workflow with an action that creates a version number when building an artefact. This version number is written to file.
How can I give that as an input to another action?
I.e: How can I use this version number as part of a commit message in another action?
Per the fabulous answer here, there's actually an inline way to accomplish this. Not intuitive at all, except that the ::set-output... syntax matches the same expected output format for GitHub Actions.
The below step loads the VERSION file into ${{ steps.getversion.outputs.version }}:
- name: Read VERSION file
id: getversion
run: echo "::set-output name=version::$(cat VERSION)"
I had the same use case as OP, so I'm pasting below my entire code, which does three things:
Pull first three-parts of the 4-part version string from the file VERSION.
Get a sequential build number using the einaregilsson/build-number#v2 action.
Concatenate these two into an always-unique 4-part version string that becomes a new GitHub release.
name: Auto-Tag Release
on:
push:
branches:
- master
jobs:
release_new_tag:
runs-on: ubuntu-latest
steps:
- name: "Checkout source code"
uses: "actions/checkout#v1"
- name: Generate build number
id: buildnumber
uses: einaregilsson/build-number#v2
with:
token: ${{secrets.github_token}}
- name: Read VERSION file
id: getversion
run: echo "::set-output name=version::$(cat VERSION)"
- uses: "marvinpinto/action-automatic-releases#latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: v${{ steps.getversion.outputs.version }}.${{ steps.buildnumber.outputs.build_number }}
prerelease: false
Fully automated release management! :-)
Note: The branch filter at top ensures that we only run this on commits to master.
It is possible to use the filesystem to communicate between actions. But if you have input on 3rd party actions, you need to give this from the outputs of another action
Ie. you need to read this file in your action and present it as output in your action.yml. Then you can use this output as input to another action in your workflow.yaml
The accepted answer is outdated as per this blog post from GitHub.
It is still possible to do this as one step from your workflow though:
- name: Read VERSION file
id: getversion
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
This will set an output named version which you can access just as before using ${{ steps.getversion.outputs.version }}:
- uses: "marvinpinto/action-automatic-releases#latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: v${{ steps.getversion.outputs.version }}.${{ steps.buildnumber.outputs.build_number }}
prerelease: false