diff --git a/.github/actions-scripts/fr-add-docs-reviewers-requests.js b/.github/actions-scripts/fr-add-docs-reviewers-requests.js index 18de154302..86bc34ddea 100644 --- a/.github/actions-scripts/fr-add-docs-reviewers-requests.js +++ b/.github/actions-scripts/fr-add-docs-reviewers-requests.js @@ -119,6 +119,7 @@ async function run() { const statusID = findFieldID('Status', data) const featureID = findFieldID('Feature', data) const contributorTypeID = findFieldID('Contributor type', data) + const sizeTypeID = findFieldID('Size', data) const authorID = findFieldID('Author', data) // Get the ID of the single select values that we want to set @@ -169,6 +170,8 @@ async function run() { reviewDueDateID: reviewDueDateID, contributorTypeID: contributorTypeID, contributorType: contributorType, + sizeTypeID: sizeTypeID, + sizeType: '', // Although we aren't populating size, we are passing the variable so that we can use the shared mutation function featureID: featureID, authorID: authorID, headers: { diff --git a/.github/actions-scripts/projects.js b/.github/actions-scripts/projects.js index 8c96c6f8c6..7bba91e246 100644 --- a/.github/actions-scripts/projects.js +++ b/.github/actions-scripts/projects.js @@ -186,6 +186,8 @@ export function generateUpdateProjectNextItemFieldMutation({ $reviewDueDateID: ID! $contributorTypeID: ID! $contributorType: String! + $sizeTypeID: ID! + $sizeType: String! $featureID: ID! $authorID: ID! ) { @@ -211,6 +213,11 @@ export function generateUpdateProjectNextItemFieldMutation({ fieldID: '$contributorTypeID', value: '$contributorType', })} + ${generateMutationToUpdateField({ + item: item, + fieldID: '$sizeTypeID', + value: '$sizeType', + })} ${generateMutationToUpdateField({ item: item, fieldID: '$featureID', diff --git a/.github/actions-scripts/ready-for-docs-review.js b/.github/actions-scripts/ready-for-docs-review.js index a411ca9fe3..b64a3c77b3 100644 --- a/.github/actions-scripts/ready-for-docs-review.js +++ b/.github/actions-scripts/ready-for-docs-review.js @@ -12,7 +12,7 @@ async function run() { // Get info about the docs-content review board project const data = await graphql( ` - query ($organization: String!, $projectNumber: Int!) { + query ($organization: String!, $projectNumber: Int!, $id: ID!) { organization(login: $organization) { projectNext(number: $projectNumber) { id @@ -25,9 +25,22 @@ async function run() { } } } + item: node(id: $id) { + __typename + ... on PullRequest { + files(first: 100) { + nodes { + additions + deletions + path + } + } + } + } } `, { + id: process.env.ITEM_NODE_ID, organization: process.env.ORGANIZATION, projectNumber: parseInt(process.env.PROJECT_NUMBER), headers: { @@ -46,6 +59,7 @@ async function run() { const statusID = findFieldID('Status', data) const featureID = findFieldID('Feature', data) const contributorTypeID = findFieldID('Contributor type', data) + const sizeTypeID = findFieldID('Size', data) const authorID = findFieldID('Author', data) // Get the ID of the single select values that we want to set @@ -53,22 +67,115 @@ async function run() { const hubberTypeID = findSingleSelectID('Hubber or partner', 'Contributor type', data) const docsMemberTypeID = findSingleSelectID('Docs team', 'Contributor type', data) const osContributorTypeID = findSingleSelectID('OS contributor', 'Contributor type', data) + const sizeXS = findSingleSelectID('XS', 'Size', data) + const sizeS = findSingleSelectID('S', 'Size', data) + const sizeM = findSingleSelectID('M', 'Size', data) + const sizeL = findSingleSelectID('L', 'Size', data) // Add the PR to the project - const newItemID = await addItemToProject(process.env.PR_NODE_ID, projectID) + const newItemID = await addItemToProject(process.env.ITEM_NODE_ID, projectID) + // If the item is a PR, determine the feature and size + let feature = '' + let sizeType = '' // You don't need to use a field ID if you want the value to be empty + if (data.item.__typename === 'PullRequest') { + // Get the + // - number of files changed + // - total number of additions/deletions + // - affected docs sets (not considering changes to data/assets) + let numFiles = 0 + let numChanges = 0 + let features = new Set([]) + const files = data.item.files.nodes.forEach((node) => { + numFiles += 1 + numChanges += node.additions + numChanges += node.deletions + // To determine the feature, we are only looking at `content/*` paths + // and then pulling out the second part of the path, which corresponds to the docs set + const pathComponents = node.path.split('/') + if (pathComponents[0] === 'content') { + features.add(pathComponents[1]) + } + }) + + // Determine the size + if (numFiles < 5 && numChanges < 25) { + sizeType = sizeXS + } else if (numFiles < 5 && numChanges < 25) { + sizeType = sizeS + } else if (numFiles < 5 && numChanges < 25) { + sizeType = sizeM + } else { + sizeType = sizeL + } + + // Set the feature + feature = Array.from(features).join() + } + + // If this is the OS repo, determine if this is a first time contributor + // If yes, set the author to 'first time contributor' instead of to the author login + let firstTimeContributor + if (process.env.REPO === 'github/docs') { + const contributorData = await graphql( + ` + query ($author: String!) { + user(login: $author) { + contributionsCollection { + pullRequestContributionsByRepository { + contributions { + totalCount + } + repository { + nameWithOwner + } + } + issueContributionsByRepository { + contributions { + totalCount + } + repository { + nameWithOwner + } + } + } + } + } + `, + { + author: process.env.AUTHOR_LOGIN, + headers: { + authorization: `token ${process.env.TOKEN}`, + }, + } + ) + const prCount = + contributorData.user.contributionsCollection.pullRequestContributionsByRepository.filter( + (item) => item.repository.nameWithOwner === 'github/docs' + )[0].contributions.totalCount + const issueCount = + contributorData.user.contributionsCollection.issueContributionsByRepository.filter( + (item) => item.repository.nameWithOwner === 'github/docs' + )[0].contributions.totalCount + + if (prCount + issueCount <= 1) { + firstTimeContributor = true + } + } + const turnaround = process.env.REPO === 'github/docs' ? 3 : 2 // Generate a mutation to populate fields for the new project item const updateProjectNextItemMutation = generateUpdateProjectNextItemFieldMutation({ item: newItemID, - author: process.env.AUTHOR_LOGIN, - turnaround: 2, + author: firstTimeContributor ? 'first time contributor' : process.env.AUTHOR_LOGIN, + turnaround: turnaround, + feature: feature, }) // Determine which variable to use for the contributor type let contributorType if (await isDocsTeamMember(process.env.AUTHOR_LOGIN)) { contributorType = docsMemberTypeID - } else if (process.env.PR_REPO === 'github/docs') { + } else if (process.env.REPO === 'github/docs') { contributorType = osContributorTypeID } else { contributorType = hubberTypeID @@ -84,6 +191,8 @@ async function run() { reviewDueDateID: reviewDueDateID, contributorTypeID: contributorTypeID, contributorType: contributorType, + sizeTypeID: sizeTypeID, + sizeType: sizeType, featureID: featureID, authorID: authorID, headers: { diff --git a/.github/workflows/os-ready-for-review.yml b/.github/workflows/os-ready-for-review.yml new file mode 100644 index 0000000000..02cc40ff19 --- /dev/null +++ b/.github/workflows/os-ready-for-review.yml @@ -0,0 +1,68 @@ +name: OS Ready for review + +# **What it does**: Adds pull requests and issues in the docs repository to the docs-content review board when the "waiting for review" label is added +# **Why we have it**: So that contributors in the OS repo can easily get reviews from the docs-content team, and so that writers can see when a PR is ready for review +# **Who does it impact**: Writers working in the docs repository +permissions: + contents: read + +on: + pull_request: + types: [labeled] + issues: + types: [labeled] + +jobs: + request_doc_review: + name: Request a review from the docs-content team + if: github.event.label.name == 'waiting for review' && github.repository == 'github/docs' + runs-on: ubuntu-latest + steps: + - name: Exit if not triggered by a docs team member + env: + GITHUB_TOKEN: ${{ secrets.DOCUBOT_READORG_REPO_WORKFLOW_SCOPES }} + run: | + members="$( gh api graphql -f query=' + query { + organization(login: "github") { + team(slug: "docs") { + members { + nodes { + login + } + } + } + } + } + ' --jq '.data.organization.team.members.nodes | [(.[].login)]')" + + isMember=$(echo ${members[@]} | grep -ow $GITHUB_ACTOR | wc -w) + + if [ $isMember -eq 0 ] + then + echo "$GITHUB_ACTOR is not a docs team member. exiting..." + exit 1 + fi + + - name: Check out repo content + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + + - name: Setup Node + uses: actions/setup-node@38d90ce44d5275ad62cc48384b3d8a58c500bb5f + with: + node-version: 16.x + cache: npm + + - name: Install dependencies + run: npm install @octokit/graphql + + - name: Run script + run: | + node .github/actions-scripts/ready-for-docs-review.js + env: + TOKEN: ${{ secrets.DOCS_BOT_FR }} + PROJECT_NUMBER: 2936 + ORGANIZATION: 'github' + ITEM_NODE_ID: ${{ github.event.pull_request.node_id || github.event.issue.node_id }} + AUTHOR_LOGIN: ${{ github.event.pull_request.user.login || github.event.issue.user.login }} + REPO: ${{ github.repository }} diff --git a/.github/workflows/ready-for-doc-review.yml b/.github/workflows/ready-for-doc-review.yml index 8b382b1582..fc4ed7a6ed 100644 --- a/.github/workflows/ready-for-doc-review.yml +++ b/.github/workflows/ready-for-doc-review.yml @@ -33,9 +33,9 @@ jobs: TOKEN: ${{ secrets.DOCS_BOT_FR }} PROJECT_NUMBER: 2936 ORGANIZATION: 'github' - PR_NODE_ID: ${{ github.event.pull_request.node_id }} + ITEM_NODE_ID: ${{ github.event.pull_request.node_id }} AUTHOR_LOGIN: ${{ github.event.pull_request.user.login }} - PR_REPO: ${{ github.event.pull_request.base.repo.full_name }} + REPO: ${{ github.event.pull_request.base.repo.full_name }} # Since the projects API is still in beta, use the old workflow if something fails # so that we don't miss these PRs diff --git a/content/github/setting-up-and-managing-your-enterprise/managing-users-in-your-enterprise/viewing-and-managing-a-users-saml-access-to-your-enterprise.md b/content/github/setting-up-and-managing-your-enterprise/managing-users-in-your-enterprise/viewing-and-managing-a-users-saml-access-to-your-enterprise.md index 5a0979aed5..84e3c40071 100644 --- a/content/github/setting-up-and-managing-your-enterprise/managing-users-in-your-enterprise/viewing-and-managing-a-users-saml-access-to-your-enterprise.md +++ b/content/github/setting-up-and-managing-your-enterprise/managing-users-in-your-enterprise/viewing-and-managing-a-users-saml-access-to-your-enterprise.md @@ -23,16 +23,7 @@ If your enterprise is uses {% data variables.product.prodname_emus %}, your memb {% data reusables.saml.about-linked-identities %} -If your enterprise is uses {% data variables.product.prodname_emus %}, you will not be able to deprovision or remove user accounts from the enterprise on {% data variables.product.product_name %}. Any changes you need to make to your enterprise's {% data variables.product.prodname_managed_users %} should be made through your IdP. - -{% warning %} - -**Warning:** For organizations using SCIM: -- Revoking a linked user identity on {% data variables.product.product_name %} will also remove the SAML and SCIM metadata. As a result, the identity provider will not be able to synchronize or deprovision the linked user identity. -- An admin must revoke a linked identity through the identity provider. -- To revoke a linked identity and link a different account through the identity provider, an admin can remove and re-assign the user to the {% data variables.product.product_name %} application. For more information, see your identity provider's docs. - -{% endwarning %} +If your enterprise uses {% data variables.product.prodname_emus %}, you will not be able to deprovision or remove user accounts from the enterprise on {% data variables.product.product_name %}. Any changes you need to make to your enterprise's {% data variables.product.prodname_managed_users %} should be made through your IdP. {% data reusables.identity-and-permissions.revoking-identity-team-sync %} diff --git a/content/organizations/granting-access-to-your-organization-with-saml-single-sign-on/viewing-and-managing-a-members-saml-access-to-your-organization.md b/content/organizations/granting-access-to-your-organization-with-saml-single-sign-on/viewing-and-managing-a-members-saml-access-to-your-organization.md index 241f12b23d..6fac15b475 100644 --- a/content/organizations/granting-access-to-your-organization-with-saml-single-sign-on/viewing-and-managing-a-members-saml-access-to-your-organization.md +++ b/content/organizations/granting-access-to-your-organization-with-saml-single-sign-on/viewing-and-managing-a-members-saml-access-to-your-organization.md @@ -23,7 +23,19 @@ You can view and revoke each member's linked identity, active sessions, and auth ## Viewing and revoking a linked identity -{% data reusables.saml.about-linked-identities %} +{% data reusables.saml.about-linked-identities %} + +When available, the entry will include SCIM data. For more information, see "[About SCIM](/organizations/managing-saml-single-sign-on-for-your-organization/about-scim)." + +{% warning %} + +**Warning:** For organizations using SCIM: +- Revoking a linked user identity on {% data variables.product.product_name %} will also remove the SAML and SCIM metadata. As a result, the identity provider will not be able to synchronize or deprovision the linked user identity. +- An admin must revoke a linked identity through the identity provider. +- To revoke a linked identity and link a different account through the identity provider, an admin can remove and re-assign the user to the {% data variables.product.product_name %} application. For more information, see your identity provider's documentation. + +{% endwarning %} + {% data reusables.identity-and-permissions.revoking-identity-team-sync %} diff --git a/content/repositories/archiving-a-github-repository/backing-up-a-repository.md b/content/repositories/archiving-a-github-repository/backing-up-a-repository.md index 8346b22105..b20d4b0156 100644 --- a/content/repositories/archiving-a-github-repository/backing-up-a-repository.md +++ b/content/repositories/archiving-a-github-repository/backing-up-a-repository.md @@ -35,7 +35,7 @@ When you clone a repository or wiki, only Git data, such as project files and co - [Projects](/rest/reference/projects#list-repository-projects) {% endif %} -Once you have {% ifversion ghes or ghae %}a local version of all the content you want to back up, you can create a zip archive and {% else %}downloaded your archive, you can {% endif %}copy it to an external hard drive and/or upload it to a cloud-based backup service such as [Google Drive](https://www.google.com/drive/) or [Dropbox](https://www.dropbox.com/). +Once you have {% ifversion ghes or ghae %}a local version of all the content you want to back up, you can create a zip archive and {% else %}downloaded your archive, you can {% endif %}copy it to an external hard drive and/or upload it to a cloud-based backup or storage service such as [Azure Blob Storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-overview/), [Google Drive](https://www.google.com/drive/) or [Dropbox](https://www.dropbox.com/). {% ifversion fpt %} ## Third-party backup tools diff --git a/data/reusables/saml/about-linked-identities.md b/data/reusables/saml/about-linked-identities.md index f879d16402..25747fe629 100644 --- a/data/reusables/saml/about-linked-identities.md +++ b/data/reusables/saml/about-linked-identities.md @@ -1,3 +1,3 @@ -You can view the single sign-on identity that a member has linked to their {% data variables.product.product_name %} account. When available, the entry will include SCIM data. For more information, see "[About SCIM](/organizations/managing-saml-single-sign-on-for-your-organization/about-scim)." +You can view the single sign-on identity that a member has linked to their {% data variables.product.product_name %} account. If a member links the wrong identity to their {% data variables.product.product_name %} account, you can revoke the linked identity to allow the member to try again. diff --git a/data/reusables/secret-scanning/partner-secret-list-private-repo.md b/data/reusables/secret-scanning/partner-secret-list-private-repo.md index 8ebdf6dd03..6c186d7f01 100644 --- a/data/reusables/secret-scanning/partner-secret-list-private-repo.md +++ b/data/reusables/secret-scanning/partner-secret-list-private-repo.md @@ -154,6 +154,14 @@ Mailchimp | Mailchimp API Key | mailchimp_api_key{% endif %} Mailgun | Mailgun API Key | mailgun_api_key{% endif %} {%- ifversion fpt or ghes > 3.1 or ghae-next %} MessageBird | MessageBird API Key | messagebird_api_key{% endif %} +{%- ifversion fpt or ghes > 3.2 or ghae-next %} +New Relic | New Relic Personal API Key | new_relic_personal_api_key{% endif %} +{%- ifversion fpt or ghes > 3.2 or ghae-next %} +New Relic | New Relic REST API Key | new_relic_rest_api_key{% endif %} +{%- ifversion fpt or ghes > 3.2 or ghae-next %} +New Relic | New Relic Insights Query Key | new_relic_insights_query_key{% endif %} +{%- ifversion fpt or ghes > 3.2 or ghae-next %} +New Relic | New Relic License Key | new_relic_license_key{% endif %} {%- ifversion fpt or ghes > 2.22 or ghae-next %} npm | npm Access Token | npm_access_token{% endif %} {%- ifversion fpt or ghes > 2.22 or ghae-next %}