DEV Community

Cover image for GitHub Composite Actions - STOP wasting your time and create reusable actions
Davide 'CoderDave' Benvegnù
Davide 'CoderDave' Benvegnù

Posted on • Updated on


GitHub Composite Actions - STOP wasting your time and create reusable actions

When working on CICD, we want to execute a variety of scripts and commands in different languages and shells in a single Action and map those outputs to the GitHub Actions workflow.

We also want to reuse parts of our workflows into other workflows.

Those 2 things are historically very difficult to do in GitHub actions. Well, despair not, today I'm showing you how to do just that, using a new GitHub Actions type that has just been released: composite run steps.

About Composite Run Steps Actions

So, first things first: What is a composite run steps action?

A composite run steps action allows you to combine multiple workflow run steps within one action. For example, you can use this feature to bundle together multiple run commands into an action, and then have a workflow that executes the bundled commands a single step using that action.

In simple words, it is a feature that enables you to nest actions within actions.

Why would you want to do it?

The most common reason is that you create a sort of template action and then you can reuse it anywhere you need. Another very common one is when you have multiple project and all of them need to follow the same steps in the CICD workflow.

Using the Composite Run Steps you can now write that part once, save it somewhere and use it in any of your actions. And if you need to change that, maybe adding a new step or changing some parameters, you'll change it once in the central location and the change will apply to all the workflows that use it.

The Video

If you are a visual learner, simply prefer to watch and listen instead of reading, or you want to see this in action, here you have the video with the whole explanation.

I'd encourage you to watch it because, to be fair, it is much more complete than this post.

If you rather prefer reading, well... let's just continue :)

Supported Properties

For each run step in a composite action, these are the properties that are currently supported:

Enter fullscreen mode Exit fullscreen mode

In addition, mapping input and outputs throughout the action are also supported.

The metadata

First of all, you need to create a metadata file.

I prefer creating a new repository to host my composite run steps action, because I like to keep things organized and this also optimize the reusability.

But you can save the composited actions also in the local repository and reference them from there.

You have to create a file named action.yml or action.yaml. Other file names are not supported.

The file could look like this:

name: 'File Copy'
description: 'Pretends to copy some files and return the number of files copied'
  destinationFolder:  # path
    description: 'The folder to copy the files to'
    required: true
    default: '~'
    description: "Number of files copied"
    value: ${{ steps.random-number-generator.outputs.filesNo }}
  using: "composite"
    - run: ${{ github.action_path }}/
      shell: bash
    - id: random-number-generator
      run: echo "::set-output name=filesNo::$(echo $RANDOM)"
      shell: bash
    - run: ${{ github.action_path }}/
      shell: bash
Enter fullscreen mode Exit fullscreen mode

In this file, the properties name, description, and runs are mandatory.

The input and outputs sections, instead, are optional and are the way we can mut input and outputs from and to the using workflow.

The YAML is quite self explanatory, I just want to point out the using: "composite" part because it's what makes this work.

Check the video with the full explanation to understand what all the parts in the YAML mean.

Save, commit, and push to the repo.

Tag time

Before we can use this "snippet" into our actions, we need to create a Tag and a Release for our repo.

You can use whatever tag you like, but this is what will identify your Composite Run Steps, so choose something meaningful.

For this example I'd go with v1

Alt Text

Ok, now we have everything we need. Let's create a composite action.

Use it in the Composite Run Steps Action

Let's go to Actions, and create a new workflow. Something like this:

# This is an example of using Composite Run Steps Actions

name: Composite Example

on: [workflow_dispatch]

    runs-on: ubuntu-latest
    name: A job that copy files
    - uses: actions/checkout@v2
    - id: myCompositeAction
      uses: n3wt0n/CompositeActionsArchive@v1 
        destinationFolder: '/whatever/folder'
    - run: echo Files copied ${{ steps.myCompositeAction.outputs.copied-files }} 
      shell: bash

Enter fullscreen mode Exit fullscreen mode

As you can see, this is a normal GitHub action. I'm using a manual trigger (check this video if you are not familiar with Manually Triggering GH Actions), but it can use any trigger you want.

The interesting part is the one in the middle:

- id: myCompositeAction
      uses: n3wt0n/CompositeActionsArchive@v1 
        destinationFolder: '/whatever/folder'
Enter fullscreen mode Exit fullscreen mode

As you can see, we are using our metadata file referencing it with the syntax "account/repo@tag".

More or less what you would do when using an Action from the Marketplace.

We are also passing some params as input (using the with: clause) and we are getting the output out of it (with the usual context, in the form steps.YOUR_STEP_ID.outputs.YOUR_PARAM_NAME)

Once again, check the video with the full explanation to understand what all the parts in the YAML mean.

And you're basically done!

Not bad right? Making slices of GitHub Actions workflows reusable is a real game changer.

Unsupported features

Some notes.

Since at the time of writing this feature has been released very recently, there are few things which are not yet supported. Those include setting conditionals, continue-on-error, timeouts and uses. Although the team is already working on most of those features.

Another thing that is not supported is using secrets on individual steps within a composite action.

Of course, you can still use all of those attributes in workflows that use a composite run steps action.


Alright, that's it for today. I will have another post and another video when the composite run steps actions will be more mature and gain more of the missing features, so subscribe to my YouTube channel and stay tuned so you'll not miss them.

Let me know in the comment section below what you think about this new feature, and if you have any question about it.

References and Links

Like, share and follow me 🚀 for more content:

📽 YouTube
Buy me a coffee
💖 Patreon
🌐 Website
👕 Merch
👦🏻 Facebook page
🐱‍💻 GitHub
👲🏻 Twitter
👴🏻 LinkedIn
🔉 Podcast

Buy Me A Coffee

Top comments (10)

choc13 profile image
Matt Thornton

One thing that caught me out was that you can’t reference other actions from within your composite action. Both the name “composite action” and the fact this post talks about “nesting actions within actions” led me astray for a while.

The crucial bit is that right now “uses” is not supported in a composite action. You can basically only use it to create a new action from several shell commands.

Just popping this here so others don’t go down that path of trying to refactor their workflows.

n3wt0n profile image
Davide 'CoderDave' Benvegnù • Edited

You are right, I should probably ass that to the article.

The reason why I haven't ephatsized that much is because the support for uses was to be added soon at the time I wrote the article and made the video. However, apparently the team's backlog has shifted and it's still not supported -_-'

markbirbeck profile image
Mark Birbeck • Edited

Can now use other actions:

Thread Thread
n3wt0n profile image
Davide 'CoderDave' Benvegnù

Yes, I’ve already made an article and a video about this new feature :

n3wt0n profile image
Davide 'CoderDave' Benvegnù

I've just double checked and in fact I do mention that in the "Unsupported Features" section :)

Thread Thread
choc13 profile image
Matt Thornton

Ah yeah I see it now. 👍 I guess the name makes more sense if their plan was to add support for “uses”. It’s a shame they’ve not been able to implement it yet though, it would be a nice feature.

n3wt0n profile image
Davide 'CoderDave' Benvegnù

What do you think of this new feature?

mteodori profile image
Marcello Teodori

looks great, I've finally found a way to achieve some DRY when moving from Travis CI similar to its import config feature

rakesh_suryawanshi profile image
Rakesh Suryawanshi

you have not used the input parameter which you are accepting in your composite file :)

n3wt0n profile image
Davide 'CoderDave' Benvegnù

hehe yes that was just a dummy example on how to require and pass parameters :)