Zurück zu Blogs

What I Wish I Knew Before Using GitHub Actions (Part 1)

avatar Jesko und avatar Niklas
7 Minuten

September 2025

Over time, I've compiled a list of crucial tips and best practices that significantly enhance security, reliability, and maintainability. Whether you're just starting or looking to refine your existing CI/CD pipelines, these are the key insights (Part 1) I truly wish I knew before I began my GitHub Actions journey.

Illustration of GitHub Actions workflow

Third Party actions - Pinning the versions

When integrating third-party GitHub Actions into your workflows, one crucial step is version pinning. Version pinning means locking an action to a specific commit SHA instead of a mutable tag like @v1 or @latest. This enhances security by ensuring that your workflow consistently uses the exact code you’ve reviewed, avoiding potential vulnerabilities introduced by unexpected updates.

Imagine you're using a third-party action like superdev/super-linter for linting your code. A typical workflow might look like this:

Example workflow using a version tag:

While this works, @v4 is mutable and can change over time. To pin it to a specific version, replace it with the commit SHA:

Example workflow pinned to a commit SHA:

How to Find the Commit SHA

1Go to the action's GitHub repository.
2Navigate to Releases or Tags to find the version you want.
3Click the tag, then copy the full commit SHA from the commit details.

By pinning GitHub Actions to an exact commit SHA, you significantly enhance the security and stability of your workflows. This prevents unexpected behavior caused by upstream changes or automatic updates, making your CI/CD pipeline more predictable and reliable.

However, keep in mind that even if you pin versions in your workflow files, the actions themselves might still reference unpinned dependencies internally. That’s why it’s important to stay cautious when using third-party actions, always review their source and update policies.

To manage updates more safely, consider using tools like GitHub Dependabot or Renovate to automatically detect and help you pin or upgrade Action versions.

Note on Immutable GitHub Releases and Actions
GitHub is actively working towards making both releases and GitHub Actions truly immutable. Immutable GitHub releases are currently available in public preview as of August 2025. Full immutability for GitHub Actions is still in development and is planned on the roadmap for Q4 2025.

Programmatically Generated Matrix Builds

When automating workflows with GitHub Actions, you might encounter scenarios where the set of tasks varies based on dynamic factors, such as changes in your codebase or external inputs. In such cases, programmatically generating matrix builds allows for flexible and efficient execution of jobs tailored to current conditions.

Let’s take a practical example. Say you’ve got a GitOps repo full of Helm charts, and you want to make sure each chart is valid before it ever gets deployed to Kubernetes. One way to handle this is to set up a workflow that runs on every pull request, using logic similar to the snippet below:

Example: Programmatically generated matrix build

Linting Workflows with Actionlint: Ensuring Quality in GitHub Actions

Why Linting GitHub Actions? Linting GitHub Actions files helps identify potential issues like:

  • Syntax errors: Ensure your workflow YAML files are correctly formatted.
  • Missing or incorrect field names: Catch common mistakes before they cause runtime failures.
  • Unused or redundant steps: Clean up your workflows and improve efficiency.
  • Best practices: Follow industry standards for writing GitHub Actions workflows.
  • Shell script validation: Actionlint includes ShellCheck, which automatically analyzes steps running shell commands to catch common pitfalls and enforce safer scripting.

Using a linter like Actionlint will save you time, prevent errors, and ensure your workflows run smoothly. You might even want to consider using Megalinter, which includes Actionlint along with other linters for a comprehensive code quality check.

How to Use Actionlint

1Install Actionlint:
Follow the official installation guide for your platform.
2Lint Your Workflows Locally:
Open your terminal and run:
actionlint
This command checks all workflow YAML files in the nearest .github/workflows directory. You can also specify files or flags as needed:
actionlint [FLAGS] [FILES…]
3Automate Linting in CI:
Add Actionlint as a step in your CI pipeline to ensure all workflows are checked automatically on every push or pull request.

