@@ -1,158 +1,58 @@
|
||||
---
|
||||
title: About larger runners
|
||||
shortTitle: About larger runners
|
||||
intro: '{% data variables.product.prodname_dotcom %} offers runners with advanced features to support more customized use cases.'
|
||||
shortTitle: Larger runners
|
||||
intro: 'Learn about the types and uses of {% data variables.product.prodname_dotcom %}-hosted {% data variables.actions.hosted_runners %}.'
|
||||
permissions: '{% data reusables.actions.larger-runner-permissions %}'
|
||||
versions:
|
||||
feature: actions-hosted-runners
|
||||
fpt: '*'
|
||||
ghes: '*'
|
||||
ghec: '*'
|
||||
redirect_from:
|
||||
- /actions/using-github-hosted-runners/about-larger-runners/about-larger-runners
|
||||
- /actions/using-github-hosted-runners/using-larger-runners/about-larger-runners
|
||||
---
|
||||
|
||||
## Overview of {% data variables.actions.hosted_runners %}
|
||||
{% ifversion ghes %}
|
||||
{% data reusables.actions.enterprise-github-hosted-runners %}
|
||||
|
||||
To learn about larger runners, see [the {% data variables.product.prodname_ghe_cloud %} documentation](/enterprise-cloud@latest/actions/concepts/runners/about-larger-runners).
|
||||
{% else %}
|
||||
|
||||
## About {% data variables.actions.hosted_runners %}
|
||||
|
||||
{% data reusables.actions.about-larger-runners %}
|
||||
|
||||
{% data variables.product.prodname_dotcom %} offers {% data variables.actions.hosted_runners %} with macOS, Ubuntu, or Windows operating systems, and different features and sizes are available depending on which operating system you use. For more information, see [Additional features for {% data variables.actions.hosted_runners %}](#additional-features-for-larger-runners).
|
||||
{% data variables.product.prodname_dotcom %} offers {% data variables.actions.hosted_runners %} with macOS, Ubuntu, or Windows operating systems, and different features and sizes are available depending on which operating system you use.
|
||||
|
||||
### About Ubuntu and Windows {% data variables.actions.hosted_runners %}
|
||||
## About Ubuntu and Windows {% data variables.actions.hosted_runners %}
|
||||
|
||||
{% data variables.actions.hosted_runner_caps %}s with Ubuntu or Windows operating systems are configured in your organization or enterprise. When you add a {% data variables.actions.hosted_runner %}, you are defining a type of machine from a selection of available hardware specifications and operating system images. {% data variables.product.prodname_dotcom %} will then create multiple instances of this runner that scale up and down to match the job demands of your organization, based on the autoscaling limits you define. For more information, see [AUTOTITLE](/actions/using-github-hosted-runners/managing-larger-runners).
|
||||
{% data variables.actions.hosted_runner_caps %}s with Ubuntu or Windows operating systems are configured in your organization or enterprise. When you add a {% data variables.actions.hosted_runner %}, you are defining a type of machine from a selection of available hardware specifications and operating system images.
|
||||
|
||||
Ubuntu and Windows {% data variables.actions.hosted_runners %} offer autoscaling capabilities and the ability to assign the runners static IP addresses from a specific range. They can also be managed using runner groups, which enables you to control access to the {% data variables.actions.hosted_runners %}. For more information, see [Additional features for {% data variables.actions.hosted_runners %}](#additional-features-for-larger-runners).
|
||||
With Ubuntu and Windows {% data variables.actions.hosted_runners %}, you can:
|
||||
* Assign runners static IP addresses from a specific range, allowing you to use this range to configure a firewall allowlist
|
||||
* Control access to your resources by assigning runners to runner groups
|
||||
* Use autoscaling to simplify runner management and control your costs
|
||||
* Use your runners with Azure private networking
|
||||
|
||||
### About macOS {% data variables.actions.hosted_runners %}
|
||||
## About macOS {% data variables.actions.hosted_runners %}
|
||||
|
||||
{% data variables.actions.hosted_runner_caps %}s with a macOS operating system are used by updating the YAML workflow label to the desired runner image. To run your workflows on a macOS {% data variables.actions.hosted_runner %}, update the `runs-on` key to use one of the {% data variables.product.company_short %}-defined macOS {% data variables.actions.hosted_runner %} labels. No additional configuration is required. For more information, see [AUTOTITLE](/actions/using-github-hosted-runners/running-jobs-on-larger-runners?platform=mac).
|
||||
{% data variables.actions.hosted_runner_caps %}s with a macOS operating system are not manually added to your organization or enterprise, but are instead used by updating the `runs-on` key of a workflow file to one of the {% data variables.product.company_short %}-defined macOS {% data variables.actions.hosted_runner %} labels.
|
||||
|
||||
The following machines sizes are available for macOS {% data variables.actions.hosted_runners %}.
|
||||
Since macOS {% data variables.actions.hosted_runners %} are not preconfigured, they have limitations that Ubuntu and Windows {% data variables.actions.hosted_runners %} do not. For more information, see [AUTOTITLE](/actions/reference/larger-runners-reference#limitations-for-macos-larger-runners).
|
||||
|
||||
{% data reusables.actions.larger-runners-table %}
|
||||
|
||||
>[!NOTE] The XLarge macOS runner is in public preview and subject to change.
|
||||
|
||||
#### Limitations for macOS {% data variables.actions.hosted_runners %}
|
||||
|
||||
{% data reusables.actions.macos-runner-limitations %}
|
||||
|
||||
### Additional features for {% data variables.actions.hosted_runners %}
|
||||
|
||||
Compared to standard {% data variables.product.prodname_dotcom %}-hosted runners, {% data variables.actions.hosted_runners %} have additional features, and their availability varies depending on the {% data variables.actions.hosted_runner %}'s operating system.
|
||||
|
||||
{% rowheaders %}
|
||||
|
||||
| | Ubuntu | Windows | macOS |
|
||||
| ------------------- | ------ | ------- | ----- |
|
||||
| Static IP addresses | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} | {% octicon "x" aria-label="Not supported" %} |
|
||||
| Azure private networking | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} | {% octicon "x" aria-label="Not supported" %} |
|
||||
| Autoscaling | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} | {% octicon "x" aria-label="Not supported" %} |
|
||||
| Runner groups | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} | {% octicon "x" aria-label="Not supported" %} |
|
||||
|
||||
{% endrowheaders %}
|
||||
|
||||
These features can enhance your CI/CD pipelines in the following ways.
|
||||
|
||||
* Assigning {% data variables.actions.hosted_runners %} static IP addresses from a specific range enables you to use this range to configure a firewall allowlist. For more information, see [Networking for {% data variables.actions.hosted_runners %}](#networking-for-larger-runners).
|
||||
* Autoscaling enables {% data variables.actions.hosted_runners %} to scale up to a maximum limit set by you, so your workflows can run concurrently. For more information, see [Autoscaling {% data variables.actions.hosted_runners %}](#autoscaling-larger-runners).
|
||||
* Runner groups allow you to control access to {% data variables.actions.hosted_runners %} for your organizations, repositories, and workflows. For more information, see [AUTOTITLE](/actions/using-github-hosted-runners/controlling-access-to-larger-runners).
|
||||
|
||||
### Runner images
|
||||
|
||||
{% data variables.actions.hosted_runner_caps %}s run on virtual machines (VMs), and {% data variables.product.prodname_dotcom %} installs a virtual hard disk (VHD) on this machine during the VM creation process. You can choose from different VM images to install on your runners.
|
||||
|
||||
**{% data variables.product.prodname_dotcom %}-owned images:** These images are maintained by {% data variables.product.prodname_dotcom %} and are available for Linux x64, Windows x64, and macOS (x64 and arm) runners. For more information on these images and a full list of included tools for each runner operating system, see the [{% data variables.product.prodname_actions %} Runner Images](https://github.com/actions/runner-images) repository.
|
||||
|
||||
**Partner Images:** Partner images are not managed by {% data variables.product.prodname_dotcom %} and are pulled from the Azure Marketplace. See below for resources on where to find more information and to report issues for partner images.
|
||||
* [Base Windows 11 desktop image](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/microsoftwindowsdesktop.windows-11?tab=Overview).
|
||||
* [NVIDIA GPU-Optimized VMI](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/nvidia.ngc_azure_17_11)
|
||||
* [Data Science Virtual Machine - Windows 2019](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/microsoft-dsvm.dsvm-win-2019?tab=overview).
|
||||
* arm64 images: [`actions/partner-runner-images` repository](https://github.com/actions/partner-runner-images).
|
||||
|
||||
### Understanding billing
|
||||
## Billing
|
||||
|
||||
> [!NOTE]
|
||||
> {% data variables.actions.hosted_runner_caps %}s are not eligible for the use of included minutes on private repositories. For both private and public repositories, when {% data variables.actions.hosted_runners %} are in use, they will always be billed at the per-minute rate.
|
||||
|
||||
Compared to standard {% data variables.product.prodname_dotcom %}-hosted runners, {% data variables.actions.hosted_runners %} are billed differently. {% data reusables.actions.about-larger-runners-billing %} For more information, see [AUTOTITLE](/billing/managing-billing-for-github-actions/about-billing-for-github-actions#per-minute-rates).
|
||||
|
||||
## Machine sizes for {% data variables.actions.hosted_runners %}
|
||||
## Next steps
|
||||
|
||||
You can choose from several specifications for {% data variables.actions.hosted_runners %}.
|
||||
To start using Windows or Ubuntu {% data variables.actions.hosted_runners %}, see [AUTOTITLE](/actions/how-tos/using-github-hosted-runners/using-larger-runners/managing-larger-runners).
|
||||
|
||||
### Specifications for general {% data variables.actions.hosted_runners %}
|
||||
To start using macOS {% data variables.actions.hosted_runners %}, see [AUTOTITLE](/actions/how-tos/using-github-hosted-runners/using-larger-runners/running-jobs-on-larger-runners?platform=mac).
|
||||
|
||||
| CPU | Memory (RAM) | Storage (SSD) | Architecture | Operating system (OS) |
|
||||
| --- | ------------- | ------------- | ------------ | --------------------- |
|
||||
| 5 | 14 GB | 14 GB | arm64 | macOS |
|
||||
| 12 | 30 GB | 14 GB | x64 | macOS |
|
||||
| 2 | 8 GB | 75 GB | x64, arm64 | Ubuntu |
|
||||
| 4 | 16 GB | 150 GB | x64, arm64 | Ubuntu, Windows |
|
||||
| 8 | 32 GB | 300 GB | x64, arm64 | Ubuntu, Windows |
|
||||
| 16 | 64 GB | 600 GB | x64, arm64 | Ubuntu, Windows |
|
||||
| 32 | 128 GB | 1200 GB | x64, arm64 | Ubuntu, Windows |
|
||||
| 64 | 208 GB | 2040 GB | arm64 | Ubuntu, Windows |
|
||||
| 64 | 256 GB | 2040 GB | x64 | Ubuntu, Windows |
|
||||
| 96 | 384 GB | 2040 GB | x64 | Ubuntu, Windows |
|
||||
To find reference information about using {% data variables.actions.hosted_runners %}, see [AUTOTITLE](/actions/reference/larger-runners-reference).
|
||||
|
||||
>[!NOTE] The 4-vCPU Windows runner only works with the Windows Server 2025 or the Base Windows 11 Desktop image.
|
||||
|
||||
>[!NOTE] The 5-vCPU macOS runner is in public preview and subject to change.
|
||||
|
||||
### Specifications for GPU {% data variables.actions.hosted_runners %}
|
||||
|
||||
| CPU | GPU | GPU card | Memory (RAM) | GPU memory (VRAM) | Storage (SSD) | Operating system (OS) |
|
||||
| --- | --- | -------- | ------------ | ----------------- | ------------- | --------------------- |
|
||||
| 4 | 1 | Tesla T4 | 28 GB | 16 GB | 176 GB | Ubuntu, Windows |
|
||||
|
||||
## About runner groups
|
||||
|
||||
> [!NOTE]
|
||||
> Only {% data variables.actions.hosted_runners %} with Linux or Windows operating systems can be assigned to runner groups.
|
||||
|
||||
Runner groups enable administrators to control access to runners at the organization and enterprise levels. With runner groups, you can collect sets of runners and create a security boundary around them. You can then decide which organizations or repositories are permitted to run jobs on those sets of machines. During the {% data variables.actions.hosted_runner %} deployment process, the runner can be added to an existing group, otherwise it will join a default group. You can create a group by following the steps in [AUTOTITLE](/actions/using-github-hosted-runners/controlling-access-to-larger-runners).
|
||||
|
||||
## Architectural overview of {% data variables.actions.hosted_runners %}
|
||||
|
||||
> [!NOTE]
|
||||
> This architecture diagram only applies to {% data variables.actions.hosted_runners %} with Linux or Windows operating systems.
|
||||
|
||||
{% data variables.actions.hosted_runner_caps %}s are managed at the organization level, where they are arranged into groups that can contain multiple instances of the runner. They can also be created at the enterprise level and shared with organizations in the hierarchy. Once you've created a group, you can then add a runner to the group and update your workflows to target either the group name or the label assigned to the {% data variables.actions.hosted_runner %}. You can also control which repositories are permitted to send jobs to the group for processing. For more information about groups, see [AUTOTITLE](/actions/using-github-hosted-runners/controlling-access-to-larger-runners).
|
||||
|
||||
In the following diagram, a class of hosted runner named `ubuntu-20.04-16core` has been defined with customized hardware and operating system configuration.
|
||||
|
||||

|
||||
|
||||
1. Instances of this runner are automatically created and added to a group called `grp-ubuntu-20.04-16core`.
|
||||
1. The runners have been assigned the label `ubuntu-20.04-16core`.
|
||||
1. Workflow jobs use the `ubuntu-20.04-16core` label in their `runs-on` key to indicate the type of runner they need to execute the job.
|
||||
1. {% data variables.product.prodname_actions %} checks the runner group to see if your repository is authorized to send jobs to the runner.
|
||||
1. The job runs on the next available instance of the `ubuntu-20.04-16core` runner.
|
||||
|
||||
## Autoscaling {% data variables.actions.hosted_runners %}
|
||||
|
||||
> [!NOTE]
|
||||
> Autoscaling is only available for {% data variables.actions.hosted_runners %} with Linux or Windows operating systems.
|
||||
|
||||
{% data variables.actions.hosted_runner_caps %}s can automatically scale to suit your needs. You can provision machines to run a specified maximum number of jobs when jobs are submitted for processing. Each machine only handles one job at a time, so these settings effectively determine the number of jobs that can be run concurrently.
|
||||
|
||||
You can configure the maximum job concurrency, which allows you to control your costs by setting the maximum parallel number of jobs that can be run using this set. A higher value here can help avoid workflows being blocked due to parallelism. For more information on how to set limits, see [AUTOTITLE](/actions/using-github-hosted-runners/managing-larger-runners#configuring-autoscaling-for-larger-runners). For more information on the maximum auto-scaling limits for {% data variables.product.company_short %}-hosted runners, see [AUTOTITLE](/actions/learn-github-actions/usage-limits-billing-and-administration#usage-limits).
|
||||
|
||||
## Assigning static IP addresses to {% data variables.actions.hosted_runners %}
|
||||
|
||||
You can assign static IP addresses only to {% data variables.actions.hosted_runners %} that use Linux or Windows operating systems.
|
||||
|
||||
Static IP addresses assigned are all usable and are not in CIDR notation.
|
||||
|
||||
{% data reusables.actions.static-ip-limitation-vnet %} For more information about private networking for {% data variables.product.company_short %}-hosted runners, see [AUTOTITLE](/admin/configuration/configuring-private-networking-for-hosted-compute-products/about-azure-private-networking-for-github-hosted-runners-in-your-enterprise).
|
||||
|
||||
## Networking for {% data variables.actions.hosted_runners %}
|
||||
|
||||
By default, {% data variables.actions.hosted_runners %} receive a dynamic IP address that changes for each job run. Optionally, {% data variables.product.prodname_ghe_cloud %} customers can configure their {% data variables.actions.hosted_runners %} to receive static IP addresses from {% data variables.product.prodname_dotcom %}'s IP address pool. For more information, see [AUTOTITLE](/authentication/keeping-your-account-and-data-secure/about-githubs-ip-addresses).
|
||||
|
||||
When enabled, instances of the {% data variables.actions.hosted_runner %} will receive IP addresses from specific ranges that are unique to the runner, allowing you to use the ranges to configure a firewall allowlist. {% ifversion fpt %}You can use up to 10 {% data variables.actions.hosted_runners %} with static IP address ranges in total across all your {% data variables.actions.hosted_runners %}{% endif %}{% ifversion ghec %}You can use up to 10 {% data variables.actions.hosted_runners %} with static IP address ranges for the {% data variables.actions.hosted_runners %} created at the enterprise level. In addition, you can use up to 10 {% data variables.actions.hosted_runners %} with static IP address ranges for the {% data variables.actions.hosted_runners %} created at the organization level, for each organization in your enterprise{% endif %}. For more information, see [AUTOTITLE](/actions/using-github-hosted-runners/managing-larger-runners#networking-for-larger-runners).
|
||||
|
||||
{% data reusables.actions.larger-runner-static-ip-contact-support %}
|
||||
|
||||
> [!NOTE]
|
||||
> If runners are unused for more than 30 days, their IP address ranges are automatically removed and cannot be recovered.
|
||||
{% endif %}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
---
|
||||
title: About custom actions
|
||||
shortTitle: Custom actions
|
||||
intro: 'Actions are individual tasks that you can combine to create jobs and customize your workflow. You can create your own actions, or use and customize actions shared by the {% data variables.product.prodname_dotcom %} community.'
|
||||
redirect_from:
|
||||
- /articles/about-actions
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
title: About monitoring workflows
|
||||
intro: 'You can use the tools in {% data variables.product.prodname_actions %} to monitor your workflows, metrics, and self-hosted runners.'
|
||||
versions:
|
||||
fpt: '*'
|
||||
ghes: '*'
|
||||
ghec: '*'
|
||||
shortTitle: About monitoring
|
||||
redirect_from:
|
||||
- /actions/monitoring-and-troubleshooting-workflows/monitoring-workflows/about-monitoring-workflows
|
||||
---
|
||||
|
||||
{% data reusables.actions.enterprise-github-hosted-runners %}
|
||||
|
||||
## Monitoring your workflows
|
||||
|
||||
{% ifversion github-runner-dashboard %}
|
||||
|
||||
### Monitoring your current jobs in your organization or enterprise
|
||||
|
||||
{% data reusables.actions.github-hosted-runners-check-concurrency %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
### Using the visualization graph
|
||||
|
||||
Every workflow run generates a real-time graph that illustrates the run progress. You can use this graph to monitor and debug workflows. For example:
|
||||
|
||||

|
||||
|
||||
For more information, see [AUTOTITLE](/actions/monitoring-and-troubleshooting-workflows/using-the-visualization-graph).
|
||||
|
||||
### Adding a workflow status badge
|
||||
|
||||
{% data reusables.repositories.actions-workflow-status-badge-intro %}
|
||||
|
||||
For more information, see [AUTOTITLE](/actions/monitoring-and-troubleshooting-workflows/adding-a-workflow-status-badge).
|
||||
|
||||
{% ifversion fpt or ghec %}
|
||||
|
||||
### Viewing job execution time
|
||||
|
||||
To identify how long a job took to run, you can view its execution time. For more information, see [AUTOTITLE](/actions/monitoring-and-troubleshooting-workflows/viewing-job-execution-time).
|
||||
{% endif %}
|
||||
|
||||
### Viewing workflow run history
|
||||
|
||||
You can view the status of each job and step in a workflow. For more information, see [AUTOTITLE](/actions/monitoring-and-troubleshooting-workflows/viewing-workflow-run-history).
|
||||
|
||||
{% ifversion actions-metrics %}
|
||||
|
||||
## Monitoring {% data variables.product.prodname_actions %} metrics
|
||||
|
||||
To analyze the efficiency and reliability of your workflows using metrics, see [AUTOTITLE](/actions/administering-github-actions/viewing-github-actions-metrics).
|
||||
{% endif %}
|
||||
|
||||
## Monitoring self-hosted runners
|
||||
|
||||
If you use self-hosted runners, you can view their activity and diagnose common issues.
|
||||
|
||||
For more information, see [AUTOTITLE](/actions/hosting-your-own-runners/managing-self-hosted-runners/monitoring-and-troubleshooting-self-hosted-runners).
|
||||
@@ -17,7 +17,5 @@ children:
|
||||
- /concurrency
|
||||
- /workflow-artifacts
|
||||
- /dependency-caching
|
||||
- /about-monitoring-workflows
|
||||
- /notifications-for-workflow-runs
|
||||
- /about-troubleshooting-workflows
|
||||
---
|
||||
|
||||
@@ -36,7 +36,15 @@ Reusable workflows and composite actions both help you to avoid duplication. Whe
|
||||
|
||||
## Reusable workflows and workflow templates
|
||||
|
||||
Workflow templates allow everyone in your organization who has permission to create workflows to do so more quickly and easily. When people create a new workflow, they can choose a workflow template and some or all of the work of writing the workflow will be done for them. Within a workflow template, you can also reference reusable workflows to make it easy for people to benefit from reusing centrally managed workflow code. If you use a commit SHA when referencing the reusable workflow, you can ensure that everyone who reuses that workflow will always be using the same YAML code. However, if you reference a reusable workflow by a tag or branch, be sure that you can trust that version of the workflow. For more information, see [AUTOTITLE](/actions/security-guides/security-hardening-for-github-actions#reusing-third-party-workflows).
|
||||
Workflow templates allow everyone in your organization who has permission to create workflows to do so more quickly and easily. When people create a new workflow, they can choose a workflow template and some or all of the work of writing the workflow will be done for them. Within a workflow template, you can also reference reusable workflows to make it easy for people to benefit from reusing centrally managed workflow code.
|
||||
|
||||
If you use a commit SHA when referencing the reusable workflow, you can ensure that everyone who reuses that workflow will always be using the same YAML code. However, if you reference a reusable workflow by a tag or branch, be sure that you can trust that version of the workflow. For more information, see [AUTOTITLE](/actions/security-guides/security-hardening-for-github-actions#reusing-third-party-workflows).
|
||||
|
||||
{% data variables.product.github %} offers workflow templates for a variety of languages and tooling. When you set up workflows in your repository, {% data variables.product.github %} analyzes the code in your repository and recommends workflows based on the language and framework in your repository. For example, if you use Node.js, {% data variables.product.github %} will suggest a workflow template file that installs your Node.js packages and runs your tests. You can search and filter to find relevant workflow templates.
|
||||
|
||||
{% data reusables.actions.workflow-templates-categories %}
|
||||
|
||||
{% data reusables.actions.workflow-templates-repo-link %}
|
||||
|
||||
For more information, see [AUTOTITLE](/actions/using-workflows/creating-starter-workflows-for-your-organization).
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
---
|
||||
title: Working with Support for GitHub Actions
|
||||
title: Getting help from GitHub Support about GitHub Actions
|
||||
shortTitle: Get support
|
||||
intro: 'Learn how {% data variables.contact.github_support %} can assist with {% data variables.product.prodname_actions %}'
|
||||
versions:
|
||||
fpt: '*'
|
||||
@@ -9,10 +10,10 @@ type: reference
|
||||
topics:
|
||||
- Actions
|
||||
- Support
|
||||
shortTitle: 'Working with {% data variables.contact.github_support %}'
|
||||
redirect_from:
|
||||
- /actions/monitoring-and-troubleshooting-workflows/working-with-support-for-github-actions
|
||||
- /actions/monitoring-and-troubleshooting-workflows/troubleshooting-workflows/working-with-support-for-github-actions
|
||||
- /actions/how-tos/monitoring-and-troubleshooting-workflows/troubleshooting-workflows/working-with-support-for-github-actions
|
||||
---
|
||||
|
||||
You can [contact {% data variables.contact.github_support %}](/support/contacting-github-support) for assistance with {% data variables.product.prodname_actions %}.
|
||||
@@ -10,11 +10,17 @@ children:
|
||||
- /writing-workflows
|
||||
- /managing-workflow-runs-and-deployments
|
||||
- /sharing-automations
|
||||
- /monitoring-and-troubleshooting-workflows
|
||||
- /using-github-hosted-runners
|
||||
- /using-larger-runners
|
||||
- /hosting-your-own-runners
|
||||
- /security-for-github-actions
|
||||
- /use-cases-and-examples
|
||||
- /administering-github-actions
|
||||
- /monitor-workflows
|
||||
- /troubleshooting-workflows
|
||||
- /getting-help-from-github-support-about-github-actions
|
||||
redirect_from:
|
||||
- /actions/how-tos/monitoring-and-troubleshooting-workflows
|
||||
- /actions/monitoring-and-troubleshooting-workflows/about-monitoring-and-troubleshooting
|
||||
---
|
||||
|
||||
|
||||
@@ -13,11 +13,8 @@ versions:
|
||||
ghec: '*'
|
||||
---
|
||||
|
||||
{% data reusables.actions.enterprise-github-hosted-runners %}
|
||||
|
||||
## About re-running workflows and jobs
|
||||
|
||||
Re-running a workflow or jobs in a workflow uses the same `GITHUB_SHA` (commit SHA) and `GITHUB_REF` (Git ref) of the original event that triggered the workflow run. The workflow will use the privileges of the actor who initially triggered the workflow, not the privileges of the actor who initiated the re-run. You can re-run a workflow or jobs in a workflow for up to 30 days after the initial run. You cannot re-run jobs in a workflow once its logs have passed their retention limits. For more information, see [AUTOTITLE](/actions/learn-github-actions/usage-limits-billing-and-administration#artifact-and-log-retention-policy). When you re-run a workflow or jobs in a workflow, you can enable debug logging for the re-run. This will enable runner diagnostic logging and step debug logging for the re-run. For more information about debug logging, see [AUTOTITLE](/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging)
|
||||
> [!NOTE]
|
||||
> Re-run workflows use the privileges of the actor who initially triggered the workflow, not the privileges of the actor who initiated the re-run. The workflow will also use the same `GITHUB_SHA` (commit SHA) and `GITHUB_REF` (git ref) of the original event that triggered the workflow run.
|
||||
|
||||
## Re-running all the jobs in a workflow
|
||||
|
||||
@@ -30,7 +27,6 @@ Re-running a workflow or jobs in a workflow uses the same `GITHUB_SHA` (commit S
|
||||
1. In the upper-right corner of the workflow, re-run jobs.
|
||||
|
||||
* If any jobs failed, select the **{% octicon "sync" aria-hidden="true" aria-label="sync" %} Re-run jobs** dropdown menu and click **Re-run all jobs**.
|
||||
|
||||
* If no jobs failed, click **Re-run all jobs**.
|
||||
|
||||
{% data reusables.actions.enable-debug-logging %}
|
||||
@@ -39,23 +35,21 @@ Re-running a workflow or jobs in a workflow uses the same `GITHUB_SHA` (commit S
|
||||
|
||||
{% cli %}
|
||||
|
||||
{% data reusables.cli.cli-learn-more %}
|
||||
1. To re-run a failed workflow run, use the `run rerun` subcommand, replacing `RUN_ID` with the ID of the failed run that you want to re-run. If you don't specify a `run-id`, {% data variables.product.prodname_cli %} returns an interactive menu for you to choose a recent failed run.
|
||||
|
||||
To re-run a failed workflow run, use the `run rerun` subcommand. Replace `run-id` with the ID of the failed run that you want to re-run. If you don't specify a `run-id`, {% data variables.product.prodname_cli %} returns an interactive menu for you to choose a recent failed run.
|
||||
|
||||
```shell
|
||||
```shell copy
|
||||
gh run rerun RUN_ID
|
||||
```
|
||||
|
||||
{% data reusables.actions.enable-debug-logging-cli %}
|
||||
|
||||
```shell
|
||||
```shell copy
|
||||
gh run rerun RUN_ID --debug
|
||||
```
|
||||
|
||||
To view the progress of the workflow run, use the `run watch` subcommand and select the run from the interactive list.
|
||||
1. To view the progress of the workflow run, use the `run watch` subcommand and select the run from the interactive list.
|
||||
|
||||
```shell
|
||||
```shell copy
|
||||
gh run watch
|
||||
```
|
||||
|
||||
@@ -63,8 +57,6 @@ gh run watch
|
||||
|
||||
## Re-running failed jobs in a workflow
|
||||
|
||||
If any jobs in a workflow run failed, you can re-run just the jobs that failed. When you re-run failed jobs in a workflow, a new workflow run will start for all failed jobs and their dependents. Any outputs for any successful jobs in the previous workflow run will be used for the re-run. Any artifacts that were created in the initial run will be available in the re-run. Any deployment protection rules that passed in the previous run will automatically pass in the re-run.
|
||||
|
||||
{% webui %}
|
||||
|
||||
{% data reusables.repositories.navigate-to-repo %}
|
||||
@@ -78,7 +70,7 @@ If any jobs in a workflow run failed, you can re-run just the jobs that failed.
|
||||
|
||||
{% cli %}
|
||||
|
||||
To re-run failed jobs in a workflow run, use the `run rerun` subcommand with the `--failed` flag. Replace `run-id` with the ID of the run for which you want to re-run failed jobs. If you don't specify a `run-id`, {% data variables.product.prodname_cli %} returns an interactive menu for you to choose a recent failed run.
|
||||
To re-run failed jobs in a workflow run, use the `run rerun` subcommand with the `--failed` flag. Replace `RUN_ID` with the ID of the run for which you want to re-run failed jobs. If you don't specify a `run-id`, {% data variables.product.prodname_cli %} returns an interactive menu for you to choose a recent failed run.
|
||||
|
||||
```shell
|
||||
gh run rerun RUN_ID --failed
|
||||
@@ -94,8 +86,6 @@ gh run rerun RUN_ID --failed --debug
|
||||
|
||||
## Re-running a specific job in a workflow
|
||||
|
||||
When you re-run a specific job in a workflow, a new workflow run will start for the job and any dependents. Any outputs for any other jobs in the previous workflow run will be used for the re-run. Any artifacts that were created in the initial run will be available in the re-run. Any deployment protection rules that passed in the previous run will automatically pass in the re-run.
|
||||
|
||||
{% webui %}
|
||||
|
||||
{% data reusables.repositories.navigate-to-repo %}
|
||||
@@ -110,7 +100,7 @@ When you re-run a specific job in a workflow, a new workflow run will start for
|
||||
|
||||
{% cli %}
|
||||
|
||||
To re-run a specific job in a workflow run, use the `run rerun` subcommand with the `--job` flag. Replace `job-id` with the ID of the job that you want to re-run.
|
||||
To re-run a specific job in a workflow run, use the `run rerun` subcommand with the `--job` flag. Replace `JOB_ID` with the ID of the job that you want to re-run.
|
||||
|
||||
```shell
|
||||
gh run rerun --job JOB_ID
|
||||
@@ -124,14 +114,8 @@ gh run rerun --job JOB_ID --debug
|
||||
|
||||
{% endcli %}
|
||||
|
||||
## Re-running workflows and jobs with reusable workflows
|
||||
|
||||
{% data reusables.actions.partial-reruns-with-reusable %}
|
||||
|
||||
## Reviewing previous workflow runs
|
||||
|
||||
You can view the results from your previous attempts at running a workflow. You can also view previous workflow runs using the API. For more information, see [AUTOTITLE](/rest/actions/workflow-runs#get-a-workflow-run).
|
||||
|
||||
{% data reusables.repositories.navigate-to-repo %}
|
||||
{% data reusables.repositories.actions-tab %}
|
||||
{% data reusables.repositories.navigate-to-workflow %}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: Monitoring workflows
|
||||
shortTitle: Monitor
|
||||
title: Monitor workflows
|
||||
intro: 'You can monitor {% data variables.product.prodname_actions %} workflows by using tools like the visualization graph and run logs.'
|
||||
versions:
|
||||
fpt: '*'
|
||||
@@ -12,6 +11,8 @@ children:
|
||||
- /viewing-job-execution-time
|
||||
- /adding-a-workflow-status-badge
|
||||
- /using-workflow-run-logs
|
||||
- /enabling-debug-logging
|
||||
redirect_from:
|
||||
- /actions/monitoring-and-troubleshooting-workflows/monitoring-workflows
|
||||
- /actions/concepts/workflows-and-actions/about-monitoring-workflows
|
||||
---
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Using the visualization graph
|
||||
shortTitle: Visualization graph
|
||||
shortTitle: Use the visualization graph
|
||||
intro: Every workflow run generates a real-time graph that illustrates the run progress. You can use this graph to monitor and debug workflows.
|
||||
redirect_from:
|
||||
- /actions/managing-workflow-runs/using-the-visualization-graph
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Using workflow run logs
|
||||
shortTitle: Workflow run logs
|
||||
shortTitle: Use workflow run logs
|
||||
intro: 'You can view, search, and download the logs for each job in a workflow run.'
|
||||
redirect_from:
|
||||
- /actions/managing-workflow-runs/using-workflow-run-logs
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Viewing workflow run history
|
||||
shortTitle: Workflow run history
|
||||
shortTitle: View workflow run history
|
||||
intro: You can view logs for each run of a workflow. Logs include the status for each job and step in a workflow.
|
||||
redirect_from:
|
||||
- /actions/managing-workflow-runs/viewing-workflow-run-history
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
title: Monitoring and troubleshooting workflows
|
||||
shortTitle: Monitor & troubleshoot
|
||||
intro: 'You can view the status and results of each step in your workflow, debug a failed workflow, and search and download logs.'
|
||||
redirect_from:
|
||||
- /articles/viewing-your-repository-s-workflows
|
||||
- /articles/viewing-your-repositorys-workflows
|
||||
- /actions/monitoring-and-troubleshooting-workflows/about-monitoring-and-troubleshooting
|
||||
- /actions/monitoring-and-troubleshooting-workflows
|
||||
versions:
|
||||
fpt: '*'
|
||||
ghes: '*'
|
||||
ghec: '*'
|
||||
children:
|
||||
- /monitoring-workflows
|
||||
- /troubleshooting-workflows
|
||||
---
|
||||
|
||||
{% data reusables.actions.enterprise-github-hosted-runners %}
|
||||
@@ -1,15 +0,0 @@
|
||||
---
|
||||
title: Troubleshooting workflows
|
||||
shortTitle: Troubleshoot
|
||||
intro: 'You can troubleshoot {% data variables.product.prodname_actions %} workflows by using tools like debug logging.'
|
||||
versions:
|
||||
fpt: '*'
|
||||
ghes: '*'
|
||||
ghec: '*'
|
||||
children:
|
||||
- /using-copilot-to-troubleshoot-workflows
|
||||
- /enabling-debug-logging
|
||||
- /working-with-support-for-github-actions
|
||||
redirect_from:
|
||||
- /actions/monitoring-and-troubleshooting-workflows/troubleshooting-workflows
|
||||
---
|
||||
@@ -1,21 +0,0 @@
|
||||
---
|
||||
title: Using Copilot to troubleshoot workflows
|
||||
intro: 'You can use {% data variables.product.prodname_copilot %} to help resolve failed workflow runs.'
|
||||
versions:
|
||||
feature: copilot
|
||||
shortTitle: Use Copilot
|
||||
permissions: This feature is available for users on all {% data variables.product.prodname_copilot %} subscription tiers.
|
||||
redirect_from:
|
||||
- /actions/monitoring-and-troubleshooting-workflows/troubleshooting-workflows/using-copilot-to-troubleshoot-workflows
|
||||
---
|
||||
|
||||
If a workflow run fails, you can open a chat with {% data variables.product.prodname_copilot %} for assistance resolving the error.
|
||||
|
||||
To open a chat about a failed workflow run, you can either:
|
||||
|
||||
* Next to the failed check in the merge box, click **{% octicon "kebab-horizontal" aria-hidden="true" aria-label="kebab-horizontal" %}**, then click **{% octicon "copilot" aria-hidden="true" aria-label="copilot" %} Explain error**.
|
||||
* In the merge box, click on the failed check. At the top of the workflow run summary page, click **{% octicon "copilot" aria-hidden="true" aria-label="copilot" %} Explain error**.
|
||||
|
||||
This opens a chat window with {% data variables.product.prodname_copilot %}, where it will provide instructions to resolve the issue.
|
||||
|
||||
>[!NOTE] If you are on a {% data variables.copilot.copilot_free %} subscription, this will count towards your monthly chat message limit.
|
||||
@@ -1,13 +1,15 @@
|
||||
---
|
||||
title: About troubleshooting workflows
|
||||
title: Troubleshooting workflows
|
||||
shortTitle: Troubleshoot workflows
|
||||
intro: 'You can use the tools in {% data variables.product.prodname_actions %} to debug your workflows.'
|
||||
versions:
|
||||
fpt: '*'
|
||||
ghes: '*'
|
||||
ghec: '*'
|
||||
shortTitle: About troubleshooting
|
||||
redirect_from:
|
||||
- /actions/monitoring-and-troubleshooting-workflows/troubleshooting-workflows/about-troubleshooting-workflows
|
||||
- /actions/how-tos/monitoring-and-troubleshooting-workflows/troubleshooting-workflows/using-copilot-to-troubleshoot-workflows
|
||||
- /actions/how-tos/monitoring-and-troubleshooting-workflows/troubleshooting-workflows
|
||||
---
|
||||
|
||||
{% data reusables.actions.enterprise-github-hosted-runners %}
|
||||
@@ -18,9 +20,16 @@ There are several ways you can troubleshoot failed workflow runs.
|
||||
|
||||
{% ifversion copilot %}
|
||||
|
||||
>[!NOTE] If you are on a {% data variables.copilot.copilot_free %} subscription, this will count towards your monthly chat message limit.
|
||||
|
||||
### Using {% data variables.product.prodname_copilot %}
|
||||
|
||||
If a workflow run fails, you can open a chat with {% data variables.product.prodname_copilot %} for assistance resolving the error. See [AUTOTITLE](/actions/monitoring-and-troubleshooting-workflows/troubleshooting-workflows/using-copilot-to-troubleshoot-workflows).
|
||||
To open a chat with {% data variables.product.prodname_copilot %} about a failed workflow run, you can either:
|
||||
|
||||
* Next to the failed check in the merge box, click **{% octicon "kebab-horizontal" aria-hidden="true" aria-label="kebab-horizontal" %}**, then click **{% octicon "copilot" aria-hidden="true" aria-label="copilot" %} Explain error**.
|
||||
* In the merge box, click on the failed check. At the top of the workflow run summary page, click **{% octicon "copilot" aria-hidden="true" aria-label="copilot" %} Explain error**.
|
||||
|
||||
This opens a chat window with {% data variables.product.prodname_copilot %}, where it will provide instructions to resolve the issue.
|
||||
|
||||
{% endif %}
|
||||
|
||||
@@ -9,8 +9,7 @@ versions:
|
||||
children:
|
||||
- /using-github-hosted-runners
|
||||
- /customizing-github-hosted-runners
|
||||
- /monitoring-your-current-jobs
|
||||
- /using-larger-runners
|
||||
- /viewing-your-current-jobs
|
||||
- /connecting-to-a-private-network
|
||||
redirect_from:
|
||||
- /actions/using-github-hosted-runners
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Monitoring your current jobs
|
||||
shortTitle: Monitor current jobs
|
||||
title: Viewing your current jobs
|
||||
shortTitle: View current jobs
|
||||
intro: 'Monitor how {% data variables.product.prodname_dotcom %}-hosted runners are processing jobs in your organization or enterprise, and identify any related constraints.'
|
||||
versions:
|
||||
feature: github-runner-dashboard
|
||||
@@ -9,6 +9,8 @@ redirect_from:
|
||||
- /actions/using-github-hosted-runners/about-github-hosted-runners/monitoring-your-current-jobs
|
||||
- /actions/using-github-hosted-runners/using-github-hosted-runners/monitoring-your-current-jobs
|
||||
- /actions/how-tos/using-github-hosted-runners/using-github-hosted-runners/monitoring-your-current-jobs
|
||||
- /actions/how-tos/using-github-hosted-runners/monitoring-your-current-jobs#viewing-active-jobs-in-your-organization-or-enterprise
|
||||
- /actions/how-tos/using-github-hosted-runners/monitoring-your-current-jobs
|
||||
---
|
||||
|
||||
{% data reusables.actions.enterprise-github-hosted-runners %}
|
||||
@@ -10,6 +10,7 @@ redirect_from:
|
||||
- /actions/using-github-hosted-runners/controlling-access-to-larger-runners
|
||||
- /actions/using-github-hosted-runners/about-larger-runners/controlling-access-to-larger-runners
|
||||
- /actions/using-github-hosted-runners/using-larger-runners/controlling-access-to-larger-runners
|
||||
- /actions/how-tos/using-github-hosted-runners/using-larger-runners/controlling-access-to-larger-runners
|
||||
---
|
||||
|
||||
> [!NOTE]
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: Using larger runners
|
||||
shortTitle: Using larger runners
|
||||
intro: '{% data variables.product.prodname_dotcom %} offers runners with more RAM, CPU, and disk space.'
|
||||
versions:
|
||||
feature: actions-hosted-runners
|
||||
@@ -11,6 +10,7 @@ children:
|
||||
redirect_from:
|
||||
- /actions/using-github-hosted-runners/about-larger-runners
|
||||
- /actions/using-github-hosted-runners/using-larger-runners
|
||||
- /actions/how-tos/using-github-hosted-runners/using-larger-runners
|
||||
---
|
||||
|
||||
{% data reusables.actions.enterprise-github-hosted-runners %}
|
||||
@@ -9,6 +9,7 @@ redirect_from:
|
||||
- /actions/using-github-hosted-runners/managing-larger-runners
|
||||
- /actions/using-github-hosted-runners/about-larger-runners/managing-larger-runners
|
||||
- /actions/using-github-hosted-runners/using-larger-runners/managing-larger-runners
|
||||
- /actions/how-tos/using-github-hosted-runners/using-larger-runners/managing-larger-runners
|
||||
---
|
||||
|
||||
> [!NOTE]
|
||||
@@ -10,6 +10,7 @@ redirect_from:
|
||||
- /actions/using-github-hosted-runners/running-jobs-on-larger-runners
|
||||
- /actions/using-github-hosted-runners/about-larger-runners/running-jobs-on-larger-runners
|
||||
- /actions/using-github-hosted-runners/using-larger-runners/running-jobs-on-larger-runners
|
||||
- /actions/how-tos/using-github-hosted-runners/using-larger-runners/running-jobs-on-larger-runners
|
||||
---
|
||||
|
||||
## Running jobs on your runner
|
||||
@@ -26,18 +26,6 @@ topics:
|
||||
|
||||
{% data reusables.actions.enterprise-github-hosted-runners %}
|
||||
|
||||
## About workflow templates
|
||||
|
||||
Workflow templates are templates that help you to create your own {% data variables.product.prodname_actions %} workflows for a repository. They offer an alternative to starting from a blank workflow file and are useful because some of the work will already have been done for you.
|
||||
|
||||
{% data variables.product.github %} offers workflow templates for a variety of languages and tooling. When you set up workflows in your repository, {% data variables.product.github %} analyzes the code in your repository and recommends workflows based on the language and framework in your repository. For example, if you use Node.js, {% data variables.product.github %} will suggest a workflow template file that installs your Node.js packages and runs your tests. You can search and filter to find relevant workflow templates.
|
||||
|
||||
{% data reusables.actions.workflow-templates-categories %}
|
||||
|
||||
{% data reusables.actions.workflow-templates-repo-link %}
|
||||
|
||||
You can also create your own workflow template to share with your organization. These workflow templates will appear alongside the {% data variables.product.github %}-provided workflow templates. Anyone with write access to the organization's `.github` repository can set up a workflow template. For more information, see [AUTOTITLE](/actions/using-workflows/creating-starter-workflows-for-your-organization).
|
||||
|
||||
## Choosing and using a workflow template
|
||||
|
||||
{% data reusables.repositories.navigate-to-repo %}
|
||||
|
||||
@@ -12,7 +12,6 @@ featuredLinks:
|
||||
- /actions/concepts/overview/continuous-integration
|
||||
- /actions/tutorials/deploying-with-github-actions
|
||||
- /packages/managing-github-packages-using-github-actions-workflows/publishing-and-installing-a-package-with-github-actions
|
||||
- /actions/how-tos/monitoring-and-troubleshooting-workflows
|
||||
guideCards:
|
||||
- /actions/how-tos/writing-workflows/using-workflow-templates
|
||||
- /actions/tutorials/publishing-packages/publishing-nodejs-packages
|
||||
|
||||
@@ -23,6 +23,7 @@ children:
|
||||
- /openid-connect-reference
|
||||
- /dockerfile-support-for-github-actions
|
||||
- /github-hosted-runners-reference
|
||||
- /larger-runners-reference
|
||||
- /self-hosted-runners-reference
|
||||
- /supplemental-arguments-and-settings
|
||||
- /extending-github-actions-importer-with-custom-transformers
|
||||
|
||||
83
content/actions/reference/larger-runners-reference.md
Normal file
83
content/actions/reference/larger-runners-reference.md
Normal file
@@ -0,0 +1,83 @@
|
||||
---
|
||||
title: Larger runners reference
|
||||
shortTitle: Larger runners reference
|
||||
intro: 'Find information about larger runners, including their specifications and customization options.'
|
||||
versions:
|
||||
fpt: '*'
|
||||
ghes: '*'
|
||||
ghec: '*'
|
||||
---
|
||||
|
||||
{% ifversion ghes %}
|
||||
|
||||
{% data reusables.actions.enterprise-github-hosted-runners %}
|
||||
|
||||
For reference information about larger runners, see [the {% data variables.product.prodname_ghe_cloud %} documentation](/enterprise-cloud@latest/actions/reference/larger-runners-reference).
|
||||
|
||||
{% else %}
|
||||
|
||||
## Machine sizes for {% data variables.actions.hosted_runners %}
|
||||
|
||||
You can choose from several specifications for {% data variables.actions.hosted_runners %}.
|
||||
|
||||
### Specifications for general {% data variables.actions.hosted_runners %}
|
||||
|
||||
| CPU | Memory (RAM) | Storage (SSD) | Architecture | Operating system (OS) |
|
||||
| --- | ------------- | ------------- | ------------ | --------------------- |
|
||||
| 5 | 14 GB | 14 GB | arm64 (M2) | macOS |
|
||||
| 12 | 30 GB | 14 GB | x64 (Intel) | macOS |
|
||||
| 2 | 8 GB | 75 GB | x64, arm64 | Ubuntu |
|
||||
| 4 | 16 GB | 150 GB | x64, arm64 | Ubuntu, Windows |
|
||||
| 8 | 32 GB | 300 GB | x64, arm64 | Ubuntu, Windows |
|
||||
| 16 | 64 GB | 600 GB | x64, arm64 | Ubuntu, Windows |
|
||||
| 32 | 128 GB | 1200 GB | x64, arm64 | Ubuntu, Windows |
|
||||
| 64 | 208 GB | 2040 GB | arm64 | Ubuntu, Windows |
|
||||
| 64 | 256 GB | 2040 GB | x64 | Ubuntu, Windows |
|
||||
| 96 | 384 GB | 2040 GB | x64 | Ubuntu, Windows |
|
||||
|
||||
>[!NOTE] The 4-vCPU Windows runner only works with the Windows Server 2025 or the Base Windows 11 Desktop image.
|
||||
|
||||
>[!NOTE] The 5-vCPU macOS runner is in public preview and subject to change.
|
||||
|
||||
### Specifications for GPU {% data variables.actions.hosted_runners %}
|
||||
|
||||
| CPU | GPU | GPU card | Memory (RAM) | GPU memory (VRAM) | Storage (SSD) | Operating system (OS) |
|
||||
| --- | --- | -------- | ------------ | ----------------- | ------------- | --------------------- |
|
||||
| 4 | 1 | Tesla T4 | 28 GB | 16 GB | 176 GB | Ubuntu, Windows |
|
||||
|
||||
## Runner images
|
||||
|
||||
{% data variables.actions.hosted_runner_caps %}s run on virtual machines (VMs), and {% data variables.product.prodname_dotcom %} installs a virtual hard disk (VHD) on this machine during the VM creation process. You can choose from different VM images to install on your runners.
|
||||
|
||||
**{% data variables.product.prodname_dotcom %}-owned images:** These images are maintained by {% data variables.product.prodname_dotcom %} and are available for Linux x64, Windows x64, and macOS (x64 and arm) runners. For more information on these images and a full list of included tools for each runner operating system, see the [{% data variables.product.prodname_actions %} Runner Images](https://github.com/actions/runner-images) repository.
|
||||
|
||||
**Partner Images:** Partner images are not managed by {% data variables.product.prodname_dotcom %} and are pulled from the Azure Marketplace. See below for resources on where to find more information and to report issues for partner images.
|
||||
* [Base Windows 11 desktop image](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/microsoftwindowsdesktop.windows-11?tab=Overview).
|
||||
* [NVIDIA GPU-Optimized VMI](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/nvidia.ngc_azure_17_11)
|
||||
* [Data Science Virtual Machine - Windows 2019](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/microsoft-dsvm.dsvm-win-2019?tab=overview).
|
||||
* arm64 images: [`actions/partner-runner-images` repository](https://github.com/actions/partner-runner-images).
|
||||
|
||||
## Available macOS {% data variables.actions.hosted_runners %} and labels
|
||||
|
||||
The following machines are available for macOS {% data variables.actions.hosted_runners %}.
|
||||
|
||||
{% data reusables.actions.larger-runners-table %}
|
||||
|
||||
>[!NOTE] The XLarge macOS runner is in public preview and subject to change.
|
||||
|
||||
## Limitations for macOS {% data variables.actions.hosted_runners %}
|
||||
|
||||
{% data reusables.actions.macos-runner-limitations %}
|
||||
|
||||
## Networking for {% data variables.actions.hosted_runners %}
|
||||
|
||||
By default, {% data variables.actions.hosted_runners %} receive a dynamic IP address that changes for each job run. Optionally, {% data variables.product.prodname_ghe_cloud %} customers can configure their {% data variables.actions.hosted_runners %} to receive static IP addresses from {% data variables.product.prodname_dotcom %}'s IP address pool. For more information, see [AUTOTITLE](/authentication/keeping-your-account-and-data-secure/about-githubs-ip-addresses).
|
||||
|
||||
When enabled, instances of the {% data variables.actions.hosted_runner %} will receive IP addresses from specific ranges that are unique to the runner, allowing you to use the ranges to configure a firewall allowlist. {% ifversion fpt %}You can use up to 10 {% data variables.actions.hosted_runners %} with static IP address ranges in total across all your {% data variables.actions.hosted_runners %}{% endif %}{% ifversion ghec %}You can use up to 10 {% data variables.actions.hosted_runners %} with static IP address ranges for the {% data variables.actions.hosted_runners %} created at the enterprise level. In addition, you can use up to 10 {% data variables.actions.hosted_runners %} with static IP address ranges for the {% data variables.actions.hosted_runners %} created at the organization level, for each organization in your enterprise{% endif %}. For more information, see [AUTOTITLE](/actions/using-github-hosted-runners/managing-larger-runners#networking-for-larger-runners).
|
||||
|
||||
{% data reusables.actions.larger-runner-static-ip-contact-support %}
|
||||
|
||||
> [!NOTE]
|
||||
> If runners are unused for more than 30 days, their IP address ranges are automatically removed and cannot be recovered.
|
||||
|
||||
{% endif %}
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: About customizing GitHub Copilot Chat responses
|
||||
shortTitle: Customize Copilot responses
|
||||
intro: 'Learn about customizing {% data variables.copilot.copilot_chat %} responses to fit with your preferences and requirements.'
|
||||
intro: 'Learn about customizing the behavior of {% data variables.product.prodname_copilot %} to fit with your preferences and requirements.'
|
||||
versions:
|
||||
feature: copilot
|
||||
topics:
|
||||
@@ -50,6 +50,16 @@ redirect_from:
|
||||
* **Repository custom instructions** apply to conversations within the context of a specific repository. They are useful for defining project-specific coding standards, frameworks, or tools. For example, you can specify that a repository uses TypeScript and a particular library, ensuring consistent responses for all contributors.
|
||||
* **Organization custom instructions (public preview)** apply to conversations within the context of an organization on the {% data variables.product.github %} website. They are ideal for enforcing organization-wide preferences, such as a common language or security guidelines. Organization custom instructions can only be set by organization owners for organizations with a {% data variables.copilot.copilot_enterprise_short %} subscription.
|
||||
|
||||
### About repository custom instructions
|
||||
|
||||
Repository custom instructions consist of a single file, `.github/copilot-instructions.md`, that you create in a repository.
|
||||
|
||||
Repository custom instructions files are used for chat responses, for code review, and also by {% data variables.product.prodname_copilot_short %} when you assign it to an issue or ask it to create a pull request. Instructions included in this file can help {% data variables.product.prodname_copilot_short %} to work on files in a way that matches your team's working practices and conforms to coding standards for your project. See [AUTOTITLE](/copilot/using-github-copilot/coding-agent/about-assigning-tasks-to-copilot).
|
||||
|
||||
{% data reusables.copilot.repository-custom-instructions-example %}
|
||||
|
||||
{% data reusables.copilot.repository-cust-instr-code-review %}
|
||||
|
||||
{% endwebui %}
|
||||
|
||||
{% vscode %}
|
||||
@@ -122,6 +132,8 @@ Common use cases include:
|
||||
|
||||
{% data reusables.copilot.repository-custom-instructions-example %}
|
||||
|
||||
{% data reusables.copilot.repository-cust-instr-code-review %}
|
||||
|
||||
## About prompt files
|
||||
|
||||
> [!NOTE] Prompt files are {% data variables.release-phases.public_preview %} and subject to change.
|
||||
@@ -189,6 +201,8 @@ Common use cases include:
|
||||
|
||||
{% data reusables.copilot.repository-custom-instructions-example %}
|
||||
|
||||
{% data reusables.copilot.repository-cust-instr-code-review %}
|
||||
|
||||
{% endvisualstudio %}
|
||||
|
||||
{% jetbrains %}
|
||||
@@ -227,6 +241,28 @@ Common use cases include:
|
||||
|
||||
{% endxcode %}
|
||||
|
||||
## Writing effective custom instructions
|
||||
|
||||
The instructions you add should ideally be short, self-contained statements provide {% data variables.product.prodname_copilot_short %} with relevant information to help it work.
|
||||
|
||||
When writing custom instructions for a repository, you should also consider the size and complexity of your repository. The following types of instructions may work for a small repository with only a few contributors, but for a large and diverse repository, **these may cause problems**:
|
||||
|
||||
* Requests to refer to external resources when formulating a response
|
||||
* Instructions to answer in a particular style
|
||||
* Requests to always respond with a certain level of detail
|
||||
|
||||
For example, the following instructions **may not have the intended results**:
|
||||
|
||||
```markdown
|
||||
Always conform to the coding styles defined in styleguide.md in repo my-org/my-repo when generating code.
|
||||
|
||||
Use @terminal when answering questions about Git.
|
||||
|
||||
Answer all questions in the style of a friendly colleague, using informal language.
|
||||
|
||||
Answer all questions in less than 1000 characters, and words of no more than 12 characters.
|
||||
```
|
||||
|
||||
## Next steps
|
||||
|
||||
{% webui %}
|
||||
|
||||
@@ -55,7 +55,7 @@ AI-generated text completion to help you write pull request descriptions quickly
|
||||
|
||||
### {% data variables.product.prodname_copilot_short %} custom instructions
|
||||
|
||||
Enhance {% data variables.copilot.copilot_chat_short %} responses by providing contextual details on your preferences, tools, and requirements. See [AUTOTITLE](/copilot/customizing-copilot/about-customizing-github-copilot-chat-responses).
|
||||
Enhance {% data variables.copilot.copilot_chat_short %} responses by providing contextual details on your preferences, tools, and requirements. See [AUTOTITLE](/copilot/concepts/about-customizing-github-copilot-chat-responses).
|
||||
|
||||
### {% data variables.copilot.copilot_desktop_short %}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ redirect_from:
|
||||
|
||||
{% data reusables.copilot.organization-instructions-note %}
|
||||
|
||||
For an overview of the methods you can use to customize {% data variables.copilot.copilot_chat %} responses, see [AUTOTITLE](/copilot/customizing-copilot/about-customizing-github-copilot-chat-responses?tool=webui).
|
||||
For an overview of the methods you can use to customize {% data variables.copilot.copilot_chat %} responses, see [AUTOTITLE](/copilot/concepts/about-customizing-github-copilot-chat-responses?tool=webui).
|
||||
|
||||
## About organization custom instructions for {% data variables.copilot.copilot_chat %}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ redirect_from:
|
||||
|
||||
{% data reusables.copilot.personal-instructions-note %}
|
||||
|
||||
For an overview of the methods you can use to customize {% data variables.copilot.copilot_chat %} responses, see [AUTOTITLE](/copilot/customizing-copilot/about-customizing-github-copilot-chat-responses?tool=webui).
|
||||
For an overview of the methods you can use to customize {% data variables.copilot.copilot_chat %} responses, see [AUTOTITLE](/copilot/concepts/about-customizing-github-copilot-chat-responses?tool=webui).
|
||||
|
||||
## About personal custom instructions for {% data variables.copilot.copilot_chat %}
|
||||
|
||||
|
||||
@@ -19,80 +19,25 @@ This version of this article is for using repository custom instructions on the
|
||||
|
||||
## About repository custom instructions for {% data variables.product.prodname_copilot_short %}
|
||||
|
||||
Repository custom instructions let you provide {% data variables.product.prodname_copilot_short %} with repository-specific guidance and preferences. For a full introduction to custom instructions, see [AUTOTITLE](/copilot/concepts/about-customizing-github-copilot-chat-responses?tool=webui).
|
||||
|
||||
{% data reusables.copilot.repository-custom-instructions-support %}
|
||||
* **{% data variables.copilot.copilot_coding_agent %}**
|
||||
* **{% data variables.copilot.copilot_code-review_short %}**
|
||||
|
||||
{% data reusables.copilot.repository-custom-instructions-intro %} You can do this by creating a file in your repository that provides {% data variables.product.prodname_copilot_short %} with the contextual information it needs to generate higher quality responses.
|
||||
|
||||
The custom instructions file is used for chat responses, for code review, and also by {% data variables.product.prodname_copilot_short %} when you assign it to an issue or ask it to create a pull request. Instructions included in this file can help {% data variables.product.prodname_copilot_short %} to work on files in a way that matches your team's working practices and conforms to coding standards for your project. See [AUTOTITLE](/copilot/using-github-copilot/coding-agent/about-assigning-tasks-to-copilot).
|
||||
|
||||
### Example
|
||||
|
||||
{% data reusables.copilot.repository-custom-instructions-example %}
|
||||
|
||||
{% data reusables.copilot.repository-cust-instr-code-review %}
|
||||
|
||||
{% endwebui %}
|
||||
|
||||
{% vscode %}
|
||||
|
||||
This version of this article is for using repository custom instructions in {% data variables.product.prodname_vscode_shortname %}. Click the tabs above for instructions on using custom instructions in other environments.
|
||||
This version of this article is for using repository custom instructions and prompt files in {% data variables.product.prodname_vscode_shortname %}. Click the tabs above for instructions on using custom instructions in other environments.
|
||||
|
||||
## About repository custom instructions and prompt files for {% data variables.product.prodname_copilot_short %}
|
||||
|
||||
You can provide {% data variables.product.prodname_copilot_short %} with repository-wide instructions or reusable prompt files to give it context and guidance when working in {% data variables.product.prodname_vscode_shortname %}. For a full introduction to repository custom instructions and prompt files, including examples, see [AUTOTITLE](/copilot/concepts/about-customizing-github-copilot-chat-responses?tool=vscode).
|
||||
|
||||
{% data reusables.copilot.repository-custom-instructions-support %}
|
||||
* **{% data variables.copilot.copilot_code-review_short %}**
|
||||
|
||||
{% data reusables.copilot.repository-custom-instructions-intro %} You can do this by creating a file in your repositories that provides {% data variables.product.prodname_copilot_short %} with the contextual information it needs to generate higher quality responses.
|
||||
|
||||
There are two types of files you can use to provide context and instructions to {% data variables.product.prodname_copilot_short %} in {% data variables.product.prodname_vscode_shortname %}:
|
||||
|
||||
* **Repository custom instructions** allow you to specify repository-wide instructions and preferences, in a single file, that {% data variables.product.prodname_copilot_short %} will use when working in this repository.
|
||||
* **Prompt files** (public preview) allow you to save common prompt instructions and relevant context in Markdown files (`*.prompt.md`) that you can then reuse in your {% data variables.copilot.copilot_chat_short %} prompts. Prompt files are only available in {% data variables.product.prodname_vscode_shortname %}.
|
||||
|
||||
While custom instructions help to add codebase-wide context to each AI workflow, prompt files let you add instructions to a specific {% data variables.product.prodname_copilot_short %} interaction.
|
||||
|
||||
### Repository custom instructions example
|
||||
|
||||
{% data reusables.copilot.repository-custom-instructions-example %}
|
||||
|
||||
{% data reusables.copilot.repository-cust-instr-code-review %}
|
||||
|
||||
### Prompt file examples
|
||||
|
||||
The following examples demonstrate how to use prompt files.
|
||||
|
||||
* `New React form.prompt.md` - contains instructions for a reusable task to generate a form using React.
|
||||
|
||||
```markdown
|
||||
Your goal is to generate a new React form component.
|
||||
|
||||
Ask for the form name and fields if not provided.
|
||||
|
||||
Requirements for the form:
|
||||
- Use form design system components: [design-system/Form.md](../docs/design-system/Form.md)
|
||||
- Use `react-hook-form` for form state management:
|
||||
- Always define TypeScript types for your form data
|
||||
- Prefer *uncontrolled* components using register
|
||||
- Use `defaultValues` to prevent unnecessary rerenders
|
||||
- Use `yup` for validation:
|
||||
- Create reusable validation schemas in separate files
|
||||
- Use TypeScript types to ensure type safety
|
||||
- Customize UX-friendly validation rules
|
||||
```
|
||||
|
||||
* `API security review.prompt.md` - contains reusable information about security practices for REST APIs, which can be used to do security reviews of REST APIs.
|
||||
|
||||
```markdown
|
||||
Secure REST API review:
|
||||
- Ensure all endpoints are protected by authentication and authorization
|
||||
- Validate all user inputs and sanitize data
|
||||
- Implement rate limiting and throttling
|
||||
- Implement logging and monitoring for security events
|
||||
…
|
||||
```
|
||||
|
||||
{% endvscode %}
|
||||
|
||||
{% visualstudio %}
|
||||
@@ -103,17 +48,11 @@ This version of this article is for using repository custom instructions in {% d
|
||||
|
||||
## About repository custom instructions for {% data variables.product.prodname_copilot_short %}
|
||||
|
||||
Repository custom instructions let you provide {% data variables.product.prodname_copilot_short %} with repository-specific guidance and preferences. For a full introduction to custom instructions, see [AUTOTITLE](/copilot/concepts/about-customizing-github-copilot-chat-responses?tool=visualstudio).
|
||||
|
||||
{% data reusables.copilot.repository-custom-instructions-support %}
|
||||
* **{% data variables.copilot.copilot_code-review_short %}**
|
||||
|
||||
{% data reusables.copilot.repository-custom-instructions-intro %} You can do this by creating a file in your repositories that provides {% data variables.product.prodname_copilot_short %} with the contextual information it needs to generate higher quality responses.
|
||||
|
||||
### Example
|
||||
|
||||
{% data reusables.copilot.repository-custom-instructions-example %}
|
||||
|
||||
{% data reusables.copilot.repository-cust-instr-code-review %}
|
||||
|
||||
{% endvisualstudio %}
|
||||
|
||||
{% jetbrains %}
|
||||
@@ -124,13 +63,9 @@ This version of this article is for using repository custom instructions in JetB
|
||||
|
||||
## About repository custom instructions for {% data variables.copilot.copilot_chat %}
|
||||
|
||||
Repository custom instructions are currently supported for {% data variables.copilot.copilot_chat_short %} in JetBrains IDEs, {% data variables.product.prodname_vs %}, {% data variables.product.prodname_vscode_shortname %}, Xcode, and on the {% data variables.product.github %} website.
|
||||
Repository custom instructions let you provide {% data variables.product.prodname_copilot_short %} with repository-specific guidance and preferences. For a full introduction to custom instructions, see [AUTOTITLE](/copilot/concepts/about-customizing-github-copilot-chat-responses?tool=jetbrains).
|
||||
|
||||
{% data variables.product.prodname_copilot %} can provide chat responses that are tailored to the way your team works, the tools you use, or the specifics of your project, if you provide it with enough context to do so. Instead of repeatedly adding this contextual detail to your chat questions, you can create a file in your repository that automatically adds this information for you. The additional information is not displayed in the chat, but is available to {% data variables.product.prodname_copilot_short %} to allow it to generate higher quality responses.
|
||||
|
||||
### Example
|
||||
|
||||
{% data reusables.copilot.repository-custom-instructions-example %}
|
||||
{% data reusables.copilot.repository-custom-instructions-support %}
|
||||
|
||||
{% endjetbrains %}
|
||||
|
||||
@@ -142,13 +77,9 @@ This version of this article is for using repository custom instructions in Xcod
|
||||
|
||||
## About repository custom instructions for {% data variables.copilot.copilot_chat %}
|
||||
|
||||
Repository custom instructions are currently supported for {% data variables.copilot.copilot_chat_short %} in Xcode, {% data variables.product.prodname_vs %}, {% data variables.product.prodname_vscode_shortname %} JetBrains IDEs, and on the {% data variables.product.github %} website.
|
||||
Repository custom instructions let you provide {% data variables.product.prodname_copilot_short %} with repository-specific guidance and preferences. For a full introduction to custom instructions, see [AUTOTITLE](/copilot/concepts/about-customizing-github-copilot-chat-responses?tool=xcode).
|
||||
|
||||
{% data variables.product.prodname_copilot %} can provide chat responses that are tailored to the way your team works, the tools you use, or the specifics of your project, if you provide it with enough context to do so. Instead of repeatedly adding this contextual detail to your chat questions, you can create a file in your repository that automatically adds this information for you. The additional information is not displayed in the chat, but is available to {% data variables.product.prodname_copilot_short %} to allow it to generate higher quality responses.
|
||||
|
||||
### Example
|
||||
|
||||
{% data reusables.copilot.repository-custom-instructions-example %}
|
||||
{% data reusables.copilot.repository-custom-instructions-support %}
|
||||
|
||||
{% endxcode %}
|
||||
|
||||
@@ -289,28 +220,6 @@ Did you successfully add a custom instructions file to your repository?
|
||||
|
||||
{% endnote %}
|
||||
|
||||
## Writing effective repository custom instructions
|
||||
|
||||
The instructions you add to the `.github/copilot-instructions.md` file should be short, self-contained statements provide {% data variables.product.prodname_copilot_short %} with relevant information to help it work in this repository.
|
||||
|
||||
You should also consider the size and complexity of your repository. The following types of instructions may work for a small repository with only a few contributors, but for a large and diverse repository, **these may cause problems**:
|
||||
|
||||
* Requests to refer to external resources when formulating a response
|
||||
* Instructions to answer in a particular style
|
||||
* Requests to always respond with a certain level of detail
|
||||
|
||||
For example, the following instructions **may not have the intended results**:
|
||||
|
||||
```markdown
|
||||
Always conform to the coding styles defined in styleguide.md in repo my-org/my-repo when generating code.
|
||||
|
||||
Use @terminal when answering questions about Git.
|
||||
|
||||
Answer all questions in the style of a friendly colleague, using informal language.
|
||||
|
||||
Answer all questions in less than 1000 characters, and words of no more than 12 characters.
|
||||
```
|
||||
|
||||
## Repository custom instructions in use
|
||||
|
||||
The instructions in the `.github/copilot-instructions.md` file are available for use by {% data variables.copilot.copilot_chat_short %} as soon as you save the file. The complete set of instructions will be automatically added to requests that you submit to {% data variables.product.prodname_copilot_short %} in the context of that repository. For example, they are added to the prompt you submit to {% data variables.copilot.copilot_chat_short %}.
|
||||
|
||||
@@ -39,7 +39,7 @@ Follow these best practices to get the most out of combining MCP servers with ag
|
||||
* **Provide context**: Include relevant background information about your project and requirements, including links to external resources that {% data variables.product.prodname_copilot_short %} can access.
|
||||
* **Set boundaries**: Specify any constraints or limitations for the task. For example, if you want {% data variables.product.prodname_copilot_short %} to only plan a new feature and not make any changes yet, specify that. You can also limit which MCP tools are enabled.
|
||||
* **Request confirmations**: Ask {% data variables.product.prodname_copilot_short %} to confirm its understanding before proceeding with significant changes.
|
||||
* **Use prompt files or custom instructions**: You can create prompt files or custom instructions files to guide {% data variables.product.prodname_copilot_short %} on how to behave for different MCP servers. See [AUTOTITLE](/copilot/customizing-copilot/about-customizing-github-copilot-chat-responses).
|
||||
* **Use prompt files or custom instructions**: You can create prompt files or custom instructions files to guide {% data variables.product.prodname_copilot_short %} on how to behave for different MCP servers. See [AUTOTITLE](/copilot/concepts/about-customizing-github-copilot-chat-responses).
|
||||
|
||||
### MCP server use
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Customers on {% data variables.product.prodname_team %} and {% data variables.product.prodname_ghe_cloud %} plans can choose from a range of managed virtual machines that have more resources than the [standard {% data variables.product.prodname_dotcom %}-hosted runners](/actions/how-tos/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources). These machines are referred to as "{% data variables.actions.hosted_runner %}." They offer the following advanced features:
|
||||
Customers on {% data variables.product.prodname_team %} and {% data variables.product.prodname_ghe_cloud %} plans can choose from a range of managed virtual machines that have more resources than the [standard {% data variables.product.prodname_dotcom %}-hosted runners](/actions/how-tos/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources). These machines are referred to as "{% data variables.actions.hosted_runners %}." They offer the following advanced features:
|
||||
|
||||
* More RAM, CPU, and disk space
|
||||
* Static IP addresses
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
* **Opt in to preview features:** If enabled, users can test new {% data variables.product.prodname_copilot_short %} features that are not yet generally available. Be aware that previews of features may have flaws, and the features may be changed or discontinued at any time. Current previews of {% data variables.product.prodname_copilot_short %} features include:
|
||||
|
||||
* {% data variables.copilot.copilot_spaces %}. See [AUTOTITLE](/copilot/using-github-copilot/copilot-spaces/about-organizing-and-sharing-context-with-copilot-spaces).
|
||||
* Repository custom instructions for {% data variables.copilot.copilot_code-review_short %}. See [AUTOTITLE](/copilot/customizing-copilot/about-customizing-github-copilot-chat-responses).
|
||||
* Repository custom instructions for {% data variables.copilot.copilot_code-review_short %}. See [AUTOTITLE](/copilot/concepts/about-customizing-github-copilot-chat-responses).
|
||||
|
||||
@@ -1 +1 @@
|
||||
For examples of custom instructions used to configure {% data variables.copilot.copilot_code-review_short %}, see [AUTOTITLE](/copilot/how-tos/agents/copilot-code-review/using-copilot-code-review?tool=webui#customizing-copilots-reviews-with-custom-instructions).
|
||||
For examples of repository custom instructions used to configure {% data variables.copilot.copilot_code-review_short %}, see [AUTOTITLE](/copilot/how-tos/agents/copilot-code-review/using-copilot-code-review?tool=webui#customizing-copilots-reviews-with-custom-instructions).
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
Repository custom instructions are currently supported for:
|
||||
* **{% data variables.copilot.copilot_chat_short %}** in {% data variables.product.prodname_vs %}, {% data variables.product.prodname_vscode_shortname %} and on the {% data variables.product.github %} website
|
||||
* **{% data variables.copilot.copilot_chat_short %}** in {% data variables.product.prodname_vs %}, {% data variables.product.prodname_vscode_shortname %}, JetBrains IDEs, Xcode, and on the {% data variables.product.github %} website
|
||||
|
||||
@@ -19,27 +19,111 @@ import { renderContentWithFallback } from '@/languages/lib/render-with-fallback'
|
||||
import { deprecated, supported } from '@/versions/lib/enterprise-server-releases'
|
||||
import { allPlatforms } from '@/tools/lib/all-platforms'
|
||||
|
||||
import type { Context, FrontmatterVersions } from '@/types'
|
||||
|
||||
// We're going to check a lot of pages' "ID" (the first part of
|
||||
// the relativePath) against `productMap` to make sure it's valid.
|
||||
// To avoid having to do `Object.keys(productMap).includes(id)`
|
||||
// every single time, we turn it into a Set once.
|
||||
const productMapKeysAsSet = new Set(Object.keys(productMap))
|
||||
|
||||
type ReadFileContentsResult = {
|
||||
data?: any
|
||||
content?: string
|
||||
errors?: any[]
|
||||
}
|
||||
|
||||
type PageInitOptions = {
|
||||
languageCode: string
|
||||
relativePath: string
|
||||
basePath: string
|
||||
}
|
||||
|
||||
type PageReadResult = PageInitOptions & {
|
||||
fullPath: string
|
||||
markdown: string
|
||||
frontmatterErrors?: any[]
|
||||
} & any
|
||||
|
||||
type RenderOptions = {
|
||||
preferShort?: boolean
|
||||
unwrap?: boolean
|
||||
textOnly?: boolean
|
||||
throwIfEmpty?: boolean
|
||||
}
|
||||
|
||||
type CommunityRedirect = {
|
||||
name: string
|
||||
href: string
|
||||
}
|
||||
|
||||
type GuideWithType = {
|
||||
href: string
|
||||
title: string
|
||||
type?: string
|
||||
topics?: string[]
|
||||
}
|
||||
|
||||
export class FrontmatterErrorsError extends Error {
|
||||
constructor(message, frontmatterErrors) {
|
||||
public frontmatterErrors: string[]
|
||||
|
||||
constructor(message: string, frontmatterErrors: string[]) {
|
||||
super(message)
|
||||
this.frontmatterErrors = frontmatterErrors
|
||||
}
|
||||
}
|
||||
|
||||
class Page {
|
||||
static async init(opts) {
|
||||
opts = await Page.read(opts)
|
||||
if (!opts) return
|
||||
return new Page(opts)
|
||||
// Core properties from PageFrontmatter
|
||||
public title: string = ''
|
||||
public rawTitle: string = ''
|
||||
public shortTitle?: string
|
||||
public rawShortTitle?: string
|
||||
public intro: string = ''
|
||||
public rawIntro?: string
|
||||
public product?: string
|
||||
public rawProduct?: string
|
||||
public permissions?: string
|
||||
public rawPermissions?: string
|
||||
public versions: FrontmatterVersions = {}
|
||||
public showMiniToc?: boolean
|
||||
public hidden?: boolean
|
||||
public redirect_from?: string[]
|
||||
public learningTracks?: any[]
|
||||
public rawLearningTracks?: string[]
|
||||
public includeGuides?: GuideWithType[]
|
||||
public rawIncludeGuides?: string[]
|
||||
public introLinks?: Record<string, string>
|
||||
public rawIntroLinks?: Record<string, string>
|
||||
|
||||
// Derived properties
|
||||
public languageCode!: string
|
||||
public relativePath!: string
|
||||
public basePath!: string
|
||||
public fullPath!: string
|
||||
public markdown!: string
|
||||
public documentType: string
|
||||
public applicableVersions: string[]
|
||||
public permalinks: Permalink[]
|
||||
public tocItems?: any[]
|
||||
public communityRedirect?: CommunityRedirect
|
||||
public detectedPlatforms: string[] = []
|
||||
public includesPlatformSpecificContent: boolean = false
|
||||
public detectedTools: string[] = []
|
||||
public includesToolSpecificContent: boolean = false
|
||||
public allToolsParsed: typeof allTools = allTools
|
||||
public introPlainText?: string
|
||||
|
||||
// Bound method
|
||||
public render: (context: Context) => Promise<string>
|
||||
|
||||
static async init(opts: PageInitOptions): Promise<Page | undefined> {
|
||||
const readResult = await Page.read(opts)
|
||||
if (!readResult) return
|
||||
return new Page(readResult)
|
||||
}
|
||||
|
||||
static async read(opts) {
|
||||
static async read(opts: PageInitOptions): Promise<PageReadResult | false> {
|
||||
assert(opts.languageCode, 'languageCode is required')
|
||||
assert(opts.relativePath, 'relativePath is required')
|
||||
assert(opts.basePath, 'basePath is required')
|
||||
@@ -50,7 +134,11 @@ class Page {
|
||||
// Per https://nodejs.org/api/fs.html#fs_fs_exists_path_callback
|
||||
// its better to read and handle errors than to check access/stats first
|
||||
try {
|
||||
const { data, content, errors: frontmatterErrors } = await readFileContents(fullPath)
|
||||
const {
|
||||
data,
|
||||
content,
|
||||
errors: frontmatterErrors,
|
||||
}: ReadFileContentsResult = await readFileContents(fullPath)
|
||||
|
||||
// The `|| ''` is for pages that are purely frontmatter.
|
||||
// So the `content` property will be `undefined`.
|
||||
@@ -72,11 +160,11 @@ class Page {
|
||||
// where as notations like `__GHES_DEPRECATED__[3]`
|
||||
// or `__GHES_SUPPORTED__[0]` are static.
|
||||
if (opts.basePath.split(path.sep).includes('fixtures')) {
|
||||
supported.forEach((version, i, arr) => {
|
||||
supported.forEach((version: string, i: number, arr: string[]) => {
|
||||
markdown = markdown.replaceAll(`__GHES_SUPPORTED__[${i}]`, version)
|
||||
markdown = markdown.replaceAll(`__GHES_SUPPORTED__[-${arr.length - i}]`, version)
|
||||
})
|
||||
deprecated.forEach((version, i, arr) => {
|
||||
deprecated.forEach((version: string, i: number, arr: string[]) => {
|
||||
markdown = markdown.replaceAll(`__GHES_DEPRECATED__[${i}]`, version)
|
||||
markdown = markdown.replaceAll(`__GHES_DEPRECATED__[-${arr.length - i}]`, version)
|
||||
})
|
||||
@@ -86,25 +174,29 @@ class Page {
|
||||
...opts,
|
||||
relativePath,
|
||||
fullPath,
|
||||
...data,
|
||||
...(data || {}),
|
||||
markdown,
|
||||
frontmatterErrors,
|
||||
}
|
||||
} catch (err) {
|
||||
} as PageReadResult
|
||||
} catch (err: any) {
|
||||
if (err.code === 'ENOENT') return false
|
||||
console.error(err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
constructor(opts) {
|
||||
constructor(opts: PageReadResult) {
|
||||
if (opts.frontmatterErrors && opts.frontmatterErrors.length) {
|
||||
throw new FrontmatterErrorsError(
|
||||
`${opts.frontmatterErrors.length} frontmatter errors trying to load ${opts.fullPath}`,
|
||||
opts.frontmatterErrors,
|
||||
)
|
||||
}
|
||||
delete opts.frontmatterErrors
|
||||
Object.assign(this, { ...opts })
|
||||
|
||||
// Remove frontmatter errors before assignment
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { frontmatterErrors: _, ...cleanOpts } = opts
|
||||
Object.assign(this, cleanOpts)
|
||||
|
||||
// Store raw data so we can cache parsed versions
|
||||
this.rawIntro = this.intro
|
||||
@@ -113,7 +205,7 @@ class Page {
|
||||
this.rawProduct = this.product
|
||||
this.rawPermissions = this.permissions
|
||||
this.rawLearningTracks = this.learningTracks
|
||||
this.rawIncludeGuides = this.includeGuides
|
||||
this.rawIncludeGuides = this.includeGuides as any
|
||||
this.rawIntroLinks = this.introLinks
|
||||
|
||||
// Is this the Homepage or a Product, Category, Topic, or Article?
|
||||
@@ -130,7 +222,7 @@ class Page {
|
||||
const versionsParentProductIsNotAvailableIn = this.applicableVersions
|
||||
// only the homepage will not have this.parentProduct
|
||||
.filter(
|
||||
(availableVersion) =>
|
||||
(availableVersion: string) =>
|
||||
this.parentProduct && !this.parentProduct.versions.includes(availableVersion),
|
||||
)
|
||||
|
||||
@@ -164,12 +256,15 @@ class Page {
|
||||
return this
|
||||
}
|
||||
|
||||
buildRedirects() {
|
||||
return generateRedirectsForPermalinks(this.permalinks, this.redirect_from || [])
|
||||
buildRedirects(): Record<string, string> {
|
||||
return generateRedirectsForPermalinks(this.permalinks, this.redirect_from || []) as Record<
|
||||
string,
|
||||
string
|
||||
>
|
||||
}
|
||||
|
||||
// Infer the parent product ID from the page's relative file path
|
||||
get parentProductId() {
|
||||
get parentProductId(): string | null {
|
||||
// Each page's top-level content directory matches its product ID
|
||||
const id = this.relativePath.split('/')[0]
|
||||
|
||||
@@ -184,17 +279,21 @@ class Page {
|
||||
return id
|
||||
}
|
||||
|
||||
get parentProduct() {
|
||||
return productMap[this.parentProductId]
|
||||
get parentProduct(): any {
|
||||
const id = this.parentProductId
|
||||
return id ? productMap[id] : undefined
|
||||
}
|
||||
|
||||
async renderTitle(context, opts = { preferShort: true }) {
|
||||
async renderTitle(
|
||||
context: Context,
|
||||
opts: RenderOptions = { preferShort: true },
|
||||
): Promise<string> {
|
||||
return opts.preferShort && this.shortTitle
|
||||
? this.renderProp('shortTitle', context, opts)
|
||||
: this.renderProp('title', context, opts)
|
||||
}
|
||||
|
||||
async _render(context) {
|
||||
private async _render(context: Context): Promise<string> {
|
||||
// use English IDs/anchors for translated headings, so links don't break (see #8572)
|
||||
if (this.languageCode !== 'en') {
|
||||
const englishHeadings = getEnglishHeadings(this, context)
|
||||
@@ -246,7 +345,7 @@ class Page {
|
||||
|
||||
// introLinks may contain Liquid and need to have versioning processed.
|
||||
if (this.rawIntroLinks) {
|
||||
const introLinks = {}
|
||||
const introLinks: Record<string, string> = {}
|
||||
for (const [rawKey, value] of Object.entries(this.rawIntroLinks)) {
|
||||
introLinks[rawKey] = await renderContent(value, context, {
|
||||
textOnly: true,
|
||||
@@ -257,8 +356,8 @@ class Page {
|
||||
}
|
||||
|
||||
if (this.rawIncludeGuides) {
|
||||
this.includeGuides = await getLinkData(this.rawIncludeGuides, context)
|
||||
this.includeGuides.map((guide) => {
|
||||
this.includeGuides = (await getLinkData(this.rawIncludeGuides, context)) as GuideWithType[]
|
||||
this.includeGuides?.map((guide: any) => {
|
||||
const { page } = guide
|
||||
guide.type = page.type
|
||||
if (page.topics) {
|
||||
@@ -272,7 +371,7 @@ class Page {
|
||||
// set a flag so layout knows whether to render a mac/windows/linux switcher element
|
||||
// Remember, the values of platform is matched in
|
||||
// the handleInvalidQuerystringValues shielding middleware.
|
||||
this.detectedPlatforms = allPlatforms.filter((platform) => {
|
||||
this.detectedPlatforms = allPlatforms.filter((platform: string) => {
|
||||
// This matches `ghd-tool mac` but not `ghd-tool macos`
|
||||
// Whereas `html.includes('ghd-tool mac')` would match both.
|
||||
const regex = new RegExp(`ghd-tool ${platform}\\b|platform-${platform}\\b`)
|
||||
@@ -281,7 +380,7 @@ class Page {
|
||||
this.includesPlatformSpecificContent = this.detectedPlatforms.length > 0
|
||||
|
||||
// set flags for webui, cli, etc switcher element
|
||||
this.detectedTools = Object.keys(allTools).filter((tool) => {
|
||||
this.detectedTools = Object.keys(allTools).filter((tool: string) => {
|
||||
// This matches `ghd-tool jetbrain` but not `ghd-tool jetbrain_beta`
|
||||
// Whereas `html.includes('ghd-tool jetbrain')` would match both.
|
||||
const regex = new RegExp(`ghd-tool ${tool}\\b|tool-${tool}\\b`)
|
||||
@@ -298,8 +397,12 @@ class Page {
|
||||
|
||||
// Allow other modules (like custom liquid tags) to make one-off requests
|
||||
// for a page's rendered properties like `title` and `intro`
|
||||
async renderProp(propName, context, opts = { unwrap: false }) {
|
||||
let prop
|
||||
async renderProp(
|
||||
propName: string,
|
||||
context: Context,
|
||||
opts: RenderOptions = { unwrap: false },
|
||||
): Promise<string> {
|
||||
let prop: string
|
||||
if (propName === 'title') {
|
||||
prop = 'rawTitle'
|
||||
} else if (propName === 'shortTitle') {
|
||||
@@ -316,13 +419,13 @@ class Page {
|
||||
|
||||
// The unwrap option removes surrounding tags from a string, preserving any inner HTML
|
||||
const $ = cheerio.load(html, { xmlMode: true })
|
||||
return $.root().contents().html()
|
||||
return $.root().contents().html() || ''
|
||||
}
|
||||
|
||||
// infer current page's corresponding homepage
|
||||
// /en/articles/foo -> /en
|
||||
// /en/enterprise/2.14/user/articles/foo -> /en/enterprise/2.14/user
|
||||
static getHomepage(requestPath) {
|
||||
static getHomepage(requestPath: string): string {
|
||||
return requestPath.replace(/\/articles.*/, '')
|
||||
}
|
||||
}
|
||||
@@ -60,7 +60,7 @@ export default async function glossaries(req: ExtendedRequest, res: Response, ne
|
||||
)
|
||||
}
|
||||
description = await executeWithFallback(
|
||||
req.context,
|
||||
req.context!,
|
||||
() => liquid.parseAndRender(description, req.context),
|
||||
(enContext: Context) => {
|
||||
const { term } = glossary
|
||||
|
||||
@@ -62,15 +62,30 @@ All previously archived content lives in its own repository. For example, GHES 3
|
||||
|
||||
1. Update all translation directories to the latest `main` branch.
|
||||
|
||||
1. Hide search component temporarily while scraping docs in `src/search/components/Search.tsx`, by adding the `visually-hidden` class to the `form` element:
|
||||
1. Hide search components temporarily while scraping docs by adding the `visually-hidden` class to the search components:
|
||||
|
||||
**In `src/search/components/input/SearchBarButton.tsx`**, wrap the return statement content:
|
||||
|
||||
```javascript
|
||||
return (
|
||||
<div data-testid="search">
|
||||
<div className="position-relative z-2">
|
||||
<form
|
||||
role="search"
|
||||
className="width-full d-flex visually-hidden"
|
||||
<div className="visually-hidden">
|
||||
{/* existing search button content */}
|
||||
</div>
|
||||
)
|
||||
```
|
||||
|
||||
**In `src/search/components/input/SearchOverlayContainer.tsx`**, wrap the return statement content:
|
||||
|
||||
```javascript
|
||||
if (isSearchOpen) {
|
||||
return (
|
||||
<div className="visually-hidden">
|
||||
<SearchOverlay
|
||||
// ... existing props
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
1. Ensure your build is up to date:
|
||||
@@ -93,7 +108,7 @@ All previously archived content lives in its own repository. For example, GHES 3
|
||||
npm run deprecate-ghes-archive
|
||||
```
|
||||
|
||||
1. Revert changes to `src/search/components/Search.tsx`.
|
||||
1. Revert changes to `src/search/components/input/SearchBarButton.tsx` and `src/search/components/input/SearchOverlayContainer.tsx`.
|
||||
|
||||
1. Check in any change to `src/ghes-releases/lib/enterprise-dates.json`.
|
||||
|
||||
@@ -158,7 +173,7 @@ All previously archived content lives in its own repository. For example, GHES 3
|
||||
1. Poke around several deprecated pages by navigating to `docs.github.com/enterprise/<DEPRECATED VERSION>`, and ensure that:
|
||||
- Stylesheets are working properly
|
||||
- Images are rendering properly
|
||||
- The search functionality was disabled
|
||||
- The search functionality was disabled during scraping
|
||||
- Look at any console errors to ensure that no new unexpected errors were introduced. You can look at previous errors by viewing a previously completed deprecation page.
|
||||
- You should see a banner on the top of every deprecated page with the date that the version was deprecated.
|
||||
- You should see a banner at the top of every page for the oldes currently supported version with the date that it will be deprecated in the ~3 months.
|
||||
|
||||
@@ -7,7 +7,19 @@
|
||||
* It looks for easy "low hanging fruit" that we can correct for.
|
||||
*
|
||||
*/
|
||||
export function correctTranslatedContentStrings(content, englishContent, context = {}) {
|
||||
|
||||
interface CorrectionContext {
|
||||
code?: string
|
||||
dottedPath?: string
|
||||
relativePath?: string
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export function correctTranslatedContentStrings(
|
||||
content: string,
|
||||
englishContent: string,
|
||||
context: CorrectionContext = {},
|
||||
): string {
|
||||
// A lot of translations have corruptions around the AUTOTITLE links.
|
||||
// We've requested that these are corrected back but as a temporary
|
||||
// solution we'll manually recover now.
|
||||
@@ -294,7 +306,7 @@ export function correctTranslatedContentStrings(content, englishContent, context
|
||||
const keyString = '5DE3 E050 9C47 EA3C F04A 42D3 4AEE 18F8 3AFD EB23'
|
||||
const translatedSentences = [
|
||||
// ru
|
||||
'Полный отпечаток ключа — `' + keyString + '`.',
|
||||
'Полный отпечаток ключа\u00A0\u2014 `' + keyString + '`.',
|
||||
// ko
|
||||
`키의 전체 지문은 \`${keyString}\`입니다.`,
|
||||
// es
|
||||
@@ -306,7 +318,7 @@ export function correctTranslatedContentStrings(content, englishContent, context
|
||||
// ja
|
||||
`キーの完全な指紋は、\`${keyString}\` です。`,
|
||||
// fr
|
||||
`L’empreinte digitale complète de la clé est \`${keyString}\`.`,
|
||||
`L\u2019empreinte digitale complète de la clé est \`${keyString}\`.`,
|
||||
// de
|
||||
`Der vollständige Fingerabdruck des Schlüssels ist \`${keyString}\`.`,
|
||||
]
|
||||
@@ -1,20 +1,40 @@
|
||||
import { fromMarkdown } from 'mdast-util-from-markdown'
|
||||
import { toString } from 'mdast-util-to-string'
|
||||
import { visit } from 'unist-util-visit'
|
||||
import type { Node } from 'unist'
|
||||
|
||||
import findPage from '@/frame/lib/find-page'
|
||||
import { getDataByLanguage } from '@/data-directory/lib/get-data'
|
||||
import type { Context } from '@/types'
|
||||
|
||||
interface HeadingNode extends Node {
|
||||
type: 'heading'
|
||||
depth: number
|
||||
}
|
||||
|
||||
interface PageWithMarkdown {
|
||||
relativePath: string
|
||||
markdown: string
|
||||
}
|
||||
|
||||
interface GlossaryTerm {
|
||||
term: string
|
||||
slug: string
|
||||
}
|
||||
|
||||
// for any translated page, first get corresponding English markdown
|
||||
// then get the headings on both the translated and English pageMap
|
||||
// finally, create a map of translation:English for all headings on the page
|
||||
export default function getEnglishHeadings(page, context) {
|
||||
export default function getEnglishHeadings(
|
||||
page: PageWithMarkdown,
|
||||
context: Context,
|
||||
): Record<string, string> | undefined {
|
||||
// Special handling for glossaries, because their headings are
|
||||
// generated programmatically.
|
||||
if (page.relativePath.endsWith('/github-glossary.md')) {
|
||||
// Return an object of `{ localized-term: english-slug }`
|
||||
const languageGlossary = getDataByLanguage('glossaries.external', 'en')
|
||||
return languageGlossary.reduce((prev, curr) => {
|
||||
const languageGlossary = getDataByLanguage('glossaries.external', 'en') as GlossaryTerm[]
|
||||
return languageGlossary.reduce((prev: Record<string, string>, curr: GlossaryTerm) => {
|
||||
prev[curr.term] = curr.slug
|
||||
return prev
|
||||
}, {})
|
||||
@@ -35,20 +55,21 @@ export default function getEnglishHeadings(page, context) {
|
||||
if (!englishHeadings.length) return
|
||||
|
||||
// return a map from translation:English
|
||||
return Object.assign(
|
||||
...translatedHeadings.map((k, i) => ({
|
||||
[k]: englishHeadings[i],
|
||||
})),
|
||||
)
|
||||
const headingMap: Record<string, string> = {}
|
||||
translatedHeadings.forEach((k: string, i: number) => {
|
||||
headingMap[k] = englishHeadings[i]
|
||||
})
|
||||
return headingMap
|
||||
}
|
||||
|
||||
function getHeadings(markdown) {
|
||||
function getHeadings(markdown: string): string[] {
|
||||
const ast = fromMarkdown(markdown)
|
||||
const headings = []
|
||||
const headings: string[] = []
|
||||
|
||||
visit(ast, (node) => {
|
||||
visit(ast, (node: Node) => {
|
||||
if (node.type !== 'heading') return
|
||||
if (![2, 3, 4].includes(node.depth)) return
|
||||
const headingNode = node as HeadingNode
|
||||
if (![2, 3, 4].includes(headingNode.depth)) return
|
||||
headings.push(toString(node))
|
||||
})
|
||||
|
||||
@@ -1,26 +1,47 @@
|
||||
import { renderContent } from '@/content-render/index'
|
||||
import Page from '@/frame/lib/page'
|
||||
import { TitleFromAutotitleError } from '@/content-render/unified/rewrite-local-links'
|
||||
import type { Context } from '@/types'
|
||||
|
||||
export class EmptyTitleError extends Error {}
|
||||
|
||||
interface LiquidToken {
|
||||
file?: string
|
||||
getPosition?: () => [number, number]
|
||||
}
|
||||
|
||||
interface LiquidError extends Error {
|
||||
token?: LiquidToken
|
||||
originalError?: Error
|
||||
}
|
||||
|
||||
interface RenderOptions {
|
||||
throwIfEmpty?: boolean
|
||||
textOnly?: boolean
|
||||
cache?: boolean | ((template: string, context: any) => string)
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
const LIQUID_ERROR_NAMES = new Set(['RenderError', 'ParseError', 'TokenizationError'])
|
||||
export const isLiquidError = (error) =>
|
||||
error instanceof Error && error.name && LIQUID_ERROR_NAMES.has(error.name)
|
||||
export const isLiquidError = (error: unknown): error is LiquidError =>
|
||||
error instanceof Error && error.name !== undefined && LIQUID_ERROR_NAMES.has(error.name)
|
||||
|
||||
const isAutotitleError = (error) => error instanceof TitleFromAutotitleError
|
||||
const isEmptyTitleError = (error) => error instanceof EmptyTitleError
|
||||
const isAutotitleError = (error: unknown): error is TitleFromAutotitleError =>
|
||||
error instanceof TitleFromAutotitleError
|
||||
|
||||
const isFallbackableError = (error) =>
|
||||
const isEmptyTitleError = (error: unknown): error is EmptyTitleError =>
|
||||
error instanceof EmptyTitleError
|
||||
|
||||
const isFallbackableError = (error: unknown): boolean =>
|
||||
isLiquidError(error) || isAutotitleError(error) || isEmptyTitleError(error)
|
||||
|
||||
/**
|
||||
* Creates an HTML comment with translation fallback error information
|
||||
* Includes detailed debugging information for translators
|
||||
*/
|
||||
export function createTranslationFallbackComment(error, property) {
|
||||
export function createTranslationFallbackComment(error: Error, property: string): string {
|
||||
const errorType = error.name || 'UnknownError'
|
||||
let errorDetails = []
|
||||
const errorDetails: string[] = []
|
||||
|
||||
// Add basic error information
|
||||
errorDetails.push(`TRANSLATION_FALLBACK`)
|
||||
@@ -82,14 +103,21 @@ export function createTranslationFallbackComment(error, property) {
|
||||
// function. This means, we can know, in the middleware (which is a
|
||||
// higher level than `lib/`) how to use the URL to figure out the
|
||||
// equivalent English page instance.
|
||||
export async function renderContentWithFallback(page, property, context, options) {
|
||||
export async function renderContentWithFallback(
|
||||
// Using `any` type for page because the actual Page class from @/frame/lib/page
|
||||
// has more properties than the Page interface defined in @/types, causing type conflicts
|
||||
page: any,
|
||||
property: string,
|
||||
context: Context,
|
||||
options?: RenderOptions,
|
||||
): Promise<string> {
|
||||
if (!(page instanceof Page)) {
|
||||
throw new Error(`The first argument has to be Page instance (not ${typeof page})`)
|
||||
}
|
||||
if (typeof property !== 'string') {
|
||||
throw new Error(`The second argument has to be a string (not ${typeof property})`)
|
||||
}
|
||||
const template = page[property]
|
||||
const template = (page as any)[property] as string
|
||||
try {
|
||||
const output = await renderContent(template, context, options)
|
||||
if (options && options.throwIfEmpty && !output.trim()) {
|
||||
@@ -101,7 +129,7 @@ export async function renderContentWithFallback(page, property, context, options
|
||||
// on English for.
|
||||
if (isFallbackableError(error) && context.getEnglishPage) {
|
||||
const enPage = context.getEnglishPage(context)
|
||||
const englishTemplate = enPage[property]
|
||||
const englishTemplate = (enPage as any)[property] as string
|
||||
// If you don't change the context, it'll confuse the liquid plugins
|
||||
// like `data.js` that uses `environment.scope.currentLanguage`
|
||||
const enContext = Object.assign({}, context, { currentLanguage: 'en' })
|
||||
@@ -112,7 +140,7 @@ export async function renderContentWithFallback(page, property, context, options
|
||||
// Add HTML comment with error details for non-English languages
|
||||
// Skip for textOnly rendering to avoid breaking plain text output
|
||||
if (context.currentLanguage !== 'en' && !options?.textOnly) {
|
||||
const errorComment = createTranslationFallbackComment(error, property)
|
||||
const errorComment = createTranslationFallbackComment(error as Error, property)
|
||||
return errorComment + '\n' + fallbackContent
|
||||
}
|
||||
|
||||
@@ -137,19 +165,23 @@ export async function renderContentWithFallback(page, property, context, options
|
||||
// (enContext) => renderContent(enTrack.title, enContext, renderOpts)
|
||||
// )
|
||||
//
|
||||
export async function executeWithFallback(context, callable, fallback) {
|
||||
export async function executeWithFallback<T>(
|
||||
context: Context,
|
||||
callable: (context: Context) => T | Promise<T>,
|
||||
fallback: (enContext: Context) => T | Promise<T>,
|
||||
): Promise<T> {
|
||||
try {
|
||||
return await callable(context)
|
||||
return await Promise.resolve(callable(context))
|
||||
} catch (error) {
|
||||
if (isFallbackableError(error) && context.currentLanguage !== 'en') {
|
||||
const enContext = Object.assign({}, context, { currentLanguage: 'en' })
|
||||
const fallbackContent = await fallback(enContext)
|
||||
const fallbackContent = await Promise.resolve(fallback(enContext))
|
||||
|
||||
// Add HTML comment with error details for non-English languages
|
||||
// Only for HTML content (detected by presence of HTML tags)
|
||||
if (typeof fallbackContent === 'string' && /<[^>]+>/.test(fallbackContent)) {
|
||||
const errorComment = createTranslationFallbackComment(error, 'content')
|
||||
return errorComment + '\n' + fallbackContent
|
||||
const errorComment = createTranslationFallbackComment(error as Error, 'content')
|
||||
return (errorComment + '\n' + fallbackContent) as T
|
||||
}
|
||||
|
||||
return fallbackContent
|
||||
Reference in New Issue
Block a user