From b8b8d67f324958600ce5ba2843e0ddaf116358e8 Mon Sep 17 00:00:00 2001 From: sam bacha Date: Sun, 22 May 2022 23:38:33 -0700 Subject: [PATCH] deploy (#1) --- .github/workflows/ci.yml | 41 ++++++++++ .github/workflows/lighthouse.yml | 62 +++++++++++++++ .github/workflows/lighthouserc.json | 9 +++ .github/workflows/release.yml | 73 ++++++++++++++++++ build-script.sh | 15 ++++ netlify.toml | 41 ++++++++++ utils/frontmatter.yml | 17 ++++ utils/generateSidebar.js | 115 ++++++++++++++++++++++++++++ 8 files changed, 373 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/lighthouse.yml create mode 100644 .github/workflows/lighthouserc.json create mode 100644 .github/workflows/release.yml create mode 100755 build-script.sh create mode 100644 netlify.toml create mode 100644 utils/frontmatter.yml create mode 100644 utils/generateSidebar.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9b29c35 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,41 @@ +name: CI + +on: + push: + branches-ignore: + - master + paths-ignore: + - .github/** + # manual trigger + workflow_dispatch: + +jobs: + build: + name: Build + runs-on: ubuntu-latest + steps: + - name: Clone source code + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Setup Node + uses: actions/setup-node@v2 + with: + node-version: '14.x' + + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-node- + - name: Install Dependencies + id: install + run: | + yarn install --frozen-lockfile + - name: Build + id: build + run: | + yarn run build diff --git a/.github/workflows/lighthouse.yml b/.github/workflows/lighthouse.yml new file mode 100644 index 0000000..f3a83ed --- /dev/null +++ b/.github/workflows/lighthouse.yml @@ -0,0 +1,62 @@ +name: lighthouse + +on: [pull_request] + +jobs: + lighthouse-report: + name: Lighthouse Report + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Wait for the Netlify Preview + uses: jakepartusch/wait-for-netlify-action@v1 + id: netlify + with: + site_name: docs-manifold + max_timeout: 600 + - name: Audit URLs using Lighthouse + id: lighthouse_audit + uses: treosh/lighthouse-ci-action@v9 + # see https://docs.netlify.com/site-deploys/deploy-previews/ + # for more information on deploy previews + with: + urls: | + https://deploy-preview-$PR_NUMBER--docs-manifold.netlify.app/ + + configPath: ./.github/workflows/lighthouserc.json + uploadArtifacts: true + temporaryPublicStorage: true + env: + PR_NUMBER: ${{ github.event.pull_request.number}} + - name: Format lighthouse score + id: format_lighthouse_score + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const result = ${{ steps.lighthouse_audit.outputs.manifest }}[0].summary + const links = ${{ steps.lighthouse_audit.outputs.links }} + const formatResult = (res) => Math.round((res * 100)) + Object.keys(result).forEach(key => result[key] = formatResult(result[key])) + const score = res => res >= 90 ? '🟢' : res >= 50 ? '🟠' : '🔴' + const comment = [ + `⚡️ [Lighthouse report](${Object.values(links)[0]}) for the changes in this PR:`, + '| Category | Score |', + '| --- | --- |', + `| ${score(result.performance)} Performance | ${result.performance} |`, + `| ${score(result.accessibility)} Accessibility | ${result.accessibility} |`, + `| ${score(result['best-practices'])} Best practices | ${result['best-practices']} |`, + `| ${score(result.seo)} SEO | ${result.seo} |`, + `| ${score(result.pwa)} PWA | ${result.pwa} |`, + ' ', + `*Lighthouse ran on [${Object.keys(links)[0]}](${Object.keys(links)[0]})*` + ].join('\n') + core.setOutput("comment", comment); + - name: Add Lighthouse stats as comment + id: comment_to_pr + uses: marocchino/sticky-pull-request-comment@v2.2.0 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + number: ${{ github.event.pull_request.number }} + header: lighthouse + message: ${{ steps.format_lighthouse_score.outputs.comment }} diff --git a/.github/workflows/lighthouserc.json b/.github/workflows/lighthouserc.json new file mode 100644 index 0000000..e681e0b --- /dev/null +++ b/.github/workflows/lighthouserc.json @@ -0,0 +1,9 @@ +{ + "ci": { + "collect": { + "settings": { + "skipAudits": ["robots-txt", "canonical", "tap-targets", "is-crawlable", "works-offline", "offline-start-url"] + } + } + } +} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..a2fbd1d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,73 @@ +name: Release + +on: + push: + branches: + - master + - trunk + paths-ignore: + - .github/** + # manual trigger + workflow_dispatch: + +jobs: + bump_version: + name: Bump Version + runs-on: ubuntu-latest + outputs: + new_tag: ${{ steps.github_tag_action.outputs.new_tag }} + changelog: ${{ steps.github_tag_action.outputs.changelog }} + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Bump version and push tag + id: github_tag_action + uses: mathieudutour/github-tag-action@v4.5 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + release_branches: master + + create_release: + name: Create Release + runs-on: ubuntu-latest + needs: bump_version + if: ${{ needs.bump_version.outputs.new_tag != null }} + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Setup Node + uses: actions/setup-node@v2 + with: + node-version: '14.x' + + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-node- + - name: Install Dependencies + id: install + run: | + yarn install + + - name: Build + id: build + run: | + yarn run build + + - name: Create GitHub Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ needs.bump_version.outputs.new_tag }} + release_name: Release ${{ needs.bump_version.outputs.new_tag }} + body: | + latest version ${{ needs.bump_version.outputs.new_tag }} diff --git a/build-script.sh b/build-script.sh new file mode 100755 index 0000000..6c9c926 --- /dev/null +++ b/build-script.sh @@ -0,0 +1,15 @@ +#!/usr/env/bin bash +set -ex + +echo $BASH_VERSION + +yarn install + +export NODE_ENV=production + +yarn run format +sleep 1 +npx docusaurus clear +NODE_ENV=production npx docusaurus build +echo "Finished Building Production" +exit 0 \ No newline at end of file diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 0000000..855dc24 --- /dev/null +++ b/netlify.toml @@ -0,0 +1,41 @@ +[build] + command = "yarn install && yarn run build" + publish = "build" + + [build.processing] + skip_processing = false + [build.processing.css] + bundle = true + minify = true + [build.processing.js] + bundle = true + minify = true + [build.processing.html] + pretty_urls = true + [build.processing.images] + compress = true + + + [headers] +# Define which paths this specific [[headers]] block will cover. + for = "/*" + [headers.values] + Strict-Transport-Security = "max-age=31536000; includeSubDomains; preload" + +[build.analyze] + command = "ANALYZE=true gatsby build" + +#[[headers]] +# for = "/*" # This defines which paths this specific [[headers]] block will cover. +# [headers.values] +# X-Frame-Options = "DENY" +# X-XSS-Protection = "1; mode=block" +# Content-Security-Policy = "frame-ancestors https://www.facebook.com" +# # Multi-key header rules are expressed with multi-line strings +# Link = ''' +# ; rel=preload; as=style, \ +# ; rel=preload; as=style, \ +# ; rel=preload; as=style''' +# # Basic-Auth allows you to password protect your whole site but is only available +# # to paid accounts +# Basic-Auth = "someuser:somepassword anotheruser:anotherpassword" \ No newline at end of file diff --git a/utils/frontmatter.yml b/utils/frontmatter.yml new file mode 100644 index 0000000..8d2632d --- /dev/null +++ b/utils/frontmatter.yml @@ -0,0 +1,17 @@ +--- +id: doc-markdown +title: Docs Markdown Features +hide_title: false +hide_table_of_contents: false +sidebar_label: Markdown +sidebar_position: 3 +pagination_label: Markdown features +custom_edit_url: https://github.com/facebook/docusaurus/edit/main/docs/api-doc-markdown.md +description: How do I find you when I cannot solve this problem +keywords: + - docs + - docusaurus +image: https://i.imgur.com/mErPwqL.png +slug: /myDoc +--- + diff --git a/utils/generateSidebar.js b/utils/generateSidebar.js new file mode 100644 index 0000000..0e03909 --- /dev/null +++ b/utils/generateSidebar.js @@ -0,0 +1,115 @@ +// +// Generates a sidebar based on file structure and +// markdown frontmatter properties. +// +// --- +// title: My Cool Feature +// sidebar_label: Introduction +// --- +// +// sidebar_sort_order: the sort order of this page in the sidebar +// sidebar_label: the link text to show for this page +// +// To determine the name of categories and their sort order, +// we look in the frontmatter of the first child page (after sorting) for +// the following properties: +// +// sidebar_category: the name of the category +// sidebar_category_order: the sort order of the category +// + +const fs = require('fs'); +const path = require('path'); + +const isMarkdown = /\.md$/i; + +// TODO: use a more efficient way to achieve this +function findInFrontMatter(contents, property) { + const regMatch = new RegExp(`^${property}:\\s+(.*?)$`, 'i'); + let frontmatter; + let value = contents.split('\n').find((line, i) => { + if (line === '---') { + frontmatter = !frontmatter; + } else if (frontmatter) { + return line.indexOf(`${property}: `) === 0; + } + return false; + }); + + return value ? value.match(regMatch)[1] : null; +} + +function generateSidebar({ baseDir, sourceDir, ignoreDirectories = '' }) { + ignoreDirectories = '(' + ignoreDirectories.replace(',', '|') + ')'; + const ignoreDirectoriesRegex = new RegExp(ignoreDirectories); + const searchIn = path.join(baseDir, sourceDir); + + const files = fs.readdirSync(searchIn, { withFileTypes: true }); + + const items = files + .sort() + .map((dirent) => { + const { name } = dirent; + const filePath = path.join(sourceDir, name); + const ignoreDirectory = sourceDir.match(ignoreDirectoriesRegex); + + if (dirent.isDirectory() && !ignoreDirectory) { + const items = generateSidebar({ + baseDir, + sourceDir: filePath, + ignoreDirectories, + }); + const introItem = items.find((item) => typeof item === 'string'); + + let label; + let sortOrder; + + if (introItem) { + const contents = fs.readFileSync(path.join(searchIn, `${introItem}.md`), 'utf8'); + + label = findInFrontMatter(contents, 'sidebar_category'); + sortOrder = findInFrontMatter(contents, 'sidebar_category_order'); + } + + return { + type: 'category', + label: label || name, + sortOrder: sortOrder ? Number(sortOrder) : Infinity, + items, + }; + } + + if (!filePath.match(isMarkdown)) { + return; + } + + const contents = fs.readFileSync(path.join(searchIn, name), 'utf8'); + let sortOrder = findInFrontMatter(contents, 'sidebar_sort_order'); + sortOrder = sortOrder ? Number(sortOrder) : Infinity; + + const fileId = filePath.replace(isMarkdown, ''); + + return { + type: 'doc', + id: fileId, + sortOrder, + }; + }) + .filter((i) => !!i) + .sort((a, b) => { + if (a.sortOrder != null && b.sortOrder != null) { + return a.sortOrder - b.sortOrder; + } + + if ((a.sortOrder != null) & (b.sortOrder == null)) { + return -1; + } + return 1; + }); + + // remove additional sidebar properties not supported + // by docusaurus to avoid errors and warnings. + return items.map(({ id, sortOrder, ...item }) => id || item); +} + +module.exports = generateSidebar;