{"id":16123583,"url":"https://github.com/austenstone/actions","last_synced_at":"2026-05-16T17:34:12.303Z","repository":{"id":252440380,"uuid":"840449791","full_name":"austenstone/actions","owner":"austenstone","description":"GitHub Actions","archived":false,"fork":false,"pushed_at":"2025-08-21T13:49:28.000Z","size":863,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-16T08:57:21.950Z","etag":null,"topics":["actions","documentation","github"],"latest_commit_sha":null,"homepage":"https://austenstone.github.io/actions/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/austenstone.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["austenstone"]}},"created_at":"2024-08-09T18:24:43.000Z","updated_at":"2025-08-21T13:49:31.000Z","dependencies_parsed_at":"2025-02-12T17:51:55.537Z","dependency_job_id":"100ff5bc-a1df-4034-a4fa-5e527214fa41","html_url":"https://github.com/austenstone/actions","commit_stats":null,"previous_names":["austenstone/actions"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/austenstone/actions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/austenstone%2Factions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/austenstone%2Factions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/austenstone%2Factions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/austenstone%2Factions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/austenstone","download_url":"https://codeload.github.com/austenstone/actions/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/austenstone%2Factions/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279171216,"owners_count":26118707,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-16T02:00:06.019Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["actions","documentation","github"],"created_at":"2024-10-09T21:17:31.889Z","updated_at":"2025-10-16T09:02:31.998Z","avatar_url":"https://github.com/austenstone.png","language":null,"funding_links":["https://github.com/sponsors/austenstone"],"categories":[],"sub_categories":[],"readme":"# GitHub Actions Overview\n\nThis document is a high-level overview of GitHub Actions. It is not intended to be a comprehensive guide to the platform, but rather a starting point for understanding the basics.\n\n- [GitHub Actions Overview](#github-actions-overview)\n  - [Intro to Concepts](#intro-to-concepts)\n  - [How to Trigger/Initiate Workflow Runs](#how-to-triggerinitiate-workflow-runs)\n  - [How to Structure/Manage Jobs in the Workflow](#how-to-structuremanage-jobs-in-the-workflow)\n  - [How to Use and Create Actions (Marketplace)](#how-to-use-and-create-actions-marketplace)\n  - [How to Organize, Share, and Scale Workflows](#how-to-organize-share-and-scale-workflows)\n  - [Artifacts](#artifacts)\n  - [Caching](#caching)\n  - [Secrets](#secrets)\n  - [How to Create and Manage Runners](#how-to-create-and-manage-runners)\n  - [How to Govern Usage](#how-to-govern-usage)\n  - [How to Observe What’s Going on with CI/CD](#how-to-observe-whats-going-on-with-cicd)\n  - [How to Manage Cost and Billing](#how-to-manage-cost-and-billing)\n  - [How to Migrate](#how-to-migrate)\n  - [Understanding Platform Limits](#understanding-platform-limits)\n\n## Intro to Concepts\n\nThere are a few concepts that are important to understand when working with GitHub Actions.\n\n### Definitions\n\nSome basic definitions to get us started...\n\n![overview-actions-simple](images/overview-actions-simple.png)\n\n#### [Workflow](https://docs.github.com/en/actions/about-github-actions/understanding-github-actions#workflows)\n\nA workflow is a configurable automated process that will run one or more jobs. Workflows are defined by a YAML file checked in to your repository in the `.github/workflows` directory. A repository can have multiple workflows, each of which can perform a different set of tasks.\n\n#### [Events](https://docs.github.com/en/actions/about-github-actions/understanding-github-actions#events)\n\nAn event is a specific activity in a repository that triggers a workflow run. It could be triggered by an event in your repository, or they can be triggered manually, or at a defined schedule.\n\n#### [Jobs](https://docs.github.com/en/actions/about-github-actions/understanding-github-actions#jobs)\n\nA job is a set of steps in a workflow that is executed on the same runner. Each step is either a shell script that will be executed, or an action that will be run. Steps are executed in order and are dependent on each other. Since each step is executed on the same runner, you can share data from one step to another.\n\n#### [Steps / Actions](https://docs.github.com/en/actions/about-github-actions/understanding-github-actions#actions)\n\nA step can be a script that will be executed or a GitHub action.\n\n#### [Runners](https://docs.github.com/en/actions/about-github-actions/understanding-github-actions#runners)\n\nA runner is a server that runs your workflows when they're triggered. Each runner can run a single job at a time.\n\n* GHR: GitHub-Hosted Runner\n* SHR: Self-Hosted Runner\n\n### Action: Marketplace Action, Custom Actions (Composite Action)\n\nAn action is a custom application for the GitHub Actions platform that performs a complex but frequently repeated task. Use an action to help reduce the amount of repetitive code that you write in your workflow files. \n\nAn action can pull your git repository from GitHub, set up the correct toolchain for your build environment, or set up the authentication to your cloud provider.\n\nYou can write your own actions, or you can find actions to use in your workflows in the [GitHub Marketplace](https://github.com/marketplace?type=actions).\n\nFor more information, see [Creating actions](https://docs.github.com/en/actions/creating-actions).\n\n### Runner: GitHub-Hosted Runner vs. Self-Hosted Runner\n\nYou can run your jobs on GitHub Hosted compute or you can host your own Self Hosted runners.\n\nThe standard runners GitHub offers are:\n* `ubuntu-latest`\n* `windows-latest`\n* `macos-latest`\n\nThere are also [Larger runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-larger-runners/about-larger-runners#specifications-for-general-larger-runners) for more demanding use cases.\n\n* [About Larger Runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-larger-runners)\n\n![Actions _ Overview   Tech Requirements Check](https://github.com/user-attachments/assets/89eb287f-e840-4ea6-8f0c-d3277fd5c941)\n\n#### Cost\n\nActions running on standard GitHub-hosted runners are free for public repositories and self-hosted runners are free for all repositories.\n\nFor private repositories, GitHub charges based on a [per-minute rate](https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#per-minute-rates). The cost is simply the number of minutes your job runs multiplied by the per-minute rate.\n\n\u003e [!TIP]\n\u003e GitHub always rounds up the time that a job runs to the nearest minute. For example, if your job runs for 61 seconds, GitHub will charge you for 2 minutes.\n\nYou are entitled to a certain amount of free minutes and storage based on your plan. If you exceed these limits, you will be charged for additional usage.\n\n| Plan | Storage | Minutes (per month) |\n|------|---------|-------------------|\n| GitHub Team | 2 GB | 3,000 |\n| GitHub Enterprise Cloud | 50 GB | 50,000 |\n\n\u003e [!NOTE]\n\u003e These minutes are ONLY applicable to standard runners (not larger runners).\n\u003e The above values are for `ubuntu-latest` runners.\n\u003e `windows-latest` are 2x the cost (25k free)\n\u003e `macos-latest` are 10x the cost (5k free).\n\u003e Logs and job summaries do not count towards storage usage.\n\n![alt text](images/Screenshot%202024-08-12%20at%2010.33.53 AM.png)\n\n### Autoscaling with self-hosted runners (ARC)\n\nYou can automatically increase or decrease the number of self-hosted runners in your environment in response to the webhook events you receive with a particular label.\n\n* [Autoscaling with self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/autoscaling-with-self-hosted-runners)\n* [actions-runner-controller](https://github.com/actions/actions-runner-controller)\n\n\u003c!-- ## GitHub Actions Ethos\n\n### Essence/Opinionation\n\n### Traceability\n\n### Reusability (DRY)\n\n### Ephemerality\n\n### Extensibility: Do Anything You Want\n\n### Easy to Get Started\n\n## How to Author Workflow Files --\u003e\n\n### The Developer Loop: Writing, Testing, Debugging\n\nWriting a workflow file is as simple as creating a `.yml` file in the `.github/workflows` directory of your repository.\n\nTo test your workflow file you will push it to your repository and navigate to the Actions tab to see the status of your workflow run.\n\nWhen the workflow run is complete you can view the logs of each step to see what happened.\n\n### GitHub CLI\n\nThe GitHub CLI brings GitHub to the terminal. It's also preinstalled on all GitHub runners!\n\nIf you need to quickly perform a GitHub task this is the easiest way to do it!\n\n\u003cdetails\u003e\n  \u003csummary\u003eComment on an issue\u003c/summary\u003e\n\n```yml\non:\n  issues:\n    types:\n      - opened\njobs:\n  comment:\n    runs-on: ubuntu-latest\n    steps:\n      - run: gh issue comment $ISSUE --body \"Thank you for opening this issue!\"\n        env:\n          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          ISSUE: ${{ github.event.issue.html_url }}\n```\n\u003c/details\u003e\n\nFor the list of available extensions for the gh cli, see the topic [`gh-extension`](https://github.com/topics/gh-extension).\n\n[Install](https://cli.github.com/)\n[Manual](https://cli.github.com/manual/)\n[Using GitHub CLI in workflows](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-github-cli-in-workflows)\n\n### VS Code extension\n\nThere is a VS Code extension that provides syntax highlighting, intellisense, and more! This is a must have when authoring workflows.\n\n[GitHub Actions Extension](https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-github-actions)\n\n![alt text](images/vscode-extension-1.png)\n\n### Copilot\n\nGitHub Copilot is an AI pair programmer that helps you write code faster and with less effort. It can be incredibly useful when writing GitHub Actions workflows. Leverage the completion or chat feature to get help with writing your workflows.\n\n[GitHub Copilot](https://copilot.github.com/)\n\n### Actions Loves JavaScript\n\nOne of the most popular languages for writing actions is JavaScript. This is because it is easy to get started with and has a lot of community support.\n\n#### GitHub Actions ToolKit\n\nThe GitHub Actions ToolKit provides a set of packages to make creating actions easier.\n\n* [Actions Toolkit](https://github.com/actions/toolkit?tab=readme-ov-file#readme)\n* [Creating a JavaScript action](https://docs.github.com/en/actions/creating-actions/creating-a-javascript-action)\n\n### Github-script\n\nThis action makes it easy to quickly write a script in your workflow that uses the GitHub API and the workflow run context. The GitHub Actions Toolkit is pre-installed and available for use in the script you write.\n\n\u003cdetails\u003e\n  \u003csummary\u003eWelcome a first-time contributor\u003c/summary\u003e\n\n```yml\non: pull_request_target\n\njobs:\n  welcome:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/github-script@v7\n        with:\n          script: |\n            // Get a list of all issues created by the PR opener\n            // See: https://octokit.github.io/rest.js/#pagination\n            const creator = context.payload.sender.login\n            const opts = github.rest.issues.listForRepo.endpoint.merge({\n              ...context.issue,\n              creator,\n              state: 'all'\n            })\n            const issues = await github.paginate(opts)\n\n            for (const issue of issues) {\n              if (issue.number === context.issue.number) {\n                continue\n              }\n\n              if (issue.pull_request) {\n                return // Creator is already a contributor.\n              }\n            }\n\n            await github.rest.issues.createComment({\n              issue_number: context.issue.number,\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              body: `**Welcome**, new contributor!\n\n                Please make sure you've read our [contributing guide](CONTRIBUTING.md) and we look forward to reviewing your Pull request shortly ✨`\n            })\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eDownload data from a URL\u003c/summary\u003e\n\n```yml\non: pull_request\n\njobs:\n  diff:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/github-script@v7\n        with:\n          script: |\n            const diff_url = context.payload.pull_request.diff_url\n            const result = await github.request(diff_url)\n            console.log(result)\n```\n\u003c/details\u003e\n\n### Expressions\n\nYou can use expressions to programmatically set environment variables in workflow files and access contexts. An expression can be any combination of literal values, references to a context, or functions. You can combine literals, context references, and functions using operators. For more information about contexts, see \"Contexts.\"\n\n#### Literals\n\nYou can use boolean, null, number, or string data types.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of literals\u003c/summary\u003e\n\n```yml\nenv:\n  myNull: ${{ null }}\n  myBoolean: ${{ false }}\n  myIntegerNumber: ${{ 711 }}\n  myFloatNumber: ${{ -9.2 }}\n  myHexNumber: ${{ 0xff }}\n  myExponentialNumber: ${{ -2.99e-2 }}\n  myString: Mona the Octocat\n  myStringInBraces: ${{ 'It''s open source!' }}\n```\n\u003c/details\u003e\n\n#### Operators\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of operators\u003c/summary\u003e\n\n```\nOperator\tDescription\n( )\tLogical grouping\n[ ]\tIndex\n.\tProperty de-reference\n!\tNot\n\u003c\tLess than\n\u003c=\tLess than or equal\n\u003e\tGreater than\n\u003e=\tGreater than or equal\n==\tEqual\n!=\tNot equal\n\u0026\u0026\tAnd\n||\tOr\n```\n\u003c/details\u003e\n\n\u003e [!TIP]\n\u003e You can use a ternary operator `condition ? true : false` as `${{ condition \u0026\u0026 true || false }}`.\n\n[Expressions](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/expressions)\n\n#### Functions\n\nYou can use functions to transform data or to perform operations.\n\n* [contains](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/expressions#contains)\n* [startswith](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/expressions#startswith)\n* [endsWith](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/expressions#endswith)\n* [format](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/expressions#format)\n* [join](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/expressions#join)\n* [toJson](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/expressions#tojson)\n* [fromJson](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/expressions#fromjson)\n* [hashFiles](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/expressions#hashfiles)\n\n#### Status Check functions\n\n* [success](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/expressions#success)\n* [always](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/expressions#always)\n* [cancelled](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/expressions#cancelled)\n* [failure](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/expressions#failure)\n\n## How to Trigger/Initiate Workflow Runs\n\nYou can configure your workflows to run when specific activity on GitHub happens, at a scheduled time, or when an event outside of GitHub occurs.\n\n* [Events that trigger workflows](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows)\n\n\u003c!-- ### Summary of Event Grid That Triggers Workflows --\u003e\n\n\u003c!-- ### Configuring Input (Activity Types): Conditionally Trigger --\u003e\n\n### Event: Workflow Dispatch\n\nWorkflows triggered by `workflow_dispatch` and `workflow_call` access their inputs using the inputs context.\n\nFor workflows triggered by `workflow_dispatch` inputs are available in the `github.event.inputs`. \n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of on.workflow_dispatch.inputs\u003c/summary\u003e\n\n```yml\non:\n  workflow_dispatch:\n    inputs:\n      logLevel:\n        description: 'Log level'\n        required: true\n        default: 'warning'\n        type: choice\n        options:\n        - info\n        - warning\n        - debug\n      tags:\n        description: 'Test scenario tags'\n        required: false\n        type: boolean\n      environment:\n        description: 'Environment to run tests against'\n        type: environment\n        required: true\n\njobs:\n  log-the-inputs:\n    runs-on: ubuntu-latest\n    steps:\n      - run: |\n          echo \"Log level: $LEVEL\"\n          echo \"Tags: $TAGS\"\n          echo \"Environment: $ENVIRONMENT\"\n        env:\n          LEVEL: ${{ inputs.logLevel }}\n          TAGS: ${{ inputs.tags }}\n          ENVIRONMENT: ${{ inputs.environment }}\n```\n\u003c/details\u003e\n\n* [`workflow_dispatch` event](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflow_dispatch)\n* [`inputs` context](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/contexts#inputs-context)\n\n### Event: Workflow Call\nWorkflows triggered by `workflow_call` access their inputs using the `inputs` context.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of on.workflow_call.outputs\u003c/summary\u003e\n\n```yml\non:\n  workflow_call:\n    # Map the workflow outputs to job outputs\n    outputs:\n      workflow_output1:\n        description: \"The first job output\"\n        value: ${{ jobs.my_job.outputs.job_output1 }}\n      workflow_output2:\n        description: \"The second job output\"\n        value: ${{ jobs.my_job.outputs.job_output2 }}\n```\n\u003c/details\u003e\n\n* [`workflow_call` event](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflow_call)\n* [`inputs` context](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/contexts#inputs-context)\n\n### Event: Workflow Run\n\nThe `workflow_run` event allows you to execute a workflow based on execution or completion of another workflow.\n\n\u003cdetails\u003e\n  \u003csummary\u003eRunning a workflow based on the conclusion of another workflow\u003c/summary\u003e\n\n```yml\non:\n  workflow_run:\n    workflows: [Build]\n    types: [completed]\n\njobs:\n  on-success:\n    runs-on: ubuntu-latest\n    if: ${{ github.event.workflow_run.conclusion == 'success' }}\n    steps:\n      - run: echo 'The triggering workflow passed'\n  on-failure:\n    runs-on: ubuntu-latest\n    if: ${{ github.event.workflow_run.conclusion == 'failure' }}\n    steps:\n      - run: echo 'The triggering workflow failed'\n```\n\u003c/details\u003e\n\n### Event: Schedule\n\nThe `schedule` event allows you to trigger a workflow at a scheduled time.\n\n\u003cdetails\u003e\n  \u003csummary\u003eRunning a workflow on a schedule\u003c/summary\u003e\n\n```yml\non:\n  schedule:\n            ┌───────────── minute (0 - 59)\n            │ ┌───────────── hour (0 - 23)\n            │ │ ┌───────────── day of the month (1 - 31)\n            │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)\n            │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)\n            │ │ │ │ │\n            │ │ │ │ │\n            │ │ │ │ │\n    - cron: * * * * *\n```\n\u003c/details\u003e\n\n### Non-Core CI/CD Use Cases\n\nUnderstand that there are many ways to use GitHub Actions beyond CI/CD. For example, you can use GitHub Actions to:\n* \n\n### Concurrency: Order of Workflow Runs Based on When Trigger Happened\n\nGitHub Actions also allows you to control the concurrency of workflow runs, so that you can ensure that only one run, one job, or one step runs at a time in a specific context.\n\n\u003e [!NOTE]\n\u003e This is NOT a queueing system. If you have a lot of workflow runs that are waiting to run, they will be run in the order that they were triggered.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample: Concurrency groups\u003c/summary\u003e\n\n```yml\non:\n  push:\n    branches:\n      - main\n\nconcurrency:\n  group: ci-${{ github.ref }}\n  cancel-in-progress: true\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample: Using concurrency to cancel any in-progress job or run\u003c/summary\u003e\n\n```yml\nconcurrency:\n  group: ${{ github.ref }}\n  cancel-in-progress: true\n```\n\u003c/details\u003e\n\nYou can make the concurrency group as specific as you want. For example, you could use the branch name, the branch name and the event type, or the branch name and the event type and the workflow name.\n\n### Re-running Workflows / Retries\n\nYou can re-run a workflow run from the Actions UI. This is useful if you want to re-run a failed workflow run, or if you want to re-run a successful workflow run.\n\nRetrying a job programmatically is not officially supported but can be achieved using something like a [marketplace action](https://github.com/marketplace?query=retry)\n\n## How to Structure/Manage Jobs in the Workflow\n\n### Parallelization of Jobs\n\nBy default all jobs in a workflow run in parallel. You can control the order of jobs by specifying dependencies.\n\n### Matrices\n\nA matrix strategy is a great way to run the same job multiple times with different inputs. This is useful if you want to run your tests on multiple versions of a language, or if you want to run your tests on multiple operating systems.\n\n\u003e [!NOTE]\n\u003e The maximum number of jobs that can be used in a matrix strategy is 256.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of a matrix strategy\u003c/summary\u003e\n\n```yml\njobs:\n  example_matrix:\n    strategy:\n      matrix:\n        version: [10, 12, 14]\n        os: [ubuntu-latest, windows-latest]\n```\n\u003c/details\u003e\n\n* [Using a matrix for your jobs](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-a-matrix-for-your-jobs)\n\n### Ordering Jobs\n\nYou can define the order of the jobs using the `needs` keyword. This is useful if you want to run a job that depends on the output of another job.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of linking jobs\u003c/summary\u003e\n\n```yml\njobs:\n  job1:\n  job2:\n    needs: job1\n  job3:\n    needs: [job1, job2]\n    steps:\n      - run: echo ${{ needs.job1.outputs.myOutput }}\n```\n\u003c/details\u003e\n\n* [Defining prerequisite jobs](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-jobs-in-a-workflow#defining-prerequisite-jobs)\n\n### Job Timeouts\n\nYou can define a timeout for a job, and if the job takes longer than the timeout to run, the job will be cancelled.\n\nThe default timeout for a job is 6 hours or 360 minutes.\n\n\u003e [!NOTE]\n\u003e The `GITHUB_TOKEN` expires after the job finishes or 24 hours. This is a limiting factor for SHRs.\n\n* [`jobs.\u003cjob_id\u003e.steps[*].timeout-minutes`](https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstepstimeout-minutes)\n* [`jobs.\u003cjob_id\u003e.timeout-minutes`](https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes)\n\n### Running Jobs in Containers / Service Containers\n\nRunning in a container will not always be faster than running on a GHR. The time it takes to download the container image and start the container can be longer than the time it takes to start a job on a GHR.\n\n### Containers\n\nUse `jobs.\u003cjob_id\u003e.container` to create a container to run any steps in a job that don't already specify a container.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of running a job within a container\u003c/summary\u003e\n\n```yml\nname: CI\non:\n  push:\n    branches: [ main ]\njobs:\n  container-test-job:\n    runs-on: ubuntu-latest\n    container: \n      image: node:18\n      env:\n        NODE_ENV: development\n      ports:\n        - 80\n      volumes:\n        - my_docker_volume:/volume_mount\n      options: --cpus 1\n    steps:\n      - name: Check for dockerenv file\n        run: (ls /.dockerenv \u0026\u0026 echo Found dockerenv) || (echo No dockerenv)\n```\n\u003c/details\u003e\n\n\u003e [!TIP]\n\u003e You can omit the `image` keyword and use the short version `container: node:18` if you don't need to specify parameters.\n\n* [Running jobs in a container](https://docs.github.com/en/actions/writing-workflows/choosing-where-your-workflow-runs/running-jobs-in-a-container)\n\n#### Service Containers\n\nService containers let you run a container parallel to your job. This can be helpful if your job needs to talk to a database, for example.\n\n* [About service containers](https://docs.github.com/en/actions/use-cases-and-examples/using-containerized-services/about-service-containers)\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of using a service container\u003c/summary\u003e\n\n```yml\nname: Redis container example\non: push\n\njobs:\n  # Label of the container job\n  container-job:\n    # Containers must run in Linux based operating systems\n    runs-on: ubuntu-latest\n    # Docker Hub image that `container-job` executes in\n    container: node:16-bullseye\n\n    # Service containers to run with `container-job`\n    services:\n      # Label used to access the service container\n      redis:\n        # Docker Hub image\n        image: redis\n```\n\u003c/details\u003e\n\n#### Authenticating with a Container Registry\n\nSometimes you will need to authenticate with a container registry to pull an image. You can use the `credentials` keyword to do this.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of authenticating with a container registry\u003c/summary\u003e\n\n```yml\njobs:\n  build:\n    services:\n      redis:\n        # Docker Hub image\n        image: redis\n        ports:\n          - 6379:6379\n        credentials:\n          username: ${{ secrets.dockerhub_username }}\n          password: ${{ secrets.dockerhub_password }}\n      db:\n        # Private registry image\n        image:  ghcr.io/octocat/testdb:latest\n        credentials:\n          username: ${{ github.repository_owner }}\n          password: ${{ secrets.ghcr_password }}\n```\n\u003c/details\u003e\n\n* [Authenticating with image registries](https://docs.github.com/en/actions/use-cases-and-examples/using-containerized-services/about-service-containers#authenticating-with-image-registries)\n\n### Environments: Controls How/When a Job is Run Based on Protection Rules Set, Limits Branches, Scopes Secrets\n\nYou can create environments and secure those environments with deployment protection rules. A job that references an environment must follow any protection rules for the environment before running or accessing the environment's secrets.\n\nScoping secrets to an environment is very powerful because of the controls it gives you. You can limit which branches can access the secrets, and you can leverage the environment protection rules to control when a job can access the secrets.\n\n#### Environment Protection Rules\n\nDeployment protection rules require specific conditions to pass before a job referencing the environment can proceed.\n\n##### Required Reviewers\n\nYou can require that specific individuals or teams review a pull request before a job can proceed.\n\n##### Wait timer\n\nYou can delay a job for a specific amount of time before it can proceed.\n\n##### Branch restrictions\n\nYou can restrict which branches or tags can access the environment.\n\n##### Admin bypass\n\nYou can allow or disallow repository administrators to bypass the protection rules.\n\n##### Custom deployment protection rules\n\nYou can create custom deployment protection rules to gate deployments with third-party services.\n\n* [Deployment Protection Rules](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/managing-environments-for-deployment#deployment-protection-rules)\n* [Configuring custom deployment protection rules](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/configuring-custom-deployment-protection-rules)\n* [Environment Secrets](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/managing-environments-for-deployment#environment-secrets)\n\n### Conditional Jobs/Steps\n\nYou can use the `if` keyword to conditionally run a job or step.\n\n```yml\nif: ${{ ! startsWith(github.ref, 'refs/tags/') }}\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of conditional jobs\u003c/summary\u003e\n\n```yml\nname: example-workflow\non: [push]\njobs:\n  production-deploy:\n    if: github.repository == 'octo-org/octo-repo-prod'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version: '14'\n      - run: npm install -g bats\n```\n\u003c/details\u003e\n\n* [Using conditions to control job execution](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/using-conditions-to-control-job-execution)\n\n### Permissions for Jobs\n\nThere is a default token called `GITHUB_TOKEN` which by default has the permissions defined in your repositories Actions settings.\n\nIt's a good idea to limit permissions as much as possible by being explicit.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of limiting permissions\u003c/summary\u003e\n\n```yml\njobs:\n  stale:\n    runs-on: ubuntu-latest\n\n    permissions:\n      issues: write\n      pull-requests: write\n\n    steps:\n      - uses: actions/stale@v5\n```\n\u003c/details\u003e\n\n#### GitHub Apps\n\nUsing [actions/create-github-app-token](https://github.com/actions/create-github-app-token) you can get a token for a GitHub App. This is better than using a PAT because you get more control and you don't need to consume a license.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of using a GitHub App token\u003c/summary\u003e\n\n```yml\nname: Run tests on staging\non:\n  push:\n    branches:\n      - main\n\njobs:\n  hello-world:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/create-github-app-token@v1\n        id: app-token\n        with:\n          app-id: ${{ vars.APP_ID }}\n          private-key: ${{ secrets.PRIVATE_KEY }}\n      - uses: ./actions/staging-tests\n        with:\n          token: ${{ steps.app-token.outputs.token }}\n```\n\u003c/details\u003e\n\n* [Assigning permissions to jobs](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/assigning-permissions-to-jobs)\n* [Automatic token authentication](https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication)\n\n## How to Use and Create Actions (Marketplace)\n\n### What is an Action?\n\nActions are the building blocks that power your workflow. A workflow can contain one or more actions, either as individual steps or as part of an action group. An action is a reusable unit of code that can be used in multiple workflows. You can create your own actions, use actions created by the GitHub community, or use a combination of both.\n\n* [GitHub Actions Marketplace](https://github.com/marketplace?type=actions)\n\n### Types of Actions\n\nJavascript actions are the most popular and easiest to get started with, Docker containers package the environment with the GitHub Actions code, and Composite actions are a way to reuse actions in a more modular way.\n\nThere are three types of custom actions:\n* [JavaScript](https://docs.github.com/en/actions/creating-actions/creating-a-javascript-action)\n* [Docker](https://docs.github.com/en/actions/creating-actions/creating-a-docker-container-action) (Not available on macOS or Windows runners)\n* [Composite](https://docs.github.com/en/actions/creating-actions/creating-a-composite-run-steps-action)\n* [About custom actions](https://docs.github.com/en/actions/creating-actions/about-custom-actions)\n\n### Securing Usage of Actions\n\n* [Security hardening for GitHub Actions](https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions)\n\n### Creating Your Own Actions\n\nYou can create your own actions to use in your workflows. This is a great way to encapsulate logic that you want to reuse across multiple workflows.\n\n* [Creating actions](https://docs.github.com/en/actions/creating-actions)\n\n### Cool Actions to Look Out For: github-script, Anything by GitHub, Major Cloud Providers, Terraform, Docker\n\nHere are some popular actions to get you started:\n\n* [GitHub Script](https://github.com/actions/github-script)\n* [Awesome Actions](https://github.com/sdras/awesome-actions#readme)\n* [GitHub Authored Actions](https://github.com/marketplace?query=publisher%3Aactions)\n* [Azure Actions](https://github.com/marketplace?query=publisher%3Aazure)\n* [AWS Actions](https://github.com/marketplace?query=publisher%3Aaws-actions)\n* [GCP Actions](https://github.com/marketplace?query=publisher%3Agoogle-github-actions)\n* [Build and Push Docker Images](https://github.com/marketplace/actions/build-and-push-docker-images)\n\n## How to Organize, Share, and Scale Workflows\n\nOne of the most powerful features of GitHub Actions is the ability to share workflows across repositories. This is useful if you have a common workflow that you want to use in multiple repositories.\n\n### Reusable Workflows\n\nThese are reusable jobs. They are a great way to share common logic across multiple workflows or just to organize your workflow into smaller, more manageable pieces.\n\n#### Why?\n\n* Easier to maintain\n* Create workflows more quickly\n* Avoid duplication. DRY(don't repeat yourself).\n* Build consistently across multiple, dozens, or even hundreds of repositories\n* Require specific workflows for specific deployments\n* Promotes best practices\n* Abstract away complexity\n\n#### What can they do\n\n* Can have inputs and outputs\n* Can be nested 4 levels deep\n* Only 20 unique reusable workflows can be in a single workflow\n* Environment variables are not propagated to the reusable workflow\n* Secrets are scoped to the caller workflow\n* Secrets need to be passed to the reusable workflow\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of a reusable workflow\u003c/summary\u003e\n\n##### Defining the workflow (reusable-called.yml)\n\n```yml\non:\n  workflow_call:\n    inputs:\n      username:\n        default: ${{ github.actor }}\n        required: false\n        type: string\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Run a one-line script\n        run: echo Hello, ${{ inputs.username }}!\n```\n\n##### Using the workflow (caller.yml)\n\n```yml\njobs:\n  build:\n    uses: ./.github/workflows/reusable-called.yml\n    with:\n      username: ${{ github.actor }}\n```\n\n\u003c/details\u003e\n\n* [Reusing workflows](https://docs.github.com/en/actions/sharing-automations/reusing-workflows)\n* [Limitations](https://docs.github.com/en/actions/sharing-automations/reusing-workflows#limitations)\n\n### Composite Actions\n\nThese are reusable steps. Use a composite action to combine(re-use) multiple steps.\n\n\u003e [!TIP]\n\u003e These are far less limited than reusable workflows. Consider using composite actions over reusable workflows to start.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of a composite action\u003c/summary\u003e\n\n##### Defining the action (hello-world-composite-action.yml)\n\n```yml\nname: 'Hello World'\ndescription: 'Greet someone'\ninputs:\n  who-to-greet:  # id of input\n    description: 'Who to greet'\n    required: true\n    default: 'World'\noutputs:\n  random-number:\n    description: \"Random number\"\n    value: ${{ steps.random-number-generator.outputs.random-number }}\nruns:\n  using: \"composite\"\n  steps:\n    - name: Set Greeting\n      run: echo \"Hello $INPUT_WHO_TO_GREET.\"\n      shell: bash\n      env:\n        INPUT_WHO_TO_GREET: ${{ inputs.who-to-greet }}\n\n    - name: Random Number Generator\n      id: random-number-generator\n      run: echo \"random-number=$(echo $RANDOM)\" \u003e\u003e $GITHUB_OUTPUT\n      shell: bash\n\n    - name: Set GitHub Path\n      run: echo \"$GITHUB_ACTION_PATH\" \u003e\u003e $GITHUB_PATH\n      shell: bash\n      env:\n        GITHUB_ACTION_PATH: ${{ github.action_path }}\n\n    - name: Run goodbye.sh\n      run: goodbye.sh\n      shell: bash\n```\n\n##### Using the action (caller.yml)\n\n```yml\non: [push]\n\njobs:\n  hello_world_job:\n    runs-on: ubuntu-latest\n    name: A job to say hello\n    steps:\n      - uses: actions/checkout@v4\n      - id: foo\n        uses: OWNER/hello-world-composite-action@TAG\n        with:\n          who-to-greet: 'Mona the Octocat'\n      - run: echo random-number \"$RANDOM_NUMBER\"\n        shell: bash\n        env:\n          RANDOM_NUMBER: ${{ steps.foo.outputs.random-number }}\n```\n\n\u003c/details\u003e\n\n* [Creating a composite action](https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-composite-action)\n\n### Rulesets (Required workflows \u0026 Required checks)\n\nA new version of branch protection rules called rulesets allows you to require specific workflows to run before a pull request can be merged. These can be defined at the org level or the repo level.\n\n\u003e [!IMPORTANT]\n\u003e This means you can now create `pull_request` workflows at the organization level and apply them to some or all of your repos!\n\n* [Rulesets](https://docs.github.com/en/enterprise-cloud@latest/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets)\n* [Require workflows to pass before merging](https://docs.github.com/en/enterprise-cloud@latest/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets#require-workflows-to-pass-before-merging)\n* [Require status checks to pass before merging](https://docs.github.com/en/enterprise-cloud@latest/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets#require-status-checks-to-pass-before-merging)\n\n### Starter Workflows\n\nWorkflow templates allow everyone in your organization who has permission to create workflows to do so more quickly and easily. \n\nYou can create a workflow template by adding a `.github/workflow-templates` directory to your repository. Inside this directory, you can add one or more workflow templates. Each workflow template is a directory that contains a workflow file and a metadata file.\n\n\u003e [!NOTE]\n\u003e Because workflow templates require a public .github repository, they can not be private are not available for Enterprise Managed Users.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of a workflow template\u003c/summary\u003e\n\n`.github/workflow-templates/octo-organization-ci/octo-organization-ci.yml`\n\n```yml\nname: Octo Organization CI\n\non:\n  push:\n    branches: [ $default-branch ]\n  pull_request:\n    branches: [ $default-branch ]\n...\n```\n\n`.github/workflow-templates/octo-organization-ci/octo-organization-ci.properties.json`\n\n```yml\n{\n    \"name\": \"Octo Organization Workflow\",\n    \"description\": \"Octo Organization CI workflow template.\",\n    \"iconName\": \"example-icon\",\n    \"categories\": [\n        \"Go\"\n    ],\n    \"filePatterns\": [\n        \"package.json$\",\n        \"^Dockerfile\",\n        \".*\\\\.md$\"\n    ]\n}\n```\n\u003c/details\u003e\n\n### Managing Updates to Workflows/Actions\n\nKeeping your workflows and actions up to date is important. \n\n* The best practice is to use a commit sha to pin your actions to a specific commit because the sha is immutable (Ex: `mxschmitt/action-tmate@43767ec126ce819b2c3e6ac57a8951a7833e4ad7`)\n* You could also use a tag (Ex: `mxschmitt/action-tmate@v3`), but tags can be changed.\n* You could also use a branch (Ex: `mxschmitt/action-tmate@main`), but branches constantly change.\n\nA great way to manage updates to your workflows and actions is to use Dependabot. Dependabot will automatically create pull requests to update your workflows and actions when new versions are released. A big benefit of doing things this way is you can test changes before they are merged.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of using Dependabot to manage updates to your workflows and actions\u003c/summary\u003e\n\n`.github/dependabot.yml`\n```yml\n# Set update schedule for GitHub Actions\n\nversion: 2\nupdates:\n\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      # Check for updates to GitHub Actions every week\n      interval: \"weekly\"\n```\n\u003c/details\u003e\n\n* [Keeping your actions up to date with Dependabot](https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot)\n* [Configuration options for the dependabot.yml file](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file)\n\n### Monorepo vs Polyrepo\n\nGitHub Actions is obvious when dealing with a single repository, but what about when you have multiple repositories that depend on each other?\n\n#### Monorepo\n\nFor a monorepo you may not want to checkout, build, test, and deploy everything on every push. You may want to only build and test the things that have changed.\n\nYou can use [`on.\u003cpush|pull_request|pull_request_target\u003e.\u003cpaths|paths-ignore\u003e`](https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#onpushpull_requestpull_request_targetpathspaths-ignore) to trigger a workflow based on the files changed in a push or pull request.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of using paths to trigger a workflow based on the files changed\u003c/summary\u003e\n\n```yml\non:\n  push:\n    paths:\n      - 'sub-project/**'\n      - '!sub-project/docs/**'\n```\n\u003c/details\u003e\n\nThere are actions that let you check which files have changed so that you can conditionally run jobs.\n\n\u003cdetails\u003e\n  \u003csummary\u003edorny/paths-filter\u003c/summary\u003e\n\n```yml\njobs:\n  tests:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v4\n    - uses: dorny/paths-filter@v3\n      id: filter\n      with:\n        filters: |\n          backend:\n            - 'backend/**'\n          frontend:\n            - 'frontend/**'\n\n    # run only if 'backend' files were changed\n    - name: backend tests\n      if: steps.filter.outputs.backend == 'true'\n      run: ...\n\n    # run only if 'frontend' files were changed\n    - name: frontend tests\n      if: steps.filter.outputs.frontend == 'true'\n      run: ...\n\n    # run if 'backend' or 'frontend' files were changed\n    - name: e2e tests\n      if: steps.filter.outputs.backend == 'true' || steps.filter.outputs.frontend == 'true'\n      run: ...\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003etj-actions/changed-files\u003c/summary\u003e\n\n```yml\nname: CI\n\non:\n  pull_request:\n    branches:\n      - main\n\njobs:\n  # ------------------------------------------------------------------------------------------------------------------------------------------------\n  # Event `pull_request`: Compare the last commit of the main branch or last remote commit of the PR branch -\u003e to the current commit of a PR branch.\n  # ------------------------------------------------------------------------------------------------------------------------------------------------\n  changed_files:\n    runs-on: ubuntu-latest  # windows-latest || macos-latest\n    name: Test changed-files\n    steps:\n      - uses: actions/checkout@v4\n\n      # -----------------------------------------------------------------------------------------------------------\n      # Example 1\n      # -----------------------------------------------------------------------------------------------------------\n      - name: Get changed files\n        id: changed-files\n        uses: tj-actions/changed-files@v44\n        # To compare changes between the current commit and the last pushed remote commit set `since_last_remote_commit: true`. e.g\n        # with:\n        #   since_last_remote_commit: true \n\n      - name: List all changed files\n        env:\n          ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}\n        run: |\n          for file in ${ALL_CHANGED_FILES}; do\n            echo \"$file was changed\"\n          done\n\n      # -----------------------------------------------------------------------------------------------------------\n      # Example 2\n      # -----------------------------------------------------------------------------------------------------------\n      - name: Get all changed markdown files\n        id: changed-markdown-files\n        uses: tj-actions/changed-files@v44\n        with:\n          # Avoid using single or double quotes for multiline patterns\n          files: |\n             **.md\n\n      - name: List all changed files markdown files\n        if: steps.changed-markdown-files.outputs.any_changed == 'true'\n        env:\n          ALL_CHANGED_FILES: ${{ steps.changed-markdown-files.outputs.all_changed_files }}\n        run: |\n          for file in ${ALL_CHANGED_FILES}; do\n            echo \"$file was changed\"\n          done\n\n      # -----------------------------------------------------------------------------------------------------------\n      # Example 3\n      # -----------------------------------------------------------------------------------------------------------\n      - name: Get all test, doc and src files that have changed\n        id: changed-files-yaml\n        uses: tj-actions/changed-files@v44\n        with:\n          files_yaml: |\n            doc:\n              - '**.md'\n              - docs/**\n            test:\n              - test/**\n              - '!test/**.md'\n            src:\n              - src/**\n          # Optionally set `files_yaml_from_source_file` to read the YAML from a file. e.g `files_yaml_from_source_file: .github/changed-files.yml`\n\n      - name: Run step if test file(s) change\n        # NOTE: Ensure all outputs are prefixed by the same key used above e.g. `test_(...)` | `doc_(...)` | `src_(...)` when trying to access the `any_changed` output.\n        if: steps.changed-files-yaml.outputs.test_any_changed == 'true'  \n        env:\n          TEST_ALL_CHANGED_FILES: ${{ steps.changed-files-yaml.outputs.test_all_changed_files }}\n        run: |\n          echo \"One or more test file(s) has changed.\"\n          echo \"List all the files that have changed: $TEST_ALL_CHANGED_FILES\"\n      \n      - name: Run step if doc file(s) change\n        if: steps.changed-files-yaml.outputs.doc_any_changed == 'true'\n        env:\n          DOC_ALL_CHANGED_FILES: ${{ steps.changed-files-yaml.outputs.doc_all_changed_files }}\n        run: |\n          echo \"One or more doc file(s) has changed.\"\n          echo \"List all the files that have changed: $DOC_ALL_CHANGED_FILES\"\n\n      # -----------------------------------------------------------------------------------------------------------\n      # Example 4\n      # -----------------------------------------------------------------------------------------------------------\n      - name: Get changed files in the docs folder\n        id: changed-files-specific\n        uses: tj-actions/changed-files@v44\n        with:\n          files: docs/*.{js,html}  # Alternatively using: `docs/**`\n          files_ignore: docs/static.js\n\n      - name: Run step if any file(s) in the docs folder change\n        if: steps.changed-files-specific.outputs.any_changed == 'true'\n        env:\n          ALL_CHANGED_FILES: ${{ steps.changed-files-specific.outputs.all_changed_files }}\n        run: |\n          echo \"One or more files in the docs folder has changed.\"\n          echo \"List all the files that have changed: $ALL_CHANGED_FILES\"\n```\n\u003c/details\u003e\n\nYou may also leverage sparse checkout to only checkout the directories that have changed.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of using sparse checkout to only checkout the directories that have changed\u003c/summary\u003e\n\n```yml\n- uses: actions/checkout@v4\n  with:\n    sparse-checkout: |\n      .github\n      src\n```\n\u003c/details\u003e\n\n\n* [Using conditions to control job execution](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/using-conditions-to-control-job-execution)\n\n#### Polyrepo\n\nFor a polyrepo you have the opposite problem and may need to pull in code or artifacts from other repositories.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of checkout multiple repos\u003c/summary\u003e\n\n```yml\n- name: Checkout\n  uses: actions/checkout@v4\n  with:\n    path: main\n\n- name: Checkout private tools\n  uses: actions/checkout@v4\n  with:\n    repository: my-org/my-private-tools\n    token: ${{ secrets.GH_PAT }} # `GH_PAT` is a secret that contains your PAT\n    path: my-tools\n```\n\u003c/details\u003e\n\n## Artifacts\n\nThe [actions/upload-artifact](https://github.com/actions/upload-artifact) and [download-artifact](https://github.com/actions/download-artifact) actions enable you to save output from a job. The artifact will also be visible in the Actions UI under the job summary, at the bottom.\n\n### Retention Periods\nArtifacts have a retention period which determines when they will expire and be deleted. You can specify this retention period at the organization, repository, or workflow level.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of a custom retention period\u003c/summary\u003e\n\n```yml\n  - name: 'Upload Artifact'\n    uses: actions/upload-artifact@v4\n    with:\n      name: my-artifact\n      path: my_file.txt\n      retention-days: 5\n```\n\u003c/details\u003e\n\n### Sharing Artifacts Between Jobs\n\nYou might want to use artifacts to share data between jobs. For example you could build your project and save it as an artifact, and then deploy the artifact in a separate job.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of sharing artifacts between jobs\u003c/summary\u003e\n\n```yml\nname: Share data between jobs\n\non: [push]\n\njobs:\n  job_1:\n    name: Add 3 and 7\n    runs-on: ubuntu-latest\n    steps:\n      - shell: bash\n        run: |\n          expr 3 + 7 \u003e math-homework.txt\n      - name: Upload math result for job 1\n        uses: actions/upload-artifact@v4\n        with:\n          name: homework_pre\n          path: math-homework.txt\n\n  job_2:\n    name: Multiply by 9\n    needs: job_1\n    runs-on: windows-latest\n    steps:\n      - name: Download math result for job 1\n        uses: actions/download-artifact@v4\n        with:\n          name: homework_pre\n      - shell: bash\n        run: |\n          value=`cat math-homework.txt`\n          expr $value \\* 9 \u003e math-homework.txt\n      - name: Upload math result for job 2\n        uses: actions/upload-artifact@v4\n        with:\n          name: homework_final\n          path: math-homework.txt\n\n  job_3:\n    name: Display results\n    needs: job_2\n    runs-on: macOS-latest\n    steps:\n      - name: Download math result for job 2\n        uses: actions/download-artifact@v4\n        with:\n          name: homework_final\n      - name: Print the final result\n        shell: bash\n        run: |\n          value=`cat math-homework.txt`\n          echo The result is $value\n```\n\u003c/details\u003e\n\n* [Storing and sharing data from a workflow](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/storing-and-sharing-data-from-a-workflow)\n* [Passing data between jobs in a workflow](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/storing-workflow-data-as-artifacts#passing-data-between-jobs-in-a-workflow)\n\n### Artifact Attestations\n\nLeverage artifact attestations to create unfalsifiable provenance and integrity guarantees for the software you build.\n\n* [Using artifact attestations to establish provenance for builds](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds)\n\n## Caching\n\nGitHub Actions has a 10Gb rotating cache that you can leverage for any use case. This is usually used to speed up workflows.\n\n\u003e [!NOTE]\n\u003e GitHub will remove any cache entries that have not been accessed in over 7 days. There is no limit on the number of caches you can store, but the total size of all caches in a repository is limited to 10 GB. Once a repository has reached its maximum cache storage, the cache eviction policy will create space by deleting the oldest caches in the repository.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of caching dependencies to speed up workflows\u003c/summary\u003e\n\n#### Gradle\n\n```yml\n- name: Cache Gradle packages\n  uses: actions/cache@v3\n  with:\n    path: |\n      ~/.gradle/caches\n      ~/.gradle/wrapper\n```\n\n#### NPM Cache\n  \n```yml\nname: NPM Cache Install\ndescription: NPM clean install with caching\n\nruns:\n  using: \"composite\"\n\n  steps:\n    - uses: actions/cache@v4\n      id: cache-nodemodules\n      env:\n        cache-name: cache-node-modules\n      with:\n        path: node_modules\n        key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}\n        restore-keys: |\n          ${{ runner.os }}-build-${{ env.cache-name }}-\n          ${{ runner.os }}-build-\n          ${{ runner.os }}-\n    - run: npm ci\n      if: steps.cache-nodemodules.outputs.cache-hit != 'true'\n      shell: bash\n```\n\u003c/details\u003e\n\n* [Caching dependencies to speed up workflows](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/caching-dependencies-to-speed-up-workflows)\n\n## Secrets\n\nSecrets are variables that you create in an organization, repository, or repository environment. The secrets that you create are available to use in a GitHub Actions workflows. GitHub Actions can only read a secret if you explicitly include the secret in a workflow.\n\nGitHub redacts secrets from logs, but you should still be careful about what you log.\n\nSensitive secrets should leverage environments because environments have protection rules that can be used to gate access to the secrets. This includes which branch the secret can be accessed from. If you combine this with branch protection rules you can create a very secure system.\n\n* [Using secrets](https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions#using-secrets)\n\n### Reusable Workflows and Secrets\n\nYou must explicitly pass secrets to a reusable workflow. This is because secrets are scoped to the caller workflow.\n\n### OIDC Access to Cloud Environments\n\nGitHub Actions can now use OIDC tokens to authenticate to cloud environments. This is a more secure way to authenticate to cloud environments than using a PAT.\n\n* [About security hardening with OpenID Connect](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect)\n\n### Integrating with 3rd Party Key Vaults/HSMs\n\nThere are third-party actions on the marketplace that will allow you to integrate with key vaults and HSMs.\n\n\u003cdetails\u003e\n  \u003csummary\u003ehashicorp/hashicorp-vault\u003c/summary\u003e\n\n```yml\njobs:\n    build:\n        # ...\n        steps:\n            # ...\n            - name: Import Secrets\n              id: import-secrets\n              uses: hashicorp/vault-action@v2\n              with:\n                url: https://vault.mycompany.com:8200\n                token: ${{ secrets.VAULT_TOKEN }}\n                caCertificate: ${{ secrets.VAULT_CA_CERT }}\n                secrets: |\n                    secret/data/ci/aws accessKey | AWS_ACCESS_KEY_ID ;\n                    secret/data/ci/aws secretKey | AWS_SECRET_ACCESS_KEY ;\n                    secret/data/ci npm_token\n            # ...\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eAzure/cli\u003c/summary\u003e\n\n[Quickstart: Set and retrieve a secret from Azure Key Vault using Azure CLI](https://learn.microsoft.com/en-us/azure/key-vault/secrets/quick-create-cli)\n```yml\n  build-and-deploy:\n    runs-on: ubuntu-latest\n    steps:\n    - name: Azure Login\n      uses: azure/login@v2\n      with:\n        creds: ${{ secrets.AZURE_CREDENTIALS }}\n\n    - name: Azure CLI script\n      uses: azure/cli@v2\n      with:\n        azcliversion: latest\n        inlineScript: |\n          az keyvault secret show --name \"ExamplePassword\" --vault-name \"\u003cyour-unique-keyvault-name\u003e\" --query \"value\"\n```\n\u003c/details\u003e\n\n## How to Create and Manage Runners\n\nThere are two types of runners: self-hosted and GitHub-hosted. GitHub has standardized runners for you, but you can also create larger runners with more resources.\n\n### Ephemeral\n\nGitHub runners are ephemeral meaning they are created on the fly and destroyed when the job is complete. This is the default behavior for GitHub-hosted runners.\n\n\u003c!-- ### Based on Azure --\u003e\n\n### Types and Sizes of Runners\n\n| CPU | Memory (RAM) | Storage (SSD) | Architecture | Operating system (OS) |\n|-----|--------------|---------------|--------------|------------------------|\n| 6   | 14 GB        | 14 GB         | arm64        | macOS                  |\n| 12  | 30 GB        | 14 GB         | x64          | macOS                  |\n| 2   | 8 GB         | 75 GB         | x64, arm64   | Ubuntu                 |\n| 4   | 16 GB        | 150 GB        | x64, arm64   | Ubuntu, Windows        |\n| 8   | 32 GB        | 300 GB        | x64, arm64   | Ubuntu, Windows        |\n| 16  | 64 GB        | 600 GB        | x64, arm64   | Ubuntu, Windows        |\n| 32  | 128 GB       | 1200 GB       | x64, arm64   | Ubuntu, Windows        |\n| 64  | 208 GB       | 2040 GB       | arm64        | Ubuntu, Windows        |\n| 64  | 256 GB       | 2040 GB       | x64          | Ubuntu, Windows        |\n\n\u003e [!NOTE]\n\u003e The 4-vCPU Windows runner only works with the Windows 11 Desktop image.\n\n\u003e [!NOTE]\n\u003e Note: arm64 runners are currently in beta and subject to change.\n\nGPU runners are also available.\n\n| CPU | GPU | GPU card | Memory (RAM) | GPU memory (VRAM) | Storage (SSD) | Operating system (OS) |\n|-----|-----|----------|--------------|-------------------|---------------|------------------------|\n| 4   | 1   | Tesla T4 | 28 GB        | 16 GB             | 176 GB        | Ubuntu, Windows        |\n\n### Auto-scaling and Scale Limits\n\nIf you hit scaling limits you can ask your AM or support to increase your concurrency limit.\n\n* [Usage Limits](https://docs.github.com/en/actions/administering-github-actions/usage-limits-billing-and-administration#usage-limits)\n\n### ARC: Actions Runtime Configuration\n\nYou can automatically scale your self-hosted runners in response to webhook events.\n\n* [Autoscaling with self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/autoscaling-with-self-hosted-runners)\n\n### Runner Groups\n\nRunner groups simply allow you to manage which runners are available to which repositories. This is useful if you have a runner that is only available to a specific team.\n\n* [Managing access to self-hosted runners using groups](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/managing-access-to-self-hosted-runners-using-groups)\n\n\u003c!-- ### Managed Runner GHR Images and Custom GHR Images --\u003e\n\n### GHR Networking\n\nBy default, GitHub-hosted runners have access to the public internet. However, you may also want these runners to access resources on your private network, such as a package registry, a secret manager, or other on-premise services.\n\n* [Connecting to a private network with GitHub-hosted runners](https://docs.github.com/en/actions/using-github-hosted-runners/connecting-to-a-private-network)\n\n#### API Gateways\n\nYou could run an API gateway on the edge of your private network that authenticates incoming requests with the OIDC token and then makes API requests on behalf of your workflow in your private network.\n\n* [Using an API gateway with OIDC](https://docs.github.com/en/actions/using-github-hosted-runners/connecting-to-a-private-network/using-an-api-gateway-with-oidc)\n\n#### Wireguard\n\n* [Using WireGuard to create a network overlay](https://docs.github.com/en/actions/using-github-hosted-runners/connecting-to-a-private-network/using-wireguard-to-create-a-network-overlay)\n\n#### Static IPs\n\nYou have the option to create static IP addresses for your GitHub-hosted runners. This is useful if you need to whitelist the IP address of your runner in a firewall rule, for example.\n\n* [Creating static IP addresses for larger runners](https://docs.github.com/en/actions/using-github-hosted-runners/using-larger-runners/managing-larger-runners#creating-static-ip-addresses-for-larger-runners)\n\n#### VNET Injection (Azure Private Networking)\n\nYou can use VNET injection to connect your GitHub-hosted runners to your Azure virtual network.\n\n* [Configuring private networking for GitHub-hosted runners in your enterprise](https://docs.github.com/en/enterprise-cloud@latest/admin/configuring-settings/configuring-private-networking-for-hosted-compute-products/configuring-private-networking-for-github-hosted-runners-in-your-enterprise)\n\n### Runner Labels\n\nYou label your runners to make it easier to target them in your workflows.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of using multiple runner labels\u003c/summary\u003e\n\n```yml\nruns-on: [self-hosted, linux, x64, gpu]\n```\n\u003c/details\u003e\n\n* [Choosing the runner for a job](https://docs.github.com/en/enterprise-cloud@latest/actions/writing-workflows/choosing-where-your-workflow-runs/choosing-the-runner-for-a-job)\n* [Using labels with self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/using-labels-with-self-hosted-runners)\n\n## How to Govern Usage\n\n* [Enforcing policies for GitHub Actions in your enterprise](https://docs.github.com/en/enterprise-cloud@latest/admin/enforcing-policies/enforcing-policies-for-your-enterprise/enforcing-policies-for-github-actions-in-your-enterprise)\n\n### Rulesets\n\nRulesets are the new and improved branch protection rules, and configurable at the organization level! Rulesets help you to control how people can interact with branches and tags in a repository.\n\nYou can grant bypass permission for individuals, teams, apps, or roles.\n\nYou can evaluate rulesets before you make them active and monitor the impact of the ruleset on your organization.\n\n* [Available rules for rulesets](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets)\n\n### Branch \u0026 Tag Rulesets\n\nBranch rulesets allow you to control how people interact with branches.\n\nOne of the most powerful features of branch rulesets is the ability to require a workflow to pass before a pull request can be merged. This gives you the ability to enforce policies at the organization level.\n\n### Push Rulesets\n\nYou can create push rulesets to block pushes to private or internal repositories and those repository's entire fork network.\n\nSome common use cases include:\n1. Preventing anyone except from CI/CD admins from pushing to the `.github/**/*` directory.\n2. Restricting the accidental push of files like .env or .pem. Similar to a gitignore file, you can use a push ruleset to block pushes of files with specific names or extensions but at the server level.\n3. Prevent large files from being pushed to your repositories.\n4. Restrict file path length.\n\n* [Push rulesets](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets#push-rulesets)\n\n### Environment Protection Rules: Custom Gating\n\nEnvironment protection rules allow you to protect a job from running. This is useful if you have a sensitive job that you'd like to put controls around.\n\n#### Required reviewers\n\nYou can require a specific number of reviewers to approve a job before it can run.\n\n#### Wait timer\n\nYou can delay a job for a specified amount of time. This is useful if you want to give people a chance to cancel a job.\n\n#### Custom gating\n\nThere are existing deployment protection rules via GitHub Apps. You can also create your own custom deployment protection rules.\n\n* [Deployment protection rules](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/managing-environments-for-deployment#deployment-protection-rules)\n* [Configuring custom deployment protection rules](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/configuring-custom-deployment-protection-rules)\n* [Creating custom deployment protection rules](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/creating-custom-deployment-protection-rules)\n\n### Spending Limits and Budgets/Cost Centers\n\nIt's always a good idea to set spending limits to avoid accidents.\n\n* [Managing your spending limit for GitHub Actions](https://docs.github.com/en/enterprise-cloud@latest/billing/managing-billing-for-your-products/managing-billing-for-github-actions/managing-your-spending-limit-for-github-actions)\n\n### Actions Policies\n\n### Allow List for Marketplace Actions\n\nYou can allow only a specific list of actions to be used in your organization. This is useful if you want to prevent people from using actions that are not approved.\n\nWildcards are available and there are convenient toggles for github authored actions as well as actions created by verified creators.\n\n* [Allowing select actions and reusable workflows to run](https://docs.github.com/en/organizations/managing-organization-settings/disabling-or-limiting-github-actions-for-your-organization#allowing-select-actions-and-reusable-workflows-to-runn)\n\n### Enable/Disable Actions\n\nYou can choose to disable GitHub Actions or limit it to actions and reusable workflows in your organization.\n\n* [Disabling or limiting GitHub Actions for your organization](https://docs.github.com/en/organizations/managing-organization-settings/disabling-or-limiting-github-actions-for-your-organization)\n\n### Audit Log\n\nBecause of the enormous amount of events that can be generated by GitHub Actions, it is not always feasible to query the API for all events. Instead, you can stream the audit log to a SIEM or other log management solution.\n\n* [Streaming the audit log for your enterprise](https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/streaming-the-audit-log-for-your-enterprise)\n* [Audit log events for your enterprise](https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise)\n\n### Status Checks\n\nStatus checks let you know if your commits meet the conditions set for the repository you're contributing to.\n\nYou can see the pending, passing, or failing state of status checks next to individual commits in your pull request. \n\nA job that is skipped will report its status as \"Success\". It will not prevent a pull request from merging, even if it is a required check.\n\n* [About status checks](https://docs.github.com/en/enterprise-cloud@latest/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks)\n\n## How to Observe What’s Going on with CI/CD\n\nThere are many ways to monitor and observe your GitHub Actions workflows. GitHub has minimal native functionality for this, but there are many third-party tools that can help you monitor your workflows. Everything is available via APIs and webhooks, so you can build your own monitoring solution.\n\n* [Monitoring workflows](https://docs.github.com/en/enterprise-cloud@latest/actions/monitoring-and-troubleshooting-workflows/monitoring-workflows)\n\n### Actions Usage Metrics \u0026 Performance Metrics\n\nOrganization level metrics to help you identify usage and performance issues with GitHub Actions.\n\nUnder your organization insights you will find two tabs for GitHub Actions metrics: usage and performance.\n\n[Actions usage metrics](https://docs.github.com/en/enterprise-cloud@latest/organizations/collaborating-with-groups-in-organizations/viewing-github-actions-metrics-for-your-organization#about-github-actions-usage-metrics) help you analyze actions minutes usage.\n\n[Actions performance metrics](https://docs.github.com/en/enterprise-cloud@latest/organizations/collaborating-with-groups-in-organizations/viewing-github-actions-metrics-for-your-organization#about-github-actions-performance-metrics) enables you to analyze the efficiency and reliability of your workflows.\n\n* [Viewing GitHub Actions metrics for your organization](https://docs.github.com/en/enterprise-cloud@latest/organizations/collaborating-with-groups-in-organizations/viewing-github-actions-metrics-for-your-organization)\n\n### Job Summaries\n\nJob summaries are custom markdown associated with a job. This is a great place to provide a summary of the job such as test results, code coverage, or any other information that is relevant to the job.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of adding a job summary\u003c/summary\u003e\n\n```bash\necho \"### Hello world! :rocket:\" \u003e\u003e $GITHUB_STEP_SUMMARY\n```\n\u003c/details\u003e\n\nIf you're using JS the [Actions Toolkit](https://github.com/actions/toolkit#readme) provides a way to create job summaries using the `@actions/core` package.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of adding a job using actions toolkit\u003c/summary\u003e\n\n```js\n// Write raw text, optionally add an EOL after the content, defaults to false\ncore.summary.addRaw('Some content here :speech_balloon:', true)\n// Output: Some content here :speech_balloon:\\n\n\n// Add an operating system-specific end-of-line marker\ncore.summary.addEOL()\n// Output (POSIX): \\n\n// Output (Windows): \\r\\n\n\n// Add a codeblock with an optional language for syntax highlighting\ncore.summary.addCodeBlock('console.log(\\'hello world\\')', 'javascript')\n// Output: \u003cpre lang=\"javascript\"\u003e\u003ccode\u003econsole.log('hello world')\u003c/code\u003e\u003c/pre\u003e\n\n// Add a list, second parameter indicates if list is ordered, defaults to false\ncore.summary.addList(['item1','item2','item3'], true)\n// Output: \u003col\u003e\u003cli\u003eitem1\u003c/li\u003e\u003cli\u003eitem2\u003c/li\u003e\u003cli\u003eitem3\u003c/li\u003e\u003c/ol\u003e\n\n// Add a collapsible HTML details element\ncore.summary.addDetails('Label', 'Some detail that will be collapsed')\n// Output: \u003cdetails\u003e\u003csummary\u003eLabel\u003c/summary\u003eSome detail that will be collapsed\u003c/details\u003e\n\n// Add an image, image options parameter is optional, you can supply one of or both width and height in pixels\ncore.summary.addImage('example.png', 'alt description of img', {width: '100', height: '100'})\n// Output: \u003cimg src=\"example.png\" alt=\"alt description of img\" width=\"100\" height=\"100\"\u003e\n\n// Add an HTML section heading element, optionally pass a level that translates to 'hX' ie. h2. Defaults to h1\ncore.summary.addHeading('My Heading', '2')\n// Output: \u003ch2\u003eMy Heading\u003c/h2\u003e\n\n// Add an HTML thematic break \u003chr\u003e\ncore.summary.addSeparator()\n// Output: \u003chr\u003e\n\n// Add an HTML line break \u003cbr\u003e\ncore.summary.addBreak()\n// Output: \u003cbr\u003e\n\n// Add an HTML blockquote with an optional citation\ncore.summary.addQuote('To be or not to be', 'Shakespeare')\n// Output: \u003cblockquote cite=\"Shakespeare\"\u003eTo be or not to be\u003c/blockquote\u003e\n\n// Add an HTML anchor tag\ncore.summary.addLink('click here', 'https://github.com')\n// Output: \u003ca href=\"https://github.com\"\u003eclick here\u003c/a\u003e\n```\n\u003c/details\u003e\n\n* [Adding a job summary](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#adding-a-job-summary)\n* [Populating job summary](https://github.com/actions/toolkit/tree/main/packages/core#populating-job-summary)\n\n### Alerting/Notifications: Finished, Failed\n\nYou may want to be notified when a workflow run finishes or fails.\n\n#### GitHub Email \u0026 Web Notifications\n\nGitHub sends email and web [notifications for workflow runs](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/monitoring-workflows/notifications-for-workflow-runs) you trigger. The notifications are for status (successful, failed, neutral, and canceled runs).\n\n#### GitHub Actions Notifications\n\nYou can send the notification in the workflow itself.\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of notification on workflow failure\u003c/summary\u003e\n\n```yml\non:\n  workflow_run:\n    workflows: [Build]\n    types: [completed]\n\njobs:\n  slack:\n    runs-on: ubuntu-latest\n    steps:\n    - name: Post a message in a channel\n      uses: slackapi/slack-github-action@v2.1.0\n      with:\n        webhook: ${{ secrets.SLACK_WEBHOOK_URL }}\n        webhook-type: incoming-webhook\n        payload: |\n          text: \"*GitHub Action build result*: ${{ github.event.workflow_run.conclusion }}\\n${{ github.event.pull_request.html_url || github.event.head_commit.url }}\"\n          blocks:\n            - type: \"section\"\n              text:\n                type: \"mrkdwn\"\n                text: \"GitHub Action build result: ${{ github.event.workflow_run.conclusion }}\\n${{ github.event.pull_request.html_url || github.event.head_commit.url }}\"\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample of notification on job failure\u003c/summary\u003e\n\n```yml\njobs:\n  job1:\n  job2:\n    needs: job1\n  job3:\n    if: ${{ always() }}\n    needs: [job1, job2]\n    steps:\n    - name: Post a message in a channel\n      uses: slackapi/slack-github-action@v2.1.0\n      with:\n        webhook: ${{ secrets.SLACK_WEBHOOK_URL }}\n        webhook-type: incoming-webhook\n        payload: |\n          text: \"*GitHub Action build result*: ${{ job.status }}\\n${{ github.event.pull_request.html_url || github.event.head_commit.url }}\"\n          blocks:\n            - type: \"section\"\n              text:\n                type: \"mrkdwn\"\n                text: \"GitHub Action build result: ${{ job.status }}\\n${{ github.event.pull_request.html_url || github.event.head_commit.url }}\"\n```\n\n\u003c/details\u003e\n\n* [Slack Send GitHub Action](https://github.com/marketplace/actions/slack-send-to-slack)\n\n### GitHub Apps\n\nThere are many GitHub Apps that can help you monitor your workflows. Some of these apps can send notifications to Slack, Microsoft Teams, or other chat platforms.\n\n* [Microsoft Teams for GitHub](https://github.com/marketplace/microsoft-teams-for-github)\n* [Slack + GitHub](https://github.com/marketplace/slack-github)\n\n#### Webhooks\n\nYou can also configure webhooks to send notifications to a third-party service. \n\n* [Webhooks](https://docs.github.com/en/webhooks)\n* [workflow_run](https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_run)\n* [workflow_job](https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_job)\n* [workflow_dispatch](https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_dispatch)\n\n### 3rd Party Tools: DataDog, Trunk, etc.\n\nThere are many third-party tools that provide a richer monitoring experience for GitHub Actions. These tools can provide insights into your workflows, such as run history, performance metrics, and more.\n\n#### [Datadog](https://docs.datadoghq.com/continuous_integration/pipelines/github/)\n\nDatadog provides great CI visibility and monitoring capabilities.\n\n* [Set up CI Visibility on GitHub Actions Workflows](https://docs.datadoghq.com/continuous_integration/pipelines/github/)\n* [Blog: Monitor your CI pipelines and tests with Datadog CI Visibility](https://www.datadoghq.com/blog/datadog-ci-visibility/)\n* [Blog: Monitor your GitHub Actions workflows with Datadog CI Visibility](https://www.datadoghq.com/blog/datadog-github-actions-ci-visibility/)\n\n#### [Trunk](https://trunk.io/flaky-tests)\n\nTrunk detects, quarantines, and eliminates flaky tests from your code base. Works with any language, any test runner, and any CI provider.\n\n### Stats on Runner Utilization\n\nThere is no native solution to monitor CPU, Disk, and Memory usage of your GitHub Actions runners. You can use third-party tools to monitor your runners.\n\n#### Telemetry Action\n\n* [workflow-telemetry Action](https://github.com/marketplace/actions/workflow-telemetry) - This action collects metrics during runtime and produces a job summary report to view.\n\n### Workflow Run History\n\nYou can view the history of workflow runs in the Actions tab of your repository.\n\nThe organization level [actions usage \u0026 performance metrics](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/monitoring-workflows/actions-usage-metrics--performance-metrics) also provides insights into workflow run history.\n\n* [Monitoring workflows](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/monitoring-workflows)\n* [Viewing workflow run history](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/monitoring-workflows/viewing-workflow-run-history)\n* [REST API endpoints for workflow runs](https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28)\n\n### Pinning and Searching Workflows\n\nYou can pin workflows in the left sidebar of the Actions tab to make them easier to find.\n\nYou can search workflow runs by actor, branch, event, status, and workflow name.\n\nWorkflows are always sorted by the most recent run.\n\n### Logging\n\nYou can view logs for each step in a workflow run.\n\nYou can also search logs for specific text in a more performant way than CTRL+F.\n\n#### Retention\n\nWorkflow run logs are retained for 90 days by default. You can [configure the retention period for workflow run logs](https://docs.github.com/en/organizations/managing-organization-settings/configuring-the-retention-period-for-github-actions-artifacts-and-logs-in-your-organization) at the organization or repository level up to 90 days for public repos or 400 days for private repos.\n\n#### Formatting\n\nThere are numerous ways to format logs such as annotations, grouping, masking, coloring, etc. You can do it manually or use the [actions/toolkit](https://github.com/actions/toolkit/tree/main/packages/core#logging) to help you format your logs.\n\n![image](https://github.com/user-attachments/assets/03231846-05c8-44b2-862a-b264f93b044f)\n\n* [Workflow run logs](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/monitoring-workflows/using-workflow-run-logs)\n* [Enable debug logging](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/troubleshooting-workflows/enabling-debug-logging)\n* [Workflow commands for GitHub Actions](https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#about-workflow-commands)\n* [Configuring the retention period for GitHub Actions artifacts and logs in your organization](https://docs.github.com/en/organizations/managing-organization-settings/configuring-the-retention-period-for-github-actions-artifacts-and-logs-in-your-organization)\n\n## How to Manage Cost and Billing\n\nGitHub Actions is a metered product so we need to be careful about how we use it to avoid unexpected costs.\n\n### Pricing\n\nGitHub Actions is free for public repositories. For private repositories, GitHub offers a range of pricing plans based on usage.\n\nSee [Cost](#cost) for more information on pricing.\n\n### Billing Page in GitHub\n\nBudgets and alerts allow you to track spending on metered products for your accounts, organizations, cost centers (enterprise only), and repositories.\n\n* [Using budgets to control spending on metered products](https://docs.github.com/en/enterprise-cloud@latest/billing/managing-your-billing/using-budgets-control-spending)\n* [Charging business units](https://docs.github.com/en/enterprise-cloud@latest/billing/managing-your-billing/charging-business-units)\n\n### CSV Usage Download and GitHub Usage Report Viewer\n\nYou can download a CSV file of all metered usage for your account, organization, or repository. This is useful for analyzing usage and costs.\n\n* [Viewing your usage of metered products](https://docs.github.com/en/billing/managing-billing-for-your-products/viewing-your-product-usage)\n* [About usage reports](https://docs.github.com/en/billing/managing-your-billing/about-usage-reports)\n\n#### [GitHub Usage Report Viewer](https://austenstone.github.io/github-actions-usage-report/)\n\n[austenstone](https://github.com/austenstone) created a usage report viewer to visualize your usage report csv.\n\n### Invoicing\n\nGitHub Actions usage is billed monthly. You can view your invoice in the billing settings of your account or organization.\n\n### Paying Through GitHub vs MSFT Azure\n\nGitHub Actions can be billed through and azure subscription. This also means discounts applied to that Azure subscription will apply to GitHub Actions usage.\n\nIf you're not using an Azure subscription, you can pay for GitHub Actions usage monthly through GitHub.\n\n## [How to Migrate](https://docs.github.com/en/actions/migrating-to-github-actions)\n\nThere are many ways to migrate to GitHub Actions. The best way to migrate depends on your current CI/CD system and how complex your workflows are.\n\n### [Importer](https://docs.github.com/en/actions/migrating-to-github-actions/using-github-actions-importer-to-automate-migrations)\n\nThe GitHub Actions Importer can be a great first step in migrating but it will not cover all use cases.\n\nThe importer includes forecasting capabilities to help you understand the cost of migrating to GitHub Actions.\n\n### Copilot\n\nYou can leverage [GitHub Copilot](https://github.com/features/copilot/plans) to help you write workflows. Copilot greatly accelerates the process of writing workflows if you can provide it context and your old workflow files.\n\n## Understanding Platform Limits\n\nThere are numerous platforms limits in place to ensure the stability and reliability of GitHub Actions.\n\nA majority of the limits can be adjusted by contacting GitHub support or your account manager.\n\n* [Limits in GitHub Actions](https://docs.github.com/en/actions/reference/actions-limits)\n* [Concurrency Limits](https://docs.github.com/en/actions/concepts/overview/usage-limits-billing-and-administration#usage-limits)\n\n\u003c!-- ### API Rate Limits\n\nThe API is a dependent service and has its own rate limits.\n\nGitHub Apps have higher rate limits than PATs. GitHub can increase rate limits for GitHub Apps on a case-by-case basis.\n\n* [Commonly hit dependent service limits](https://docs.github.com/en/actions/reference/actions-limits#commonly-hit-dependent-service-limits)\n\n### [Reusable Workflow](#reusable-workflows) Limit\n\n[Reusable workflows](#reusable-workflows) have some limitations that you should be aware of. Most notably:\n* You can only nest them up to 4 levels deep\n* You can call a maximum of 20 unique reusable workflows in a single workflow run\n* env is in a different context\n\n* [Reusable workflow limitations](https://docs.github.com/en/actions/sharing-automations/reusing-workflows#limitations)\n\nFor this reason consider using [composite actions](#composite-actions) first.\n\n### Workflow Run Time\n\nThe maximum workflow execution time is 35 days. If a workflow run reaches this limit, the workflow run is cancelled. This period includes execution duration, and time spent on waiting and approval.\n\n### Job Execution Time\n\nFor github-hosted runners each job in a workflow can run for up to 6 hours of execution time. If a job reaches this limit, the job is terminated and fails.\n\nFor self-hosted runners, there is no execution time limit.\n\n### Matrix Size\n\nA job matrix can generate a maximum of 256 jobs per workflow run. This limit applies to both GitHub-hosted and self-hosted runners.\n\nCache Size per Repo\n\nEach repository has a maximum cache size of 10 GB. If a repository exceeds this limit, the oldest cache entries will be removed to make room for new ones.\n\n### Queue Limit\n\nYou can have a maximum of 500 workflow runs queued every 10 seconds.\n\n### Artifact and Log Retention\n\nArtifacts and logs are retained for 90 days. After this period, they are automatically deleted. --\u003e\n\n### Exception Process\n\nIf you need to increase any of the limits, you can contact GitHub support or your account manager. They will review your request and may grant an exception on a case-by-case basis.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faustenstone%2Factions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faustenstone%2Factions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faustenstone%2Factions/lists"}