GitHub Actions has established itself as the de facto standard for continuous integration and continuous delivery (CI/CD) within the developer community. At the core of this platform lies the YAML (YAML Ain't Markup Language) configuration file, which serves as the blueprint for automating software development workflows. For years, developers working with GitHub Actions faced limitations inherent to the YAML specification when used within the platform's context, particularly regarding code duplication and reusability. However, significant updates introduced in late 2025 have fundamentally altered the landscape, bringing native support for YAML anchors, aliases, and merge keys, alongside expanded permissions for non-public workflow templates. These changes address long-standing community requests, allowing for more efficient, maintainable, and spec-compliant workflow definitions. Understanding the structure, syntax, and newly introduced capabilities of GitHub Actions YAML is essential for engineering teams aiming to optimize their CI/CD pipelines, reduce technical debt, and accelerate development processes.
Foundational Structure of Workflow Files
The configuration for GitHub Actions is specified using YAML files stored in the .github/workflows/ directory within a repository. This directory structure is critical; GitHub only discovers and executes workflow files located specifically in this path. The files can be named arbitrarily but must use the .yml or .yaml file extension. YAML itself is a markup language commonly used for configuration files, offering a human-readable format that maps well to the hierarchical nature of CI/CD definitions.
Every workflow file follows a consistent overall structure, anchored by three primary keys: name, on, and jobs. The name key defines the title of the workflow as it appears on the repository’s Actions page. If this key is omitted, GitHub defaults to using the name of the YAML file. While optional, providing a descriptive name is a best practice for readability and identification. The on key is required and specifies the event or events that trigger the workflow. Common triggers include push events, which cause jobs to run every time a change is pushed to the repository, or specific pull request events. The syntax can be a single string, such as push, or a list of events, such as [push, pull_request].
The jobs key is the most complex and critical section of the file, containing one or more job definitions. Jobs run in parallel by default, maximizing efficiency by executing independent tasks simultaneously. To enforce sequential execution, jobs must define dependencies on other jobs. Each job is identified by a unique job_id, which is a string that must start with a letter or an underscore and can contain only alphanumeric characters, hyphens, or underscores. This ID serves as the key for the job’s configuration map.
Within each job, the runs-on key is required, specifying the type of machine or runner on which the job will execute, such as ubuntu-latest. The execution logic of a job is defined by a list of steps. Steps are the atomic units of work, combining actions or shell commands. If a step does not have an explicit name, the system defaults to using the text specified in the run command. Actions are standalone commands that can be combined into steps to create a job, while workflows themselves are composed of one or more jobs that can be scheduled or triggered by events.
yaml
name: example
on: push
jobs:
job_1:
runs-on: ubuntu-latest
steps:
- name: My first step
run: echo This is the first step of my first job.
Contexts and Dynamic Values
A powerful feature of GitHub Actions YAML is the use of contexts, which provide access to information about the repository, the workflow run, and the runner. These contexts allow workflows to be dynamic and responsive to the environment in which they are executing. Contexts are accessed using the syntax ${{ context.key }}.
For example, the github context provides information about the workflow run and the event that triggered it. Common variables include github.actor, which identifies the user who triggered the workflow, and github.event_name, which specifies the type of event. The runner context provides information about the machine executing the job, such as runner.os. The job context includes details about the current job, such as job.status. These variables can be interpolated directly into step commands, output messages, or other configuration fields.
In a typical demo workflow, these contexts are used to print diagnostic information or customize output messages. A step might echo a message stating that the job was triggered by a specific event, identify the operating system of the runner, and list the repository name and branch. This dynamic capability ensures that workflows are not static scripts but adaptive configurations that react to the specific context of each execution.
yaml
name: GitHub Actions Demo
run-name: ${{ github.actor }} is testing out GitHub Actions 🚀
on: [push]
jobs:
Explore-GitHub-Actions:
runs-on: ubuntu-latest
steps:
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
- name: Check out repository code
uses: actions/checkout@v6
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ github.workspace }}
- run: echo "🍏 This job's status is ${{ job.status }}."
Native Support for YAML Anchors and Aliases
One of the most significant updates to GitHub Actions, announced in September 2025, is the native support for YAML anchors, aliases, and merge keys. For years, the GitHub community had requested this feature as a top priority. Prior to this update, developers had to rely on workarounds or external tools to achieve code reuse within a single workflow file, as GitHub Actions did not fully conform to the YAML specification in this regard. The new feature is automatically enabled for all users and repositories, requiring no additional configuration.
YAML anchors allow developers to define a block of configuration once and reference it multiple times using aliases. This is particularly useful for eliminating duplication within a single file. For instance, if multiple jobs require the same environment variables, runner specifications, or step sequences, anchors can be used to define these elements once and reuse them. Merge keys allow for combining anchor definitions with job-specific overrides, providing a flexible way to manage common configurations while allowing for customization.
This update addresses a significant gap in the platform's functionality. While the technical capability to support YAML anchors had existed in the underlying YAML parser for some time, GitHub had chosen not to implement it, likely due to complexity or security concerns related to context evaluation. The announcement emphasized that this support ensures better conformance with the YAML specification. However, some technical experts have noted that the implementation may be limited to a subset of use cases, particularly those involving simple data structures, rather than full recursive expansion of complex nested contexts. Despite this, the ability to use anchors directly in GitHub Actions YAML files represents a major step forward for workflow maintainability.
Alternatives to YAML Anchors: Reusable Workflows and Composite Actions
Before the introduction of native YAML anchors, developers had to choose between several alternative methods for eliminating duplication and promoting reusability. Each of these methods has distinct advantages and limitations, and understanding them is crucial for designing efficient CI/CD strategies.
Reusable workflows allow teams to share entire workflows across repositories. This is ideal for organization-wide deployment patterns where the same high-level process needs to be applied to multiple projects. However, reusable workflows are overkill for eliminating minor duplications, such as shared environment variables or step sequences within a single workflow file. Additionally, reusable workflows have a structural limitation: it is not possible to add steps before or after the call to the reusable workflow within the calling workflow. This rigidity can make them unsuitable for scenarios requiring granular control over the execution order.
Composite actions offer another avenue for reusability. These allow developers to bundle a sequence of steps into a single, reusable action stored in the .github/actions/ directory. Composite actions provide proper encapsulation with defined inputs and outputs and can be used across different repositories. However, they require the creation of separate action.yml files, which adds overhead. Furthermore, composite actions cannot specify the runner they run on; the runner must be defined in the job that calls the action. For simple within-file duplication, composite actions can feel heavyweight due to the additional file management and invocation overhead.
In contrast, YAML anchors eliminate duplication within a single file with zero setup overhead. They do not require separate files, input definitions, or shell specifications. This makes them the most lightweight and direct solution for reducing redundancy in workflow definitions. The choice between anchors, reusable workflows, and composite actions depends on the scope of the reuse and the specific requirements of the CI/CD pipeline.
Non-Public Workflow and Issue Templates
Another significant update in September 2025 expanded the scope of workflow templates and issue templates beyond public repositories. Previously, workflow templates and issue templates could only be sourced from a public .github repository. This limitation hindered organizations that wished to maintain internal or private templates for security or proprietary reasons.
GitHub Actions now supports workflow templates from non-public GitHub repositories. Organizations can place templates in a .github repository that is either internal or private. If the .github repository is internal, both internal and private repositories within the same organization can utilize these workflow templates. If the .github repository is private, only private repositories can access the templates. This change aligns the handling of workflow templates with the security model of GitHub repositories, allowing for more flexible and secure template management.
The update also applies to issue templates. Issue templates stored in non-public .github repositories can now be used by internal or private repositories, depending on the visibility of the .github repository itself. It is important to note that these changes apply specifically to GitHub Actions and issue templates. Other products that utilize .github repositories, such as GitHub Issues in certain contexts, continue to rely only on public .github repositories. This distinction highlights the incremental nature of GitHub’s feature rollouts and the specific focus on enhancing the Actions and template management experience.
Job Context Enhancements: checkrunid
In addition to structural and templating updates, GitHub Actions introduced a new value in the job context: check_run_id. This addition allows users to identify the currently running job directly from within the job itself by accessing the check_run_id variable. This ID corresponds to the unique identifier of the check run associated with the job.
This enhancement provides greater visibility and control over workflow execution. By accessing the check_run_id, developers can correlate job logs, annotations, and status updates with specific check runs in the GitHub API. This is particularly useful for advanced debugging, external monitoring integrations, and automated reporting tools that require precise identification of workflow artifacts. The availability of this context variable simplifies the process of linking job execution data with GitHub’s check run infrastructure, reducing the need for custom workarounds or external tracking mechanisms.
Third-Party Solutions and Community Perspective
While GitHub has introduced native support for YAML anchors, the journey to this point was not without community-driven solutions. For years, developers utilized third-party actions to achieve similar functionality. One notable example is the true-yaml-actions action, available on the GitHub Marketplace. This action allows users to process YAML files with full support for anchors and aliases, effectively bypassing the native limitations of GitHub Actions during the period before native support was added.
Using such an action typically involved invoking a specific step with the DanySK/true-yaml-actions repository and providing a workflow token for authentication. While these solutions worked, they introduced additional complexity and dependency on external tools. The introduction of native support renders many of these third-party workarounds obsolete for basic anchor usage, streamlining the workflow definition process.
Despite these improvements, some experts in the CI/CD community maintain that GitHub Actions has inherent design flaws stemming from its bottom-up development history. Critics argue that the platform could benefit from a complete overhaul or a "v2" redesign to address fundamental architectural issues. However, despite these criticisms, GitHub Actions remains the dominant CI/CD platform due to its deep integration with GitHub, large ecosystem of actions, and continuous improvement efforts. The community’s love for the platform persists, driven by its practical utility and the steady addition of features like YAML anchors that address real-world developer pain points.
Conclusion
The evolution of GitHub Actions YAML configuration reflects a maturing platform that increasingly aligns with standard YAML specifications and developer expectations. The introduction of native support for YAML anchors and aliases in September 2025 marks a significant milestone, enabling developers to eliminate duplication within workflow files without the overhead of composite actions or the rigidity of reusable workflows. This feature, automatically enabled for all users, enhances maintainability and reduces the cognitive load associated with managing complex CI/CD pipelines.
Concurrently, the expansion of workflow and issue templates to non-public repositories provides organizations with greater flexibility in managing internal tooling and standards, respecting security boundaries while promoting consistency. The addition of check_run_id to the job context further refines the platform’s introspective capabilities, allowing for more precise tracking and integration with external systems.
As GitHub Actions continues to evolve, the balance between ease of use and technical depth remains a key focus. While some architectural criticisms persist, the platform’s commitment to addressing community feedback and adopting standard YAML features ensures its relevance in the modern development landscape. For teams looking to optimize their workflows, leveraging these new capabilities—particularly YAML anchors for in-file reuse and non-public templates for secure standardization—offers a clear path toward more efficient and robust CI/CD practices.