Building GitHub Action part 1
When to build a custom action?
Normally when a project are getting bigger with number of build and deploy arises, DevOps uses custom build action to deploy the application. The standard workflow look like this
Checkout ---> Build ---> Deploy
In yml representation:
jobs:
build_and_deploy
steps:
- name: Checkout
- uses: actions/checkout@v1
- name: Build
run: make all
- name: Deploy
uses: actions/deploy@v1
with:
environment: Staging
Keyword run is an interface to a command prompt.
Keyword uses lets us invoke the action. Action relies on some other command line tool to do the job. It acts like the adapters between the workflow and the command line tools.
When do we used either action or invoking the command itself?
We need to consider 4 things:
Control flow
Diagnostics
Complexity
Reuse
Imagine you want to run an npm script called build.
- name: Build
run: npm run buildBefore the "run build", restore first the packages by running the npm install or npm ci command.
- name: Build
run:
npm ci
npm run buildBut considering that we only want to run build when the restore is done. The above code will not behave as such it will still run the build even the restore fails.
In order to prevent this, we use a control flow. A flow in to do something only if the certain condition is met.
- name: Build
run: |
npm ci && npm run buildSince run can be interpreted via shell, we can use any control flow structures that are build into the shell itself.
The above code will requires restore to pass before the build.
Now imagine that we have more than one package to build this workflow. We can use the working-directory keyword to run the same command on multiple project.
- name: Build
run: |
npm ci && npm run build
working-directories: |
./src/projectBut we have to duplicate the same shell command in different places.
- name: Build
run: |
npm ci && npm run build
working-directories: |
./src/project
- - name: Build one
run: |
npm ci && npm run build
working-directories: |
./src/project
- name: Build two
run: |
npm ci && npm run build
working-directories: |
./src/project
- name: Build three
run: |
npm ci && npm run build
working-directories: |
./src/projectThis defeats the purpose of KISS(Keep it simple and short). This is the run keyword limitation. A better solution is to package the build logic inside an actions that accepts one or more working directories as an input.
- name: Build
uses: actions/npm-build@v1
with:
working-directories: |
- /src/projectOne
- /src/projectTwo
- /src/projectThree There is also an option to split the commands into separate jobs
jobs:
install:
steps:
- name: Clean Install
run: npm ci
build:
needs: install
steps:
- name: Build
run: npm run buildNotice that under build jobs, it requires the install by using the keyword needs. This is almost the same as using with ampersand.
What is we want log the error when the job fails. This is where Diagnostics comes in. Right now there is no way to build error handling into the workflow itself, that is to be taken care inside of an action
jobs:
install:
steps:
- name: Clean Install
run: npm ci
build:
needs: install
steps:
- name: Build
run: npm run build
Workflows being declarative in nature are design to describe processes at a high level of obstruction. Namely as a sequence of steps that run in response to certain events.
Checkout ---> Build ---> Deploy
Imagine a workflow has two jobs and will do run it in a multiple projects . The only way to do that inside in a workflow is duplicate everything and specify a working directory each instance.
jobs:
install:
steps:
- name: Clean Install
run: npm ci
working_directory:..
build:
needs: install
steps:
- name: Build
run: npm run build
working_directory:..Complexity does not also exist in the workflow level, it can also exist in a individual steps
- name: Deploy
env:
USER: ${{secret.USER}}
PWD: ${{secrets.PWD}}
run: |
curl -Ss \
--fail \
-X POST \
-T path/to/app.zip \
-u $USER:$PWD \
https://example.com/app \Take for instance a steps need to invoke command line program with many parameters. Now imagine one of the argument we need to pass comes from a different step, like at the curl parameter we need to used PWD. Again we can certainly can implement it right in the workflow. But there is a better way to do it. It is by grouping multiple related steps into a single action, we can reused it not only inside the workflow but also access workflows. This comes the Reuse
Grouping multiple related steps into a single action, we can reused it not only inside the workflow but also access workflows. If the action does something that could be useful to many people, we can make it available to everyone by publishing it to Github market place
jobs:
build_and_deploy:
steps:
- name: Deploy and Build
uses: ./npm-deploy@v1
build_and_deploy another:
steps:
- name: Deploy and Build
uses: ./npm-deploy@v1
add_another:
steps:
- name: Deploy and Build
uses: ./npm-deploy@v1In summary:

Last updated