Use GitHub App Authentication instead of PATs (Personal Access Tokens)

When automating workflows with GitHub Actions, authentication is crucial to ensure secure and efficient access to your GitHub resources. While Personal Access Tokens (PATs) are commonly used, GitHub Apps are the better option for most CI/CD use cases, especially when it comes to security, flexibility, and control.

Personal Access Tokens (PATs) in GitHub Actions

  • What Are They? PATs are user-specific tokens that grant access to repositories and perform actions within GitHub. In GitHub Actions, PATs are typically used to authenticate steps that require access to the repository, such as pushing code, creating issues, or triggering workflows.
  • Limitations in GitHub Actions:
    • Security Risks: PATs are tied to user accounts and long-lived, which means if the token is exposed, it can give attackers broad access to repositories.

Why GitHub Apps Are Better for GitHub Actions

  • What Are GitHub Apps? GitHub Apps provide a more secure and scalable solution for automating tasks in GitHub Actions. They can be installed on repositories and organizations, providing fine-grained permissions for specific tasks.
  • Benefits in GitHub Actions:
    • Granular Permissions: GitHub Apps allow you to specify exactly what your workflow can access, minimizing unnecessary permissions.
    • Short-Lived Tokens: GitHub Apps use short-lived tokens, reducing the risk if credentials are compromised. These tokens are automatically rotated, ensuring long-term security.
    • Independence from User Accounts: GitHub Apps are not tied to user accounts, ensuring that workflows continue to run with the same permissions, even if users change or leave the organization.

How to Create a Short-Term Token with GitHub Apps in GitHub Actions

One way to use GitHub App authentication in your GitHub Actions workflow is by creating a short-lived token using the create-github-app-token action. This action allows you to authenticate your workflow without exposing long-lived tokens.

Example workflow using GitHub App authentication:

Debugging GitHub Actions

Debugging GitHub Actions can be frustrating. Logs are limited, secrets are masked, and trial and error is slow. To get more detailed logs, set ACTIONS_STEP_DEBUG=true (see documentation) and use echo statements to increase visibility.

For serious troubleshooting, add mxschmitt/action-tmate to your workflow. It launches an SSH session directly into the live runner, letting you inspect, run commands, and debug interactively. Just make sure to use it only in trusted or private contexts.

Even better: speed up your dev cycle with act, a CLI tool to run GitHub Actions locally. It’s perfect for quick iteration before pushing to GitHub. My take: Easy to start, hard to master. It takes some time to configure everything, but it’s worth it!

With a mix of logging, act, and tmate, debugging CI can finally feel under control.

Reusing actions and workflows can safe time

It's tempting to stuff your entire CI/CD logic into one giant YAML file — but that quickly becomes unmaintainable. GitHub Actions supports two great tools for structuring logic: composite actions and reusable workflows.

Composite actions let you bundle shell steps into a shareable action, ideal for tasks like setting up environments or building artifacts. They're stored in your repo (.github/actions/your-action) and version-controlled like any other code.

Reusable workflows, on the other hand, encapsulate entire jobs — perfect for standardized test, build, or deploy pipelines. You can call them from multiple workflows across repos.

Use composite actions for step-level reuse, and reusable workflows for job-level orchestration. Structure matters — especially when your automation grows. Keep it clean, DRY, and versioned.

Concurrency Control: Stop Workflow Pile-Ups

Running multiple GitHub Actions workflows simultaneously can cause messy conflicts, especially with deployments. The concurrency key lets you define groups of runs and, with cancel-in-progress: true, ensures that a new run in that group cancels any older one. This is a simple but vital way to prevent e.g. conflicting deployments and manage resource usage, guaranteeing only the latest workflow run for a specific group (like deploying to production) proceeds.

Example: Preventing conflicting deployments on main branch

There are plenty of other ideas I could write about. Stay tuned for Part 2!

Willst Du mit uns darüber sprechen?