diff --git a/.buildkite/pipeline.deploy.yml b/.buildkite/pipeline.deploy.yml index 44ff7d9637..aeb05f28c6 100644 --- a/.buildkite/pipeline.deploy.yml +++ b/.buildkite/pipeline.deploy.yml @@ -1,3 +1,6 @@ +env: + BUILDKIT_PROGRESS: plain + steps: - name: ":docker::ecr: Push to ECR" command: ".buildkite/push-image.sh" @@ -9,7 +12,7 @@ steps: queue: elastic-runners plugins: - aws-assume-role-with-web-identity#v1.0.0: - role-arn: arn:aws:iam::${ECR_ACCOUNT_ID}:role/pipeline-buildkite-docs-main + role-arn: arn:aws:iam::${ECR_ACCOUNT_ID}:role/pipeline-buildkite-docs-private - ecr#v2.7.0: login: true account-ids: ${ECR_ACCOUNT_ID} @@ -21,7 +24,7 @@ steps: depends_on: "ecr-push" plugins: - aws-assume-role-with-web-identity#v1.0.0: - role-arn: arn:aws:iam::${ECR_ACCOUNT_ID}:role/pipeline-buildkite-docs-main + role-arn: arn:aws:iam::${ECR_ACCOUNT_ID}:role/pipeline-buildkite-docs-private - buildkite/ecr-scan-results#v2.0.0: image-name: "${ECR_REPO}:${BUILDKITE_BUILD_NUMBER}" fail-build-on-plugin-failure: true @@ -52,7 +55,7 @@ steps: command: scripts/deploy-ecs plugins: - aws-assume-role-with-web-identity#v1.0.0: - role-arn: arn:aws:iam::${ECR_ACCOUNT_ID}:role/pipeline-buildkite-docs-main + role-arn: arn:aws:iam::${ECR_ACCOUNT_ID}:role/pipeline-buildkite-docs-private - wait diff --git a/.buildkite/pipeline.graphql.yml b/.buildkite/pipeline.graphql.yml index d20355fff8..941078e6d3 100644 --- a/.buildkite/pipeline.graphql.yml +++ b/.buildkite/pipeline.graphql.yml @@ -1,3 +1,10 @@ steps: - label: Update GraphQL docs command: .buildkite/update_graphql_docs + plugins: + - aws-assume-role-with-web-identity#v1.0.0: + role-arn: arn:aws:iam::445615400570:role/pipeline-buildkite-docs-private + - aws-ssm#v1.0.0: + parameters: + GH_TOKEN: /pipelines/buildkite/docs-private/gh-token + API_ACCESS_TOKEN: /pipelines/buildkite/docs-private/api-access-token diff --git a/.buildkite/pipeline.preview.yml b/.buildkite/pipeline.preview.yml index 5c17bae6a3..e02171c11d 100644 --- a/.buildkite/pipeline.preview.yml +++ b/.buildkite/pipeline.preview.yml @@ -1,18 +1,42 @@ +env: + BUILDKIT_PROGRESS: plain + steps: - label: "Prepare preview" command: bin/prepare-preview + key: prepare-preview + plugins: + - aws-assume-role-with-web-identity#v1.0.0: + role-arn: arn:aws:iam::445615400570:role/pipeline-buildkite-docs-private + - aws-ssm#v1.0.0: + parameters: + GH_TOKEN: /pipelines/buildkite/docs-private/gh-token + BUILDKITE_ANALYTICS_TOKEN: /pipelines/buildkite/docs-private/buildkite-analytics-token + NETLIFY_AUTH_TOKEN: /pipelines/buildkite/docs-private/netlify-auth-token + NETLIFY_SITE_ID: /pipelines/buildkite/docs-private/netlify-site-id - label: "Deploy preview" command: bin/deploy-preview + depends_on: prepare-preview env: RAILS_ENV: "production" plugins: + - aws-assume-role-with-web-identity#v1.0.0: + role-arn: arn:aws:iam::445615400570:role/pipeline-buildkite-docs-private + - aws-ssm#v1.0.0: + parameters: + GH_TOKEN: /pipelines/buildkite/docs-private/gh-token + BUILDKITE_ANALYTICS_TOKEN: /pipelines/buildkite/docs-private/buildkite-analytics-token + NETLIFY_AUTH_TOKEN: /pipelines/buildkite/docs-private/netlify-auth-token + NETLIFY_SITE_ID: /pipelines/buildkite/docs-private/netlify-site-id - docker-compose#v3.9.0: run: app dependencies: false mount-buildkite-agent: true env: + - GH_REPO - GH_TOKEN - NETLIFY_AUTH_TOKEN - NETLIFY_SITE_ID + - NETLIFY_SALT - BUILDKITE_BRANCH diff --git a/.buildkite/pipeline.sync.yml b/.buildkite/pipeline.sync.yml new file mode 100644 index 0000000000..6d334200c6 --- /dev/null +++ b/.buildkite/pipeline.sync.yml @@ -0,0 +1,13 @@ +#docs-private-to-public-sync +notify: + - slack: "$SLACK_CHANNEL" + if: build.state != "passed" +env: + PUBLIC_REPO: git@github.com:buildkite/docs.git +steps: + - label: Sync to public mirror + branches: main + commands: | + echo "+++ :git: Syncing to public mirror" + + git push "${PUBLIC_REPO}" ${BUILDKITE_COMMIT}:main diff --git a/.buildkite/pipeline.sync_public_pr.yml b/.buildkite/pipeline.sync_public_pr.yml new file mode 100644 index 0000000000..63e65fd330 --- /dev/null +++ b/.buildkite/pipeline.sync_public_pr.yml @@ -0,0 +1,27 @@ +steps: + # NOTE: this input step is in the pipeline steps on Buildkite + # - block: "Which PR needs to be synced?" + # fields: + # - key: pull_request_number + # required: true + # text: "Pull Request Number" + # format: "^[0-9]+$" + # hint: "Find the PR number on https://github.com/buildkite/docs/pulls" + + - label: ":git: Sync Public PR to Private Repo" + command: "bin/sync-public-pr" + plugins: + - aws-assume-role-with-web-identity#v1.0.0: + role-arn: arn:aws:iam::445615400570:role/pipeline-buildkite-docs-private + - aws-ssm#v1.0.0: + parameters: + GH_TOKEN: /pipelines/buildkite/docs-private/gh-token + - docker#v5.11.0: + image: "ruby:3.3-bookworm" + propagate-environment: true + mount-buildkite-agent: true + mount-ssh-agent: true + environment: + - GH_TOKEN + - GH_PRIVATE_REPO + - GH_PUBLIC_REPO diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 192e188bea..b8afbe3b49 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -1,3 +1,6 @@ +env: + BUILDKIT_PROGRESS: plain + steps: - label: ":spider: muffet" # We need to wait until rails has started before running muffet as otherwise it will error out @@ -56,7 +59,7 @@ steps: login: true account-ids: public.ecr.aws - docker#v3.7.0: - image: "public.ecr.aws/docker/library/node:lts-alpine3.14" + image: "public.ecr.aws/docker/library/node:lts-alpine3.16" - label: ":lint-roller: Linting text and markdown" agents: @@ -80,9 +83,7 @@ steps: # version, is way faster because we don't have to wait for Ruby gems to # install. - docker#v3.7.0: - # Alpine 3.14 - EOS 01 May 2023 - # lts = Node 1415.1 - 2023-04-30 - image: "public.ecr.aws/docker/library/node:lts-alpine3.14" + image: "public.ecr.aws/docker/library/node:lts-alpine3.16" - label: "Validate YAML" command: @@ -97,7 +98,7 @@ steps: login: true account-ids: public.ecr.aws - docker#v3.7.0: - image: "public.ecr.aws/docker/library/node:lts-alpine3.14" + image: "public.ecr.aws/docker/library/node:lts-alpine3.16" - label: ":lint-roller: :markdown: Linting the Markdown" command: npm run -y mdlint @@ -110,7 +111,7 @@ steps: login: true account-ids: public.ecr.aws - docker#v3.7.0: - image: "public.ecr.aws/docker/library/node:lts-alpine3.14" + image: "public.ecr.aws/docker/library/node:lts-alpine3.16" - label: ":snake: Linting markdown files for snake case" command: npx -y @ls-lint/ls-lint@2.1.0 @@ -123,7 +124,7 @@ steps: login: true account-ids: public.ecr.aws - docker#v3.7.0: - image: "public.ecr.aws/docker/library/node:lts-alpine3.14" + image: "public.ecr.aws/docker/library/node:lts-alpine3.16" - label: ":rspec: RSpec" depends_on: linting diff --git a/.buildkite/update_graphql_docs b/.buildkite/update_graphql_docs index 79bc49afc6..0f695a814f 100755 --- a/.buildkite/update_graphql_docs +++ b/.buildkite/update_graphql_docs @@ -38,8 +38,10 @@ git config user.email $GIT_EMAIL git config user.name $GIT_NAME git checkout -b $BRANCH git commit -m "Update GraphQL docs" -git push -u origin $BRANCH + +TARGET_REPO="https://dummy-user:${GH_TOKEN}@github.com/${GH_REPO}" +git push -f "${TARGET_REPO}" HEAD:${BRANCH} echo "+++ Create pull request" -create_pull_request "Update GraphQL docs" "This is an automated PR based on the current GraphQL schema" \ +create_pull_request "Update GraphQL docs" "This is an automated PR based on the current GraphQL schema" "${BRANCH}" \ | jq ".html_url" | buildkite-agent annotate --style "success" diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..0881c12233 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @buildkite/docs diff --git a/.github/labeler.yml b/.github/labeler.yml index 3d70159e2e..0e34d6298f 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -2,8 +2,8 @@ agent: - pages/agent/**/* cli: - pages/cli/**/* -test-analytics: - - pages/test_analytics/**/* +test-engine: + - pages/test_engine/**/* pipelines: - pages/pipelines/**/* - pages/tutorials/**/* diff --git a/.nvmrc b/.nvmrc index 8b3ed1b235..6d80269a4f 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -16.19.1 +18.16.0 diff --git a/.ruby-version b/.ruby-version index 619b537668..fa7adc7ac7 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.3.3 +3.3.5 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7a47f1daad..a4ebab359e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,32 +11,34 @@ Please also note the following style guides, which are relevant to adding conten The Buildkite docs is a custom-built website. This section gives some guidance on working with the setup. +As a public contributor to the Buildkite Docs, you should work with a fork of [this upstream repository](https://github.com/buildkite/docs) in your own GitHub account, and then create pull requests to this upstream. + ### Add a new docs page and nav entry To add a new documentation (docs) page and a nav entry for it: 1. Create the file as a new Markdown file (with the extension `.md`) within the appropriate `pages` directory. Ensure the file name is written in all lowercase letters, and separate words using underscores. (These underscores will be automatically converted to hyphens when the Buildkite Docs site is rebuilt.) -1. Add a corresponding entry to this new page in the [`data/nav.yml`](./data/nav.yml) file, which adds a new entry for this page in the page navigation sidebar (nav) of the [Buildkite Docs site](https://buildkite.com/docs). Note the existing page entries in `nav.yml` and use them as a guide to determine the location and hence, placement of the entry to your new Markdown file (in the nav and `nav.yml`). The following elements require considering for a new entry in `nav.yml`: +1. Add a corresponding entry to this new page in the [`./data/nav.yml`](./data/nav.yml) file, which adds a new entry for this page in the page navigation sidebar (nav) of the [Buildkite Docs site](https://buildkite.com/docs). Note the existing page entries in `nav.yml` and use them as a guide to determine the location and hence, placement of the entry to your new Markdown file (in the nav and `nav.yml`). The following elements require considering for a new entry in `nav.yml`: -| Key | Description | Data type | -| ------------- | ----------- | --------- | -| `name` | Nav entry name (see note below). | String, required | -| `path` | Enter a relative URL path for internal pages. You can also prepend with `https` for external pages, or `mailto:` for email links, although this practice should be avoided or minimized. If the `path` is empty or omitted, then this will be rendered as a toggle that opens a new section of pages. | String, optional | -| `icon` | Prepend with an icon. | String, optional | -| `theme` | WIP: doesn't work yet. Apply a theme. You can use `green` or `purple`. | String, optional | -| `children` | Child nav entry items. | Array of objects, optional | -| `pill` | Append a pill. Currently you can use `beta`, `coming-soon`, `deprecated` or `new` | String, optional | -| `new_window` | Make this link open up a new window, although this practice should be avoided or minimized. | Bool, optional | -| `type` | Special nav link types. With `dropdown` the children nav items will be rendered as hover dropdown menus on laptop/desktop screen devices. `link` is a shortcut link that takes the user from one section to another (for example, you may link to SSO under the Integrations section from Pipeline's sidebar). It also renders an 'external link' icon as an affordance. Lastly, `divider` makes a divider line in the nav to help with visual delineation. | String, `dropdown|link|divider`, optional | + | Key | Description | Data type | + | ------------- | ----------- | --------- | + | `name` | Nav entry name (see note below). | String, required | + | `path` | Enter a relative URL path for internal pages. You can also prepend with `https` for external pages, or `mailto:` for email links, although this practice should be avoided or minimized. If the `path` is empty or omitted, then this will be rendered as a toggle that opens a new section of pages. | String, optional | + | `icon` | Prepend with an icon. | String, optional | + | `theme` | WIP: doesn't work yet. Apply a theme. You can use `green` or `purple`. | String, optional | + | `children` | Child nav entry items. | Array of objects, optional | + | `pill` | Append a pill. Currently you can use `beta`, `coming-soon`, `deprecated` or `new` | String, optional | + | `new_window` | Make this link open up a new window, although this practice should be avoided or minimized. | Bool, optional | + | `type` | Special nav link types. With `dropdown` the children nav items will be rendered as hover dropdown menus on laptop/desktop screen devices. `link` is a shortcut link that takes the user from one section to another (for example, you may link to SSO under the Integrations section from Pipeline's sidebar). It also renders an 'external link' icon as an affordance. Lastly, `divider` makes a divider line in the nav to help with visual delineation. | String, `dropdown|link|divider`, optional | > [!NOTE] > Whenever you save changes to the `nav.yml` file, you'll need to stop and restart your local development environment in order to see these changes reflected in the nav. -> +> > The Buildkite Docs web site is kept running with Ruby, which interprets underscores in filenames as hyphens. Therefore, if a page is called `octopussy_cat.md`, then for its entry in the `nav.yml` file, you need to reference its `path` key value as `octopussy-cat`. -> +> > If you're creating a new section for the nav, then as described for the `path` key above, add the `name` key for this entry, omit its `path` key, and add a `children` key to create this new section. Then, nest/indent all new page entries within this section entry. -> +> > Since a new section entry in the nav is purely a toggle that cannot hold page content itself, then to introduce a page for this new section, create a top-level "Overview" page for this section instead. ### Linting @@ -64,9 +66,9 @@ The rules enabled for this Markdown linting are defined in the [`.markdownlint.y The Buildkite Docs build pipeline uses [Vale](https://vale.sh/) to check for spelling errors, and builds will fail if a spelling error is encountered. -If you need to add an exception to this (for example, you are referencing a new technology or tool that isn't in Vale's vocabulary), add this term verbatim to the [`/vale/styles/vocab.txt`](./vale/styles/vocab.txt) file, ensuring that the term is added in the correct alphabetical order within the file. Case is important but should be ignored with regard to alphabetical ordering within the file. This makes it easier to identify if an exception has already been added. +If you need to add an exception to this (for example, you are referencing a new technology or tool that isn't in Vale's vocabulary), add this term verbatim to the [`./vale/styles/vocab.txt`](./vale/styles/vocab.txt) file, ensuring that the term is added in the correct alphabetical order within the file. Case is important but should be ignored with regard to alphabetical ordering within the file. This makes it easier to identify if an exception has already been added. -If you encounter a spelling error within a heading, add this entry into the [`/vale/styles/Buildkite/h1-h6_sentence_case.yml`](./vale/styles/Buildkite/h1-h6_sentence_case.yml) file. +If you encounter a spelling error within a heading, add this entry into the [`./vale/styles/Buildkite/h1-h6_sentence_case.yml`](./vale/styles/Buildkite/h1-h6_sentence_case.yml) file. #### Escape vale linting @@ -114,13 +116,14 @@ To save yourself a few unnecessary rounds of edits in the future, remember that #### Beta flags -To mark a content page in the site as being in beta, add its relative path _after_ `docs` to the `app/models/beta_pages.rb` file. +To mark a content page in the site as being in beta, add its relative path _after_ `docs` to the [`./app/models/beta_pages.rb`](./app/models/beta_pages.rb) file. For example: ``` [ - 'test-analytics', - 'test-analytics/integrations' + 'pipelines/some-new-beta-feature', + 'test-engine/some-new-beta-feature', + 'package-registries/some-new-beta-feature' ] ``` @@ -130,7 +133,7 @@ Adding the class `has-pill-beta` to any element will append the beta pill. This #### Table of contents -Table of contents are automatically generated based on `##`-level headings. +An in-page table of contents (with the **On this page** title) is automatically generated based on `##`-level headings. You can omit a table of contents by adding some additional metadata to a Markdown template using the following YAML front matter: @@ -243,10 +246,10 @@ This information was aggregated by going over the existing screenshots in the do > Before you proceed, make sure that both the width and the height of the image are an even number of pixels! Steps for adding add an image to a documentation page: -1. Name the image file (lowercase, separate words using hyphens; add a number to the filename, for example, 'installation-1' if you are adding several images to the same page) -2. Put the file into the corresponding `images` folder (a folder with the same name as the page you are adding this image to; create such folder if it doesn't exist yet) -3. Compose relevant alt text for the image file using sentence case -4. Add your image file to the documentation page using the following code example `<%= image "your-image.png", width: 1110, height: 1110, alt: "Screenshot of Important Feature" %>`. +1. Name the image file (lowercase, separate words using hyphens; add a number to the filename, for example, 'installation-1' if you are adding several images to the same page). +1. Save the file into its corresponding `images` folder (that is, a sub-folder within `images` whose path and name respectively matches that of the Markdown page's path within `pages` and the name this image file is referenced by on this page). Create this sub-folder hierarchy if it doesn't yet exist within `images`. +1. Compose relevant alt text for the image file using sentence case. +1. Add your image file to the documentation page using the following code example `<%= image "your-image.png", width: 1110, height: 1110, alt: "Screenshot of Important Feature" %>`. For large images/screenshots taken on a retina screen, use `<%= image "your-image.png", width: 1110/2, height: 1110/2, alt: "Screenshot of Important Feature" %>`. ## Talking about YAML diff --git a/Dockerfile b/Dockerfile index bbcd1d2b0f..aa945f6e3f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG BASE_IMAGE=public.ecr.aws/docker/library/ruby:3.3.3-slim-bookworm@sha256:bc6372a998e79b5154c8132d1b3e0287dc656249f71f48487a1ecf0d46c9c080 +ARG BASE_IMAGE=public.ecr.aws/docker/library/ruby:3.3.5-slim-bookworm ARG NODE_IMAGE=public.ecr.aws/docker/library/node:18-bookworm-slim@sha256:d2d8a6420c9fc6b7b403732d3a3c5395d016ebc4996f057aad1aded74202a476 FROM $BASE_IMAGE AS builder diff --git a/Gemfile.lock b/Gemfile.lock index 6b50c7268c..128dcdd8ef 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,25 +1,25 @@ GEM remote: https://rubygems.org/ specs: - actionpack (6.1.7.8) - actionview (= 6.1.7.8) - activesupport (= 6.1.7.8) + actionpack (6.1.7.9) + actionview (= 6.1.7.9) + activesupport (= 6.1.7.9) rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actionview (6.1.7.8) - activesupport (= 6.1.7.8) + actionview (6.1.7.9) + activesupport (= 6.1.7.9) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.1.7.8) - activesupport (= 6.1.7.8) + activejob (6.1.7.9) + activesupport (= 6.1.7.9) globalid (>= 0.3.6) - activemodel (6.1.7.8) - activesupport (= 6.1.7.8) - activesupport (6.1.7.8) + activemodel (6.1.7.9) + activesupport (= 6.1.7.9) + activesupport (6.1.7.9) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) @@ -30,7 +30,7 @@ GEM bindex (0.8.1) bugsnag (6.21.0) concurrent-ruby (~> 1.0) - builder (3.2.4) + builder (3.3.0) buildkite-test_collector (2.3.1) activesupport (>= 4.2) byebug (11.1.3) @@ -44,7 +44,7 @@ GEM xpath (~> 3.2) coderay (1.1.3) commonmarker (0.23.10) - concurrent-ruby (1.3.1) + concurrent-ruby (1.3.4) crass (1.0.6) diff-lcs (1.4.4) dotenv (2.8.1) @@ -52,7 +52,7 @@ GEM dotenv (= 2.8.1) railties (>= 3.2) dry-cli (1.0.0) - erubi (1.12.0) + erubi (1.13.0) escape_utils (1.2.1) foreman (0.87.2) front_matter_parser (1.0.1) @@ -62,7 +62,7 @@ GEM graphql-client (0.18.0) activesupport (>= 3.0) graphql - i18n (1.14.5) + i18n (1.14.6) concurrent-ruby (~> 1.0) lograge (0.12.0) actionpack (>= 4) @@ -76,19 +76,19 @@ GEM method_source (1.0.0) mini_mime (1.1.0) mini_portile2 (2.8.7) - minitest (5.23.1) - nio4r (2.7.0) - nokogiri (1.16.5) + minitest (5.25.1) + nio4r (2.7.3) + nokogiri (1.16.7) mini_portile2 (~> 2.8.2) racc (~> 1.4) pry (0.14.1) coderay (~> 1.1) method_source (~> 1.0) public_suffix (4.0.6) - puma (5.6.8) + puma (5.6.9) nio4r (~> 2.0) - racc (1.8.0) - rack (2.2.9) + racc (1.8.1) + rack (2.2.10) rack-proxy (0.7.6) rack rack-test (2.1.0) @@ -100,9 +100,9 @@ GEM rails-html-sanitizer (1.6.0) loofah (~> 2.21) nokogiri (~> 1.14) - railties (6.1.7.8) - actionpack (= 6.1.7.8) - activesupport (= 6.1.7.8) + railties (6.1.7.9) + actionpack (= 6.1.7.9) + activesupport (= 6.1.7.9) method_source rake (>= 12.2) thor (~> 1.0) @@ -155,7 +155,7 @@ GEM railties (>= 6.0.0) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.15) + zeitwerk (2.7.0) PLATFORMS ruby @@ -190,7 +190,7 @@ DEPENDENCIES web-console RUBY VERSION - ruby 3.3.3p89 + ruby 3.3.5p100 BUNDLED WITH 2.4.7 diff --git a/README.md b/README.md index 67dd616b93..30ef18250d 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ On some platforms (for example, Linux-based ones), you may need to prefix `docke #### Get the Buildkite Docs source -Clone the Buildkite Docs source locally. To do so, run these commands: +As a public contributor to the Buildkite Docs, clone its source repository locally. To do so, run these commands: ```bash git clone git@github.com:buildkite/docs.git diff --git a/app/frontend/components/copyToClipboardButton.js b/app/frontend/components/copyToClipboardButton.js index d4d9d50f97..34d8184ab8 100644 --- a/app/frontend/components/copyToClipboardButton.js +++ b/app/frontend/components/copyToClipboardButton.js @@ -6,7 +6,7 @@ const checkedCircleIcon = ` const clipboardDocumentIcon = ` - + `; const COPY_TIMEOUT = 600; diff --git a/app/frontend/components/themeToggle.js b/app/frontend/components/themeToggle.js new file mode 100644 index 0000000000..8138ec1918 --- /dev/null +++ b/app/frontend/components/themeToggle.js @@ -0,0 +1,45 @@ +export function themeToggle() { + const themeSelect = document.querySelector("#theme-select"); + + function setTheme(theme) { + localStorage.setItem("docs-theme", theme); + updateAppearance(); + } + + function updateAppearance() { + let storedTheme = localStorage.getItem("docs-theme") || "system"; + let systemPrefersDark = window.matchMedia( + "(prefers-color-scheme: dark)" + ).matches; + + themeSelect.value = storedTheme; + document + .querySelectorAll(".theme-icon") + .forEach((icon) => icon.classList.add("theme-inactive")); + + if ( + storedTheme === "dark" || + (storedTheme === "system" && systemPrefersDark) + ) { + document.documentElement.classList.add("dark"); + } else { + document.documentElement.classList.remove("dark"); + } + + document + .querySelector(`.theme-${storedTheme}`) + .classList.remove("theme-inactive"); + } + + themeSelect.addEventListener("change", function () { + setTheme(this.value); + }); + + window.matchMedia("(prefers-color-scheme: dark)").addListener(function () { + if (localStorage.getItem("docs-theme") === "system") { + updateAppearance(); + } + }); + + updateAppearance(); +} diff --git a/app/frontend/css/base/_variables.scss b/app/frontend/css/base/_variables.scss index 0203c1f6a5..2121b3712d 100644 --- a/app/frontend/css/base/_variables.scss +++ b/app/frontend/css/base/_variables.scss @@ -37,6 +37,7 @@ $navy-600: #4f4a6a; $navy-700: #383451; $navy-800: #28243f; $navy-900: #140d30; +$navy-950: #0e0923; $gray-100: #f8f8f8; $gray-200: #f5f5f5; $gray-300: #eeeeee; diff --git a/app/frontend/css/components/_copy_to_clipboard_button.scss b/app/frontend/css/components/_copy_to_clipboard_button.scss index df5ae444b2..af756d82bc 100644 --- a/app/frontend/css/components/_copy_to_clipboard_button.scss +++ b/app/frontend/css/components/_copy_to_clipboard_button.scss @@ -19,6 +19,7 @@ padding: 0; border: 0; + color: #0f172a; } // Render when focusing sibling (
) element
diff --git a/app/frontend/css/components/_global_links.scss b/app/frontend/css/components/_global_links.scss
index f1ce77fe0b..b065eb042b 100644
--- a/app/frontend/css/components/_global_links.scss
+++ b/app/frontend/css/components/_global_links.scss
@@ -1,10 +1,12 @@
 .GlobalLinks {
   display: flex;
-  flex-direction: column;
+  flex-direction: row;
   width: 100%;
+  align-items: center;
+  justify-content: center;
 
-  @media (min-width: $screen-sm) {
-    flex-direction: row;
+  @media (min-width: $screen-md) {
+    justify-content: end;
   }
 }
 
diff --git a/app/frontend/css/components/_index.scss b/app/frontend/css/components/_index.scss
index 1ac1200a8b..2b49a4f3eb 100644
--- a/app/frontend/css/components/_index.scss
+++ b/app/frontend/css/components/_index.scss
@@ -20,4 +20,5 @@
 @import "site_header";
 @import "status_badges";
 @import "tiles";
+@import "theme_select";
 @import "toc";
diff --git a/app/frontend/css/components/_menu_toggle.scss b/app/frontend/css/components/_menu_toggle.scss
index 33df73b647..4cfc804ec7 100644
--- a/app/frontend/css/components/_menu_toggle.scss
+++ b/app/frontend/css/components/_menu_toggle.scss
@@ -14,6 +14,9 @@
   &:checked ~ .SiteHeader__nav,
   &:checked ~ .SiteHeader__global-links {
     display: flex;
+    @media (max-width: 959px) {
+      width: 100%;
+    }
   }
 }
 
diff --git a/app/frontend/css/components/_site_header.scss b/app/frontend/css/components/_site_header.scss
index a5de22878c..3a5bc122e0 100644
--- a/app/frontend/css/components/_site_header.scss
+++ b/app/frontend/css/components/_site_header.scss
@@ -109,3 +109,11 @@
     color: map-get($color-aliases, "brand");
   }
 }
+
+.Wordmark__Brand {
+  color: #1a002e;
+}
+
+.Wordmark__SubBrand {
+  color: #504581;
+}
diff --git a/app/frontend/css/components/_theme_select.scss b/app/frontend/css/components/_theme_select.scss
new file mode 100644
index 0000000000..b42f0ce86c
--- /dev/null
+++ b/app/frontend/css/components/_theme_select.scss
@@ -0,0 +1,44 @@
+.theme-ui {
+  border-radius: 6px;
+  border: 1px solid $navy-200;
+  display: block;
+  position: relative;
+  svg {
+    color: $navy-600;
+  }
+}
+
+.theme-chevron {
+  width: 16px;
+  height: 16px;
+  position: absolute;
+  right: 6px;
+  top: 10px;
+  pointer-events: none;
+}
+
+.theme-icon {
+  width: 20px;
+  position: absolute;
+  top: 8px;
+  left: 8px;
+  pointer-events: none;
+}
+
+.theme-inactive {
+  display: none;
+}
+
+#theme-select {
+  appearance: none;
+  font-size: 14px;
+  margin-left: 12px;
+  line-height: 16px;
+  border: 0 none;
+  background: transparent;
+  padding: 10px 24px 10px 20px;
+  color: currentColor;
+  &:focus {
+    outline: none;
+  }
+}
diff --git a/app/frontend/css/pages/homepage/_products.scss b/app/frontend/css/pages/homepage/_products.scss
index cc509aed9f..2974d3bb03 100644
--- a/app/frontend/css/pages/homepage/_products.scss
+++ b/app/frontend/css/pages/homepage/_products.scss
@@ -55,6 +55,29 @@
 
 .ProductCard__img {
   @media (min-width: $screen-xs) {
-    width: 148px;
+    height: 50px;
+  }
+}
+
+.ProductBadge {
+  display: inline-flex;
+  align-items: center;
+  border-radius: 12px;
+  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1),
+    0px 0px 0px 1px rgba(0, 0, 0, 0.15), 0px 1px 0px 0px rgba(0, 0, 0, 0.09),
+    0px 2px 2px 0px rgba(0, 0, 0, 0.04), 0px 3px 3px 0px rgba(0, 0, 0, 0.02),
+    0px 4px 4px 0px rgba(0, 0, 0, 0.01);
+  padding-right: 12px;
+  background: #fff;
+  font-size: 15px;
+  color: #28243f;
+  font-weight: 600;
+  margin-bottom: 16px;
+  svg {
+    width: 24px;
+    height: 24px;
+    padding: 8px;
+    border-right: 1px solid rgba(0, 0, 0, 0.2);
+    margin-right: 12px;
   }
 }
diff --git a/app/frontend/css/utilities/_dark_mode.scss b/app/frontend/css/utilities/_dark_mode.scss
new file mode 100644
index 0000000000..c8f9ea1776
--- /dev/null
+++ b/app/frontend/css/utilities/_dark_mode.scss
@@ -0,0 +1,356 @@
+html.dark {
+  background: #020617;
+
+  --docsearch-text-color: rgb(245, 246, 247);
+  --docsearch-container-background: rgba(9, 10, 17, 0.8);
+  --docsearch-modal-background: rgb(21, 23, 42);
+  --docsearch-modal-shadow: inset 1px 1px 0 0 rgb(44, 46, 64),
+    0 3px 8px 0 rgb(0, 3, 9);
+  --docsearch-searchbox-background: rgb(9, 10, 17);
+  --docsearch-searchbox-focus-background: #000;
+  --docsearch-hit-color: rgb(190, 195, 201);
+  --docsearch-hit-shadow: none;
+  --docsearch-hit-background: rgb(9, 10, 17);
+  --docsearch-key-gradient: linear-gradient(
+    -26.5deg,
+    rgb(86, 88, 114) 0%,
+    rgb(49, 53, 91) 100%
+  );
+  --docsearch-key-shadow: inset 0 -2px 0 0 rgb(40, 45, 85),
+    inset 0 0 1px 1px rgb(81, 87, 125), 0 2px 2px 0 rgba(3, 4, 9, 0.3);
+  --docsearch-footer-background: rgb(30, 33, 54);
+  --docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, 0.5),
+    0 -4px 8px 0 rgba(0, 0, 0, 0.2);
+  --docsearch-muted-color: rgb(127, 132, 151);
+  --docsearch-logo-color: rgb(255, 255, 255);
+
+  .SiteHeader,
+  .Page__sidebar,
+  .SiteHeader__nav,
+  .divider,
+  .Article tbody tr,
+  hr {
+    border-color: $navy-800;
+  }
+
+  .Article thead {
+    border-color: $navy-700;
+  }
+
+  .Wordmark__Brand {
+    color: #ffffff;
+  }
+
+  .Wordmark__SubBrand {
+    color: $navy-400;
+  }
+
+  .SiteHeader,
+  .Nav--sidebar .Nav__section--level2 {
+    background: #020617;
+  }
+
+  h1,
+  h2,
+  h3,
+  h4,
+  h5,
+  h6,
+  .TileItem .TileItem__title-link,
+  .Docs__heading .Docs__heading__anchor,
+  .Footer__heading,
+  .Card__title-link {
+    color: $navy-50;
+  }
+
+  .Nav__link,
+  .Dropdown__menu-link {
+    color: $navy-300;
+    &:hover {
+      background: #1f023e;
+      color: $navy-200;
+    }
+  }
+
+  .Toc__link {
+    color: $navy-300;
+  }
+
+  .Nav__link--parent {
+    color: #e5e1ff !important;
+  }
+
+  .Nav__link--current {
+    background: #340469 !important;
+    color: #e5e1ff !important;
+  }
+
+  .Article,
+  .Footer,
+  .HeroBanner__summary,
+  .ProductCard__summary,
+  .Card__list-item-link,
+  .Reference__link,
+  p {
+    color: $navy-300;
+    a {
+      color: #9f83fe;
+      text-decoration-color: #340469;
+      &:hover {
+        text-decoration-color: #9f83fe;
+      }
+    }
+  }
+
+  .Article pre {
+    border-color: #1e293b;
+    background-color: #0f172a;
+  }
+
+  .Article .highlight-figure figcaption {
+    border-color: #1e293b;
+    color: $navy-500;
+    background-color: #0f172a;
+  }
+
+  .highlight {
+    color: $navy-300;
+  }
+
+  .CopyToClipboardButton {
+    background: $navy-600 !important;
+    svg {
+      color: $navy-200 !important;
+    }
+  }
+
+  .highlight .s,
+  .highlight .sb,
+  .highlight .sc,
+  .highlight .s2,
+  .highlight .se,
+  .highlight .sh,
+  .highlight .si,
+  .highlight .sx,
+  .highlight .sr,
+  .highlight .s1,
+  .highlight .ss {
+    color: #00e285;
+  }
+
+  .highlight .na,
+  .highlight .nc,
+  .highlight .nd,
+  .highlight .ni,
+  .highlight .ne,
+  .highlight .nf,
+  .highlight .nl,
+  .highlight .nn,
+  .highlight .nx,
+  .highlight .py,
+  .highlight .nv,
+  .highlight .vc,
+  .highlight .vg,
+  .highlight .vi {
+    color: #9f83fe;
+  }
+
+  .highlight .k,
+  .highlight .kc,
+  .highlight .kd,
+  .highlight .kn,
+  .highlight .kp,
+  .highlight .kr,
+  .highlight .kt,
+  .highlight .nb,
+  .highlight .bp,
+  .highlight .nt,
+  .highlight .no,
+  .highlight .o,
+  .highlight .ow,
+  .highlight .mf,
+  .highlight .mh,
+  .highlight .mi,
+  .highlight .il,
+  .highlight .mo,
+  .highlight .ld,
+  .highlight .m {
+    color: #f2545b;
+  }
+
+  .callout {
+    background: #0f172a;
+    color: $navy-300;
+    p {
+      color: inherit;
+    }
+  }
+
+  .Button--default,
+  .Article details {
+    background-color: #0f172a;
+    color: $navy-50 !important;
+    box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.01),
+      0px 3px 3px 0px rgba(0, 0, 0, 0.02), 0px 2px 2px 0px rgba(0, 0, 0, 0.04),
+      0px 1px 0px 0px rgba(0, 0, 0, 0.09), 0px 0px 0px 1px rgba(0, 0, 0, 0.09);
+  }
+
+  .Button--default:hover,
+  .PopularGuide:hover {
+    background-color: #1e293b;
+  }
+
+  .Article h1:not([class]) > code,
+  .Article h2:not([class]) > code,
+  .Article h3:not([class]) > code,
+  .Article h4:not([class]) > code,
+  .Article h5:not([class]) > code,
+  .Article h6:not([class]) > code,
+  .Article p:not([class]) > code,
+  .Article a:not([class]) > code,
+  .Article li > code,
+  .Article dt > code,
+  .Article td > code,
+  .Article th > code {
+    background-color: #0f172a;
+  }
+
+  .callout p code {
+    background-color: #ffffff0f !important;
+  }
+
+  .theme-ui {
+    border-color: #1e293b;
+    svg {
+      color: $navy-400;
+    }
+  }
+
+  #theme-select {
+    color: $navy-300;
+  }
+
+  .ProductCard,
+  .Card {
+    background: #0f172a;
+  }
+
+  .Card__title-link:hover,
+  .Card__icon-link:hover + .Card__title .Card__title-link {
+    color: #e5e1ff;
+  }
+
+  .Toc .Toc__list-item.active > .Toc__link,
+  .Toc .Toc__link:hover {
+    color: #9f83fe;
+  }
+
+  .Toc path {
+    stroke: #9f83fe;
+  }
+
+  .DocSearch-Button {
+    color: #fff;
+    background: #020617;
+  }
+
+  .Toc {
+    background: #020617;
+    border: 1px solid $navy-800;
+    @media (min-width: 1280px) {
+      border: 0 none;
+      background: transparent;
+    }
+  }
+
+  .Dropdown,
+  .Dropdown__menu {
+    background: #020617;
+    color: #fff;
+  }
+
+  .Dropdown__menu {
+    border: 1px solid $navy-800;
+  }
+
+  .Dropdown__menu::before {
+    border-bottom-color: $navy-800;
+  }
+
+  .Dropdown__menu::after {
+    border-bottom-color: #020617;
+  }
+
+  .Button {
+    color: $navy-50;
+  }
+
+  a.Docs__example-repo {
+    border-color: $navy-700;
+    color: $navy-300;
+    .repo {
+      color: $navy-400;
+      &:hover {
+        color: $purple1-500;
+      }
+    }
+  }
+
+  .callout {
+    @include callout($navy-200, #0f172a, default_dark);
+    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1) !important;
+    .callout__anchor {
+      &:hover,
+      &:active,
+      &:focus {
+        color: $navy-50 !important;
+      }
+    }
+  }
+
+  .callout--troubleshooting {
+    @include callout(#fed7aa, #431407, troubleshooting_dark);
+    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1) !important;
+    .callout__anchor {
+      &:hover,
+      &:active,
+      &:focus {
+        color: $navy-50 !important;
+      }
+    }
+  }
+
+  .callout--wip {
+    @include callout(#d6d3d1, #1c1917, wip_dark);
+    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1) !important;
+    .callout__anchor {
+      &:hover,
+      &:active,
+      &:focus {
+        color: $navy-50 !important;
+      }
+    }
+  }
+
+  .pill,
+  .Button__icon--16x16,
+  .MenuToggleLabel {
+    filter: invert(92%) hue-rotate(180deg);
+  }
+
+  .MenuToggleLabel {
+    background-color: #fff;
+    &:hover {
+      background-color: #eee;
+    }
+  }
+
+  .ProductBadge {
+    background: #1e293b;
+    color: #fff;
+    svg {
+      border-right: 1px solid rgba(255, 255, 255, 0.2);
+      margin-right: 8px;
+    }
+  }
+}
diff --git a/app/frontend/css/utilities/_index.scss b/app/frontend/css/utilities/_index.scss
index a6d29b0f88..e3021a6870 100644
--- a/app/frontend/css/utilities/_index.scss
+++ b/app/frontend/css/utilities/_index.scss
@@ -6,3 +6,4 @@
 @import "responsive_image_container";
 @import "sr_only";
 @import "standard_top_section";
