diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 021cf63593e5..4cbf33904ee6 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -19,7 +19,8 @@ // Set *default* container specific settings.json values on container create. "settings": { "terminal.integrated.shell.linux": "/bin/bash", - "cSpell.language": ",en" + "cSpell.language": ",en", + "git.autofetch": true }, // Visual Studio Code extensions which help authoring for docs.github.com. "extensions": [ @@ -57,7 +58,7 @@ }, // Use 'postCreateCommand' to run commands after the container is created. - "postCreateCommand": "npm ci", + "postCreateCommand": "npm ci && npm start", // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. "remoteUser": "node", diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f55b6cdde90c..56f191de0e62 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,4 +1,10 @@ version: 2 +registries: + ghcr: # Define access for a private registry + type: docker-registry + url: ghcr.io + username: PAT + password: ${{secrets.CONTAINER_BUILDER_TOKEN}} updates: - package-ecosystem: npm directory: '/' @@ -23,11 +29,18 @@ updates: - dependency-name: '*' update-types: ['version-update:semver-patch', 'version-update:semver-minor'] + - dependency-name: 'github/internal-actions' - package-ecosystem: 'docker' + registries: + - ghcr directory: '/' schedule: interval: weekly day: thursday + groups: + baseImages: + patterns: + - '*' ignore: - dependency-name: 'node' diff --git a/.github/workflows/moda-ci.yaml b/.github/workflows/moda-ci.yaml new file mode 100644 index 000000000000..0545be426c12 --- /dev/null +++ b/.github/workflows/moda-ci.yaml @@ -0,0 +1,65 @@ +name: docs-internal Moda CI + +# More info on CI actions setup can be found here: +# https://github.com/github/ops/blob/master/docs/playbooks/build-systems/moving-moda-apps-from-bp-to-actions.md + +on: + workflow_dispatch: + push: + branches-ignore: + - 'gh-readonly-queue/**' + merge_group: + types: [checks_requested] + +jobs: + moda-config-bundle: + if: ${{ github.repository == 'github/docs-internal' }} + name: ${{ matrix.ci_job.job }} + strategy: + fail-fast: false + matrix: + ci_job: [{ 'job': 'docs-internal-moda-config-bundle' }] + uses: github/internal-actions/.github/workflows/moda.yml@main + with: + ci-formatted-job-name: ${{ matrix.ci_job.job }} + vault-keys: ${{ vars.VAULT_KEYS }} + secrets: + dx-bot-token: ${{ secrets.INTERNAL_ACTIONS_DX_BOT_ACCOUNT_TOKEN }} + datadog-api-key: ${{ secrets.DATADOG_API_KEY }} + + docker-image: + if: ${{ github.repository == 'github/docs-internal' }} + name: ${{ matrix.ci_job.job }} + strategy: + fail-fast: false + matrix: + ci_job: [{ 'job': 'docs-internal-docker-image' }] + uses: github/internal-actions/.github/workflows/kube.yml@main + with: + ci-formatted-job-name: ${{ matrix.ci_job.job }} + vault-keys: ${{ vars.VAULT_KEYS }} + secrets: + dx-bot-token: ${{ secrets.INTERNAL_ACTIONS_DX_BOT_ACCOUNT_TOKEN }} + datadog-api-key: ${{ secrets.DATADOG_API_KEY }} + + docker-security: + if: ${{ github.repository == 'github/docs-internal' }} + name: ${{ matrix.ci_job.job }} + strategy: + fail-fast: false + matrix: + ci_job: [{ 'job': 'docs-internal-docker-security' }] + uses: github/internal-actions/.github/workflows/docker_security.yml@main + with: + ci-formatted-job-name: ${{ matrix.ci_job.job }} + vault-keys: ${{ vars.VAULT_KEYS }} + secrets: + dx-bot-token: ${{ secrets.INTERNAL_ACTIONS_DX_BOT_ACCOUNT_TOKEN }} + datadog-api-key: ${{ secrets.DATADOG_API_KEY }} + +permissions: + actions: read + checks: read + contents: read + statuses: read + id-token: write diff --git a/Dockerfile b/Dockerfile index dd9033bb3752..eadf79b32d54 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,6 +10,9 @@ FROM node:22-alpine@sha256:c13b26e7e602ef2f1074aef304ce6e9b7dd284c419b35d89fcf3c # This directory is owned by the node user ARG APP_HOME=/home/node/app +# Make sure there's a translations directory available to not error the COPY command +RUN mkdir -p translations && chown -R node:node translations + # Make sure we don't run anything as the root user USER node @@ -109,4 +112,4 @@ FROM preview AS production ENV ENABLED_LANGUAGES "en,zh,es,pt,ru,ja,fr,de,ko" # Copy in all translations -COPY --chown=node:node translations ./translations +COPY --chown=node:node --from=base translations ./translations diff --git a/assets/images/help/issues/issue-type-edit.png b/assets/images/help/issues/issue-type-edit.png index 2d661df0896b..04e53e2b6543 100644 Binary files a/assets/images/help/issues/issue-type-edit.png and b/assets/images/help/issues/issue-type-edit.png differ diff --git a/config/kubernetes/production/deployments/webapp.yaml b/config/kubernetes/production/deployments/webapp.yaml new file mode 100644 index 000000000000..fba6734ca36d --- /dev/null +++ b/config/kubernetes/production/deployments/webapp.yaml @@ -0,0 +1,53 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: webapp +spec: + replicas: 2 + selector: + matchLabels: + app: webapp + template: + metadata: + labels: + app: webapp + annotations: + # If you emit structured logs, you can specify a parser to use so your logs are parsed + # properly and are much nicer to query in splunk. For more details, see + # https://thehub.github.com/engineering/development-and-ops/observability/logging/fluent-bit/ + # fluentbit.io/parser: logfmt + spec: + dnsPolicy: Default + containers: + - name: webapp + image: docs-internal + resources: + requests: + cpu: 4000m + memory: 5Gi + limits: + cpu: 4000m + memory: 14Gi + ports: + - name: http + containerPort: 4000 + protocol: TCP + envFrom: + - secretRef: + name: vault-secrets + - configMapRef: + name: kube-cluster-metadata + # Zero-downtime deploys + # https://thehub.github.com/engineering/products-and-services/internal/moda/feature-documentation/pod-lifecycle/#required-prestop-hook + # https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + lifecycle: + preStop: + exec: + command: ['sleep', '5'] + readinessProbe: + initialDelaySeconds: 5 + httpGet: + # WARNING: This should be updated to a meaningful endpoint for your application which will return a 200 once the app is fully started. + # See: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-readiness-probes + path: /healthz + port: http diff --git a/config/kubernetes/production/services/webapp.yaml b/config/kubernetes/production/services/webapp.yaml new file mode 100644 index 000000000000..4c96ca5be8b5 --- /dev/null +++ b/config/kubernetes/production/services/webapp.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Service +metadata: + name: webapp + labels: + service: webapp + annotations: + moda.github.net/domain-name: 'docs-internal.github.com' + moda.github.net/dns-registration-enabled: 'false' + moda.github.net/load-balancer-type: + public-external-http + # moda.github.net/allowed-ips: '23.235.32.0/20,43.249.72.0/22,103.244.50.0/24,103.245.222.0/23,103.245.224.0/24,104.156.80.0/20,140.248.64.0/18,140.248.128.0/17,146.75.0.0/17,151.101.0.0/16,157.52.64.0/18,167.82.0.0/17,167.82.128.0/20,167.82.160.0/20,167.82.224.0/20,172.111.64.0/18,185.31.16.0/22,199.27.72.0/21,199.232.0.0/1' + # ipv6 addresses not included + # curl -i "https://api.fastly.com/public-ip-list" +spec: + ports: + - name: http + port: 4000 + protocol: TCP + targetPort: http + selector: + app: webapp + type: LoadBalancer diff --git a/config/moda/deployment.yaml b/config/moda/deployment.yaml new file mode 100644 index 000000000000..a8edafe09980 --- /dev/null +++ b/config/moda/deployment.yaml @@ -0,0 +1,13 @@ +required_builds: + - docs-internal-moda-config-bundle / docs-internal-moda-config-bundle + - docs-internal-docker-image / docs-internal-docker-image + - docs-internal-docker-security / docs-internal-docker-security +environments: + - name: production + auto_deploy: true + cluster_selector: + profile: general + region: iad +notifications: + slack_channels: + - '#docs-ops' diff --git a/content/issues/planning-and-tracking-with-projects/customizing-views-in-your-project/filtering-projects.md b/content/issues/planning-and-tracking-with-projects/customizing-views-in-your-project/filtering-projects.md index 71d79e160ab8..49e2c3fda500 100644 --- a/content/issues/planning-and-tracking-with-projects/customizing-views-in-your-project/filtering-projects.md +++ b/content/issues/planning-and-tracking-with-projects/customizing-views-in-your-project/filtering-projects.md @@ -77,6 +77,16 @@ You can invert any filter, including combinations, by prefixing with a hyphen. |-field:VALUE | **-status:done** will not show any items with a status of "done." |-field:VALUE,VALUE | **-priority:1,2** will not show any items with a priority of either 1 or 2. +## Filtering for items that have a value + +You can use `has:` to filter for items that have a value + +| Qualifier | Example +| ---------- | ------------- +|has:assignee | **has:assignee** will show items with an assignee. +|has:label | **has:label** will show items with a label. +|has:FIELD | **has:priority** will show items with a priority field value. + ## Filtering for items that are missing a value You can use `no:` to filter for items that are missing a value diff --git a/content/issues/tracking-your-work-with-issues/configuring-issues/managing-issue-types-in-an-organization.md b/content/issues/tracking-your-work-with-issues/configuring-issues/managing-issue-types-in-an-organization.md index 4ac78256c421..170c67ef047b 100644 --- a/content/issues/tracking-your-work-with-issues/configuring-issues/managing-issue-types-in-an-organization.md +++ b/content/issues/tracking-your-work-with-issues/configuring-issues/managing-issue-types-in-an-organization.md @@ -12,7 +12,7 @@ permissions: 'Organization owners can modify issue types.' {% data reusables.issues.release-stage %} -You can use issue types to classify and manage different types of issues across your organization. You can create up to ten issue types that your organization members can apply to issues, making it easier for you and your members to find issues and plan work. +You can use issue types to classify and manage different types of issues across your organization. You can create up to {% data variables.projects.issue_type_limit %} issue types that your organization members can apply to issues, making it easier for you and your members to find issues and plan work. Default issue types are included in every organization, but these can edited, disabled, or deleted. The default types are task, bug, and feature. diff --git a/content/issues/tracking-your-work-with-issues/using-issues/adding-sub-issues.md b/content/issues/tracking-your-work-with-issues/using-issues/adding-sub-issues.md index 10a492f7703a..c9954ff3b142 100644 --- a/content/issues/tracking-your-work-with-issues/using-issues/adding-sub-issues.md +++ b/content/issues/tracking-your-work-with-issues/using-issues/adding-sub-issues.md @@ -24,7 +24,7 @@ You can add sub-issues to an issue to break down larger pieces of work into task Your sub-issues can themselves contain sub-issues, allowing you to create full hierarchies of issues that visualize entire projects or pieces of work and show the relationships between your issues. -You can add up to fifty sub-issues per parent issue and create up to eight levels of nested sub-issues. +You can add up to {% data variables.projects.sub-issue_limit %} sub-issues per parent issue and create up to eight levels of nested sub-issues. ## Creating a sub-issue diff --git a/data/variables/projects.yml b/data/variables/projects.yml index 69e43d04d6c5..7b533b851aba 100644 --- a/data/variables/projects.yml +++ b/data/variables/projects.yml @@ -22,5 +22,7 @@ projects_v2_and_v1_if_create: '{% data variables.projects.projects_v2 %}{% ifver # Limits item_limit: '1,200' archived_item_limit: '10,000' +issue_type_limit: '25' +sub-issue_limit: '100' tasklists: 'tasklists (beta)' diff --git a/ownership.yaml b/ownership.yaml new file mode 100644 index 000000000000..fd23b50c4c67 --- /dev/null +++ b/ownership.yaml @@ -0,0 +1,22 @@ +--- +version: 1 +ownership: + - team: github/docs-engineering + repo: https://github.com/github/docs-internal + name: docs-internal + kind: moda + long_name: Docs on Moda + description: Please use instead. + exec_sponsor: nerdneha + product_manager: docs-bot + qos: best_effort + tier: 2 + sev1: + pagerduty: https://github.pagerduty.com/escalation_policies#PN57VQ1 + tta: 30m + sev2: + issue: https://github.com/github/docs-engineering/issues + tta: 1d + sev3: + issue: https://github.com/github/docs-engineering/issues + tta: 1w diff --git a/src/workflows/tests/actions-workflows.ts b/src/workflows/tests/actions-workflows.ts index 6f2a231dfbda..df1461e96fea 100644 --- a/src/workflows/tests/actions-workflows.ts +++ b/src/workflows/tests/actions-workflows.ts @@ -27,6 +27,7 @@ const workflowsDir = path.join(__dirname, '../../../.github/workflows') const workflows: WorkflowMeta[] = fs .readdirSync(workflowsDir) .filter((filename) => filename.endsWith('.yml') || filename.endsWith('.yaml')) + .filter((filename) => filename !== 'moda-ci.yaml') // Skip moda-ci .map((filename) => { const fullpath = path.join(workflowsDir, filename) const data = yaml.load(fs.readFileSync(fullpath, 'utf8')) as WorkflowMeta['data']