GitHub Actions Tutorial — Action Metadata

2 minute read

Action Metadata

Every custom action requires an action.yml (or action.yaml) file in its root directory. This file defines the action’s interface — its name, inputs, outputs, runtime, and branding.


Complete action.yml Reference


name: 'Deploy to S3'
description: 'Upload files to an AWS S3 bucket'
author: 'my-org'

branding:
  icon: 'upload-cloud'
  color: 'orange'

inputs:
  bucket:
    description: 'S3 bucket name'
    required: true
  path:
    description: 'Local path to upload'
    required: false
    default: './dist'
  aws-region:
    description: 'AWS region'
    required: false
    default: 'us-east-1'

outputs:
  url:
    description: 'Uploaded file URL'
    value: ${{ steps.upload.outputs.url }}

runs:
  using: 'composite'
  steps:
    - name: Upload to S3
      id: upload
      run: |
        aws s3 sync ${{ inputs.path }} s3://${{ inputs.bucket }}/ --region ${{ inputs.aws-region }}
        echo "url=https://${{ inputs.bucket }}.s3.amazonaws.com/index.html" >> "$GITHUB_OUTPUT"
      shell: bash


Top-Level Fields

Field Required Description
name ✅ Action name (shown in the Marketplace)
description ✅ Short description
author ❌ Author name or organization
branding ❌ Icon and color for Marketplace listing

Inputs


inputs:
  <input-id>:
    description: 'What this input does'
    required: true            # or false
    default: 'default-value'  # optional
    deprecationMessage: 'Use new-input instead'  # optional

  • All inputs are passed as strings
  • required: true doesn’t prevent the workflow from running — it’s informational in composite actions
  • Access in steps: ${{ inputs.input-id }}

Outputs


outputs:
  <output-id>:
    description: 'What this output contains'
    value: ${{ steps.<step-id>.outputs.<key> }}

For JavaScript actions, outputs are set via core.setOutput(). For composite actions, use $GITHUB_OUTPUT in a step and reference it in the output value.


Runs Configuration

Composite

runs:
  using: 'composite'
  steps:
    - run: echo "hello"
      shell: bash

JavaScript

runs:
  using: 'node20'
  main: 'dist/index.js'
  pre: 'setup.js'           # optional — runs before main
  post: 'cleanup.js'        # optional — runs after main

Docker


runs:
  using: 'docker'
  image: 'Dockerfile'       # or 'docker://image:tag'
  args:
    - ${{ inputs.path }}
  env:
    MY_VAR: 'value'


Branding

For Marketplace listing, choose an icon and color:

branding:
  icon: 'upload-cloud'      # Feather icon name
  color: 'blue'             # white, yellow, blue, green, orange, red, purple, gray-dark

Feather Icons — use the icon name from the site.


Pre and Post Scripts (JavaScript Only)

runs:
  using: 'node20'
  pre: 'src/setup.js'          # runs before the main entry point
  main: 'src/index.js'         # main entry point
  post: 'src/cleanup.js'       # runs after all steps (even on failure)
  post-if: 'always()'          # condition for post script

Use cases:

  • pre: — set up authentication, start services
  • post: — cleanup resources, revoke tokens

Common Mistakes

Mistake Fix
Missing action.yml Must be in the action’s root directory
required: true not enforced It’s informational — add validation in your action code
Output value empty Ensure the step ID matches and output is set correctly
Branding icon not found Use exact Feather icon names

Quick Reference

Section Key Fields
Identity name, description, author
Inputs description, required, default
Outputs description, value
Runs (composite) using: 'composite', steps:
Runs (JS) using: 'node20', main:, pre:, post:
Runs (Docker) using: 'docker', image:, args:
Branding icon:, color:

← Previous: Docker Actions

Next: Publishing to Marketplace →

Updated: