Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Repo sync #33699

Merged
merged 6 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ The following operating systems are supported for the self-hosted runner applica
The following processor architectures are supported for the self-hosted runner application.

* `x64` - Linux, macOS, Windows.
* `ARM64` - Linux{% ifversion actions-macos-arm %}, macOS{% endif %}{% ifversion actions-windows-arm %}, Windows (currently in beta){% endif %}.
* `ARM64` - Linux, macOS{% ifversion actions-windows-arm %}, Windows (currently in beta){% endif %}.
* `ARM32` - Linux.

{% ifversion ghes %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ The following table shows the permissions granted to the `GITHUB_TOKEN` by defau
| checks | read/write | none | read |
| contents | read/write | read | read |
| deployments | read/write | none | read |
| discussions | read/write | none | read |
| {% ifversion fpt or ghec %} |
| id-token | none | none | read |
| {% endif %} |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -813,8 +813,6 @@ This example demonstrates how to set the `SELECTED_COLOR` output parameter and l

{% endpowershell %}

{% ifversion actions-job-summaries %}

## Adding a job summary

{% bash %}
Expand Down Expand Up @@ -955,8 +953,6 @@ After a step has completed, job summaries are uploaded and subsequent steps cann

Job summaries are isolated between steps and each step is restricted to a maximum size of 1MiB. Isolation is enforced between steps so that potentially malformed Markdown from a single step cannot break Markdown rendering for subsequent steps. If more than 1MiB of content is added for a step, then the upload for the step will fail and an error annotation will be created. Upload failures for job summaries do not affect the overall status of a step or a job. A maximum of 20 job summaries from steps are displayed per job.

{% endif %}

## Adding a system path

Prepends a directory to the system `PATH` variable and automatically makes it available to all subsequent actions in the current job; the currently running action cannot access the updated path variable. To see the currently defined paths for your job, you can use `echo "$PATH"` in a step or an action.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
title: Adding items automatically
intro: 'You can configure your project''s built-in workflows to automatically add items from {% ifversion projects-v2-duplicate-auto-add %}repositories{% else%}a repository{% endif %} that match a filter.'
versions:
feature: projects-v2-auto-add
fpt: '*'
ghes: '*'
ghec: '*'
type: tutorial
topics:
- Projects
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ title: Archiving items automatically
shortTitle: Archiving items automatically
intro: You can configure your project's built-in workflows to automatically archive items that match a filter.
versions:
feature: projects-v2-auto-archive
fpt: '*'
ghes: '*'
ghec: '*'
type: tutorial
topics:
- Projects
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ To learn more about the different fields you can add to a project, see "[AUTOTIT

### Automating your projects

There are a number of ways you can add automation to your project. Built-in workflows allow you to automatically set fields when items are added or changed{% ifversion projects-v2-auto-archive %}, and you can also configure your project to automatically archive items when they meet certain criteria{% ifversion projects-v2-auto-add %} and automatically add items from a repository when they match set criteria{% endif %}{% endif %}. For more information, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/using-the-built-in-automations)."
There are a number of ways you can add automation to your project. Built-in workflows allow you to automatically set fields when items are added or changed, and you can also configure your project to automatically archive items when they meet certain criteria and automatically add items from a repository when they match set criteria. For more information, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/using-the-built-in-automations)."

You can also use the GraphQL API and {% data variables.product.prodname_actions %} to take even greater control of your project. For more information, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/using-the-api-to-manage-projects)" and "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/automating-projects-using-actions)."

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ To prevent information from getting out of sync, maintain a single source of tru

You can automate tasks to spend less time on busy work and more time on the project itself. The less you need to remember to do manually, the more likely your project will stay up to date.

{% data variables.product.prodname_projects_v2 %} offers built-in workflows. For example, when an issue is closed, you can automatically set the status to "Done." {% ifversion projects-v2-auto-archive %}You can also configure built-in workflows to automatically archive items when they meet certain criteria{% ifversion projects-v2-auto-add %} and to automatically add items from a repository when they match a filter{% endif %}.{% endif %}
{% data variables.product.prodname_projects_v2 %} offers built-in workflows. For example, when an issue is closed, you can automatically set the status to "Done". You can also configure built-in workflows to automatically archive items when they meet certain criteria and to automatically add items from a repository when they match a filter.

Additionally, {% data variables.product.prodname_actions %} and the GraphQL API enable you to automate routine project management tasks. For example, to keep track of pull requests awaiting review, you can create a workflow that adds a pull request to a project and sets the status to "needs review"; this process can be automatically triggered when a pull request is marked as "ready for review."

* For more information about the built-in workflows, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/using-the-built-in-automations)."{% ifversion projects-v2-auto-archive %}
* For more information about automatically archiving items, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/archiving-items-automatically)."{% endif %}{% ifversion projects-v2-auto-add %}
* For more information about automatically adding items, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/adding-items-automatically)."{% endif %}
* For more information about the built-in workflows, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/using-the-built-in-automations)."
* For more information about automatically archiving items, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/archiving-items-automatically)."
* For more information about automatically adding items, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/adding-items-automatically)."
* For an example workflow, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/automating-projects-using-actions)."
* For more information about the API, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/using-the-api-to-manage-projects)."
* For more information about {% data variables.product.prodname_actions %}, see "[AUTOTITLE](/actions)."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,6 @@ To indicate the purpose of the view, give it a descriptive name.

## Configure built-in automation

{% ifversion projects-v2-auto-add %}

Next, configure the auto-add workflow to automatically add issues opened in a repository with a specific label to your project.

{% data reusables.projects.access-workflows %}
Expand All @@ -141,8 +139,6 @@ Next, configure the auto-add workflow to automatically add issues opened in a re
1. Next to the repository selection, type the filter criteria you want items to match before they are automatically added to your project. For example, to catch all issues and PRs opened with the label "bug", use `is:issue,pr label:bug`.
1. To enable the new workflow, click **Save and turn on workflow**.

{% endif %}

Finally, add a built in workflow to set the status to **Todo** when an item is added to your project.

1. In the top-right, click {% octicon "kebab-horizontal" aria-label="The menu icon" %} to open the menu.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ allowTitleToDifferFromFilename: true

{% note %}

**Note:** A project can contain a maximum of {% data variables.projects.item_limit %} items and {% data variables.projects.archived_item_limit %} archived items. {% ifversion projects-v2-auto-archive %}To learn more about automatically archiving items when they meet specific criteria, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/archiving-items-automatically)."{% endif %}
**Note:** A project can contain a maximum of {% data variables.projects.item_limit %} items and {% data variables.projects.archived_item_limit %} archived items. To learn more about automatically archiving items when they meet specific criteria, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/archiving-items-automatically)."

{% endnote %}

## Adding issues and pull requests to a project

You have several options for adding issues and pull requests to your project. You can add them individually{% ifversion projects-v2-auto-add %}, automatically, {% endif %} or in bulk. Furthermore, you can include issues and pull requests from any organization, and you also have the ability to add draft issues that can be converted into regular issues later on. For more information, see "[Creating draft issues](#creating-draft-issues)."
You have several options for adding issues and pull requests to your project. You can add them individually, automatically, or in bulk. Furthermore, you can include issues and pull requests from any organization, and you also have the ability to add draft issues that can be converted into regular issues later on. For more information, see "[Creating draft issues](#creating-draft-issues)."

{% ifversion projects-v2-timeline-events %}

Expand All @@ -38,14 +38,10 @@ For more information about making bulk changes to your items after adding them,

{% endif %}

{% ifversion projects-v2-auto-add %}

### Automatically adding issues and pull requests

You can configure a built-in workflow to automatically add issues and pull requests from a repository when they meet specific filter criteria. For more information about configuring a workflow, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/adding-items-automatically)."

{% endif %}

### Pasting the URL of an issue or pull request

You can copy the URL of an issue or pull request into your clipboard and paste that into your project.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ allowTitleToDifferFromFilename: true

## Archiving items

You can archive an item to keep the context about the item in the project but remove it from the project views. {% ifversion projects-v2-auto-archive %}You can also configure your project's built-in workflows to automatically archive items that meet certain criteria. For more information, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/archiving-items-automatically)."{% endif %}
You can archive an item to keep the context about the item in the project but remove it from the project views. You can also configure your project's built-in workflows to automatically archive items that meet certain criteria. For more information, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/automating-your-project/archiving-items-automatically)."

{% data reusables.projects.select-an-item %}
{% data reusables.projects.open-item-menu %}
Expand All @@ -31,7 +31,7 @@ You can archive an item to keep the context about the item in the project but re
1. In the top-right, click {% octicon "kebab-horizontal" aria-label="More options" %}.

![Screenshot showing a project's menu bar. The menu icon is highlighted with an orange outline.](/assets/images/help/projects-v2/open-menu.png)

1. In the menu, click {% octicon "archive" aria-hidden="true" %} **Archived items**.
1. Optionally, to filter the archived items displayed, type your filter into the text box above the list of items. For more information about the available filters, see "[AUTOTITLE](/issues/planning-and-tracking-with-projects/customizing-views-in-your-project/filtering-projects)."
1. To the left of each item title, select the items you would like to restore.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { getProductGroups } from '#src/products/lib/get-product-groups.js'
import warmServer from '#src/frame/lib/warm-server.js'
import { languageKeys } from '#src/languages/lib/languages.js'
import { allVersionKeys } from '#src/versions/lib/all-versions.js'
import type { Response, NextFunction } from 'express'

const isHomepage = (path) => {
import type { ExtendedRequest } from '@/types'
import { getProductGroups } from '@/products/lib/get-product-groups'
import warmServer from '@/frame/lib/warm-server.js'
import { languageKeys } from '@/languages/lib/languages.js'
import { allVersionKeys } from '@/versions/lib/all-versions.js'

const isHomepage = (path: string) => {
const split = path.split('/')
// E.g. `/foo` but not `foo/bar` or `foo/`
if (split.length === 2 && split[1] && !split[0]) {
Expand All @@ -17,7 +20,14 @@ const isHomepage = (path) => {
return false
}

export default async function productGroups(req, res, next) {
export default async function productGroups(
req: ExtendedRequest,
res: Response,
next: NextFunction,
) {
if (!req.context) throw new Error('request is not contextualized')
if (!req.pagePath) throw new Error('pagePath is not set on request')
if (!req.language) throw new Error('language is not set on request')
// It's important to use `req.pathPage` instead of `req.path` because
// the request could be the client-side routing from Next where the URL
// might be something like `/_next/data/foo/bar.json` which is translated,
Expand All @@ -31,7 +41,7 @@ export default async function productGroups(req, res, next) {
// known versions. Because if it's not valid, any possible
// use of `{% ifversion ... %}` in Liquid, will throw an error.
if (isHomepage(req.pagePath) && req.context.currentVersionObj) {
const { pages } = await warmServer()
const { pages } = await warmServer([])
req.context.productGroups = await getProductGroups(pages, req.language, req.context)
}

Expand Down
2 changes: 1 addition & 1 deletion src/frame/middleware/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import glossaries from './context/glossaries'
import renderProductName from './context/render-product-name'
import features from '@/versions/middleware/features.js'
import productExamples from './context/product-examples'
import productGroups from './context/product-groups.js'
import productGroups from './context/product-groups'
import featuredLinks from '@/landings/middleware/featured-links.js'
import learningTrack from '@/learning-track/middleware/learning-track.js'
import next from './next.js'
Expand Down
4 changes: 2 additions & 2 deletions src/products/lib/all-products.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Product } from '@/types'
import type { PageFrontmatter, Product } from '@/types'

export const { data }: Record<string, any>
export const data: PageFrontmatter

export const productIds: string[]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import path from 'path'

import type { Page, ProductGroup, ProductGroupChild, Context } from '@/types'
import { productMap, data } from './all-products.js'
import { renderContentWithFallback } from '#src/languages/lib/render-with-fallback.js'
import removeFPTFromPath from '#src/versions/lib/remove-fpt-from-path.js'
import { renderContentWithFallback } from '@/languages/lib/render-with-fallback.js'
import removeFPTFromPath from '@/versions/lib/remove-fpt-from-path.js'

async function getPage(id, lang, pageMap, context) {
type PageMap = Record<string, Page>

async function getPage(
id: string,
lang: string,
pageMap: PageMap,
context: Context,
): Promise<ProductGroupChild | undefined> {
const productId = id.split('/')[0]
const product = productMap[productId]

const external = product.external || false // undefined becomes false

// The href depends. Initially all we have is an `id` which might be
Expand All @@ -26,6 +35,8 @@ async function getPage(id, lang, pageMap, context) {

let name = product.name

if (!context.currentVersion) throw new Error('context.currentVersion is not set')

if (!external) {
// First we have to find it as a page object based on its ID.
href = removeFPTFromPath(path.posix.join('/', lang, context.currentVersion, id))
Expand All @@ -34,6 +45,7 @@ async function getPage(id, lang, pageMap, context) {
// fall back it its default version, which is `product.versions[0]`.
// For example, you're on `/en/[email protected]` and you're
// but a `/foo/bar` is only available in `enterprise-cloud@latest`.
if (!product.versions) throw new Error(`Product ${productId} has no versions`)
href = removeFPTFromPath(path.posix.join('/', lang, product.versions[0], id))
}
const page = pageMap[href]
Expand Down Expand Up @@ -74,17 +86,21 @@ async function getPage(id, lang, pageMap, context) {
}
}

export async function getProductGroups(pageMap, lang, context) {
export async function getProductGroups(
pageMap: PageMap,
lang: string,
context: Context,
): Promise<ProductGroup[]> {
return await Promise.all(
data.childGroups.map(async (group) => {
data.childGroups!.map(async (group) => {
return {
name: group.name,
icon: group.icon || null,
octicon: group.octicon || null,
// Typically the children are product IDs, but we support deeper page paths too
children: (
await Promise.all(group.children.map((id) => getPage(id, lang, pageMap, context)))
).filter(Boolean),
).filter(Boolean) as ProductGroupChild[],
}
}),
)
Expand Down
76 changes: 76 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,66 @@ export type ExtendedRequest = Request & {
// Add more properties here as needed
}

// TODO: Make this type from inference using AJV based on the schema.
// For now, it's based on `schema` in frame/lib/frontmatter.js
export type PageFrontmatter = {
title: string
versions: FrontmatterVersions
shortTitle?: string
intro?: string
product?: string
permissions?: string
showMiniToc?: boolean
miniTocMaxHeadingLevel?: number
mapTopic?: boolean
hidden?: boolean
noEarlyAccessBanner?: boolean
earlyAccessToc?: string
layout?: string | boolean
redirect_from?: string[]
allowTitleToDifferFromFilename?: boolean
introLinks?: object
authors?: string[]
examples_source?: string
effectiveDate?: string

featuredLinks?: {
gettingStarted?: string[]
startHere?: string[]
guideCards?: string[]
popular?: string[]
popularHeading?: string
videos?: {
title: string
href: string
}[]
videoHeadings?: string
}[]
changelog?: ChangeLog
type?: string
topics?: string[]
includeGuides?: string[]
learningTracks?: string[]
beta_product?: boolean
product_video?: boolean
product_video_transcript?: string
interactive?: boolean
communityRedirect?: {
name: string
href: string
}
defaultPlatform?: 'mac' | 'windows' | 'linux'
defaultTool?: string
childGroups?: ChildGroup[]
}

export type ChildGroup = {
name: string
octicon: string
children: string[]
icon?: string
}

export type Product = {
id: string
name: string
Expand All @@ -23,6 +83,7 @@ export type Product = {
wip?: boolean
hidden?: boolean
versions?: string[]
external?: boolean
}

type ProductMap = {
Expand Down Expand Up @@ -95,6 +156,21 @@ export type Context = {
currentProductName?: string
productCommunityExamples?: ProductExample[]
productUserExamples?: ProductExample[]
productGroups?: ProductGroup[]
}

export type ProductGroup = {
name: string
icon: string | null
octicon: string | null
children: ProductGroupChild[]
}

export type ProductGroupChild = {
id: string
name: string
href: string
external: boolean
}

export type Glossary = {
Expand Down
Loading