+@import "dark_mode";
diff --git a/app/frontend/entrypoints/application.js b/app/frontend/entrypoints/application.js
index 1a201db67e..52f21dc73b 100644
--- a/app/frontend/entrypoints/application.js
+++ b/app/frontend/entrypoints/application.js
@@ -2,6 +2,7 @@ import * as Turbo from "@hotwired/turbo";
 import { bindToggles } from "../components/nav";
 import { initToc } from "../components/toc";
 import { attachCopyToClipboardButton } from "../components/copyToClipboardButton";
+import { themeToggle } from "../components/themeToggle";
 import docsearch from "@docsearch/js";
 
 Turbo.start();
@@ -25,6 +26,7 @@ function render() {
   bindToggles();
   initToc();
   attachCopyToClipboardButton("pre.highlight");
+  themeToggle();
 }
 
 window.addEventListener("DOMContentLoaded", () => {
diff --git a/app/models/beta_pages.rb b/app/models/beta_pages.rb
index 67eb97cc0a..952c7cc0bd 100644
--- a/app/models/beta_pages.rb
+++ b/app/models/beta_pages.rb
@@ -1,14 +1,8 @@
 class BetaPages
   def self.all
     [
-      'pipelines/cluster-queue-metrics',
-      'test-analytics/test-ownership',
-      'apis/rest-api/team-pipelines',
-      'apis/rest-api/organizations/members',
-      'apis/rest-api/teams',
-      'apis/rest-api/teams/members',
-      'apis/rest-api/teams/pipelines',
-      'apis/rest-api/teams/suites'
+      'path/page-name',
+      'path/last-page-name-in-list-without-trailing-comma'
     ]
   end
 end
diff --git a/app/views/application/_brand.html.erb b/app/views/application/_brand.html.erb
index 4521111289..498c4a7290 100644
--- a/app/views/application/_brand.html.erb
+++ b/app/views/application/_brand.html.erb
@@ -3,6 +3,9 @@
     Buildkite logo
   <% end %>
   <%= link_to home_page_path, title: "Return to Docs index page" do %>
-    Buildkite Docs" />
+    
+      
+      
+    
   <% end %>
 
diff --git a/app/views/application/_global_links.html.erb b/app/views/application/_global_links.html.erb
index 35b7f2546c..5c6ad2fdde 100644
--- a/app/views/application/_global_links.html.erb
+++ b/app/views/application/_global_links.html.erb
@@ -12,6 +12,22 @@
       
     
   
+  
  • + +
  • <% if probably_authenticated? %>