diff --git a/.circleci/config.yml b/.circleci/config.yml index 1c74c378..41d4ba0d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2.1 jobs: build: docker: - - image: circleci/ruby:2.7.1 + - image: circleci/ruby:2.7.2 environment: # fix encoding - LANG: C.UTF-8 diff --git a/.github/actions/merge-template/action.yml b/.github/actions/merge-template/action.yml deleted file mode 100644 index 66f72567..00000000 --- a/.github/actions/merge-template/action.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: "Merge guide template" -description: "Merge upstream changes from the base 18F guide template" - -# To avoid merge conflicts, use a strategy of first adopting all changes from -# the upstream template, then reverting files and directories mangaged by the -# the downstream guide. -# Note: GitHub Actions do not execute with `workflows` permission; any workflow -# updates that should be reflected in downstream guides must be manually merged. -runs: - using: "composite" - steps: - - run: | - git config user.name github-actions - git config user.email github-actions@github.com - git remote add -f upstream "https://github.com/18F/isildurs-bane.git" - git merge --squash --strategy-option=theirs --allow-unrelated-histories upstream/main - git restore --source=HEAD --staged --worktree -- _guide - git restore --source=HEAD --staged --worktree -- README.md - git restore --source=HEAD --staged --worktree -- .github/workflows - REMOTE_SHA=`git rev-parse upstream/main` - git diff-index --quiet --cached HEAD -- || \ - git commit -m "Merging in 18F/isildurs-bane guide template" -m "18F/isildurs-bane@$REMOTE_SHA" - git push - shell: bash diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 727063bc..00000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Daily Sync -on: - schedule: - - cron: "11 7 * * *" # Arbitrary time outside continental US office hours - workflow_dispatch: - -jobs: - merge-template: - if: ${{ github.repository != '18F/isildurs-bane' }} - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: Merge Template - uses: ./.github/actions/merge-template diff --git a/.github/workflows/pa11y.yml b/.github/workflows/pa11y.yml new file mode 100644 index 00000000..b7d388fe --- /dev/null +++ b/.github/workflows/pa11y.yml @@ -0,0 +1,55 @@ +# Pulled from Daniel Mundra's blog post https://accessibility.civicactions.com/posts/automated-accessibility-testing-leveraging-github-actions-and-pa11y-ci-with-axe +name: pa11y tests + +on: [pull_request] + +jobs: + build: + name: Building site and running pa11y-ci tests + runs-on: ubuntu-latest + + steps: + - name: Checkout source. + uses: actions/checkout@v2 + + - name: Install jekyll site dependencies. + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.7.2 + bundler-cache: true + + - name: Install pa11y-ci dependencies. + run: npm install + + - name: Start up jekyll server. + run: npm run start-detached + + - name: Run pa11y-ci. + run: npm run pa11y-ci:sitemap 2>&1 | tee pa11y_output.txt + + - name: Read pa11y_output file. + id: pa11y_output + uses: juliangruber/read-file-action@v1 + with: + path: ./pa11y_output.txt + + - name: Comment on pull request. + uses: thollander/actions-comment-pull-request@main + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + message: '
Pa11y testing results + + +```${{ steps.pa11y_output.outputs.content }}``` + +
' + + # A defect in pa11y is causing intermitent page crashes [1]. Until it is + # fixed, if a page crashes during a scan, do not mark the pa11y scan as + # failed. + # [1] https://github.com/pa11y/pa11y-ci/issues/128 + - name: Check for pa11y failures. + if: "${{ contains(steps.pa11y_output.outputs.content, 'errno 2') && !contains(steps.pa11y_output.outputs.content, 'UnhandledPromiseRejectionWarning: Error: Page crashed!') }}" + run: | + echo "::error::The site is failing accessibility tests. Please review the comment in the pull request or the pa11y-ci step in the workflow for details." + exit 1 diff --git a/.pa11yci b/.pa11yci new file mode 100644 index 00000000..0f8b0371 --- /dev/null +++ b/.pa11yci @@ -0,0 +1,7 @@ +{ + "defaults": { + "concurrency": 4, + "standard": "WCAG2AA", + "runners": ["axe"] + } +} \ No newline at end of file diff --git a/.ruby-version b/.ruby-version index 860487ca..37c2961c 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.7.1 +2.7.2 diff --git a/Dockerfile b/Dockerfile index 0c2cb34c..0d0d07e7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ruby:2.7.1 +FROM ruby:2.7.2 WORKDIR /usr/src/app diff --git a/Gemfile b/Gemfile index c56a44ae..9cd887c9 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,6 @@ source 'https://rubygems.org/' -ruby '2.7.1' +ruby '2.7.2' gem 'jekyll' gem 'mini_racer' @@ -8,7 +8,7 @@ gem 'mini_racer' # If you put them in a jekyll_plugins group they’ll automatically be required into Jekyll # One of 3 ways to load plug-ins, don't need to do both group :jekyll_plugins do - gem 'uswds-jekyll', '~> 5.0' + gem 'uswds-jekyll', '~> 5.3' gem 'jekyll-redirect-from' gem 'jekyll-sitemap' gem 'jemoji', '>= 0.12.0' diff --git a/Gemfile.lock b/Gemfile.lock index f29b97ec..0eab3a84 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,18 +1,17 @@ GEM remote: https://rubygems.org/ specs: - activesupport (6.0.3.3) + activesupport (7.0.7.2) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - zeitwerk (~> 2.2, >= 2.2.2) - addressable (2.7.0) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) autoprefixer-rails (9.8.6.5) execjs colorator (1.1.0) - concurrent-ruby (1.1.7) + concurrent-ruby (1.2.2) em-websocket (0.5.2) eventmachine (>= 0.12.9) http_parser.rb (~> 0.6.0) @@ -20,13 +19,13 @@ GEM ffi (>= 1.3.0) eventmachine (1.2.7) execjs (2.7.0) - ffi (1.13.1) + ffi (1.14.2) forwardable-extended (2.6.0) gemoji (3.0.1) - html-pipeline (2.14.0) + html-pipeline (2.14.2) activesupport (>= 2) nokogiri (>= 1.4) - html-proofer (3.17.3) + html-proofer (3.18.8) addressable (~> 2.3) mercenary (~> 0.3) nokogumbo (~> 2.0) @@ -35,23 +34,23 @@ GEM typhoeus (~> 1.3) yell (~> 2.0) http_parser.rb (0.6.0) - i18n (1.8.5) + i18n (1.14.1) concurrent-ruby (~> 1.0) - jekyll (4.1.1) + jekyll (4.2.0) addressable (~> 2.4) colorator (~> 1.0) em-websocket (~> 0.5) i18n (~> 1.0) jekyll-sass-converter (~> 2.0) jekyll-watch (~> 2.0) - kramdown (~> 2.1) + kramdown (~> 2.3) kramdown-parser-gfm (~> 1.0) liquid (~> 4.0) mercenary (~> 0.4.0) pathutil (~> 0.9) rouge (~> 3.0) safe_yaml (~> 1.0) - terminal-table (~> 1.8) + terminal-table (~> 2.0) jekyll-autoprefixer (1.0.2) autoprefixer-rails (~> 9.3) jekyll-last-modified-at (1.3.0) @@ -69,22 +68,23 @@ GEM gemoji (~> 3.0) html-pipeline (~> 2.2) jekyll (>= 3.0, < 5.0) - kramdown (2.3.0) + kramdown (2.3.1) rexml kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) libv8 (8.4.255.0) liquid (4.0.3) - listen (3.2.1) + listen (3.4.1) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) mercenary (0.4.0) - mini_portile2 (2.4.0) + mini_portile2 (2.8.1) mini_racer (0.3.1) libv8 (~> 8.4.255) - minitest (5.14.2) - nokogiri (1.10.10) - mini_portile2 (~> 2.4.0) + minitest (5.19.0) + nokogiri (1.14.3) + mini_portile2 (~> 2.8.0) + racc (~> 1.4) nokogumbo (2.0.4) nokogiri (~> 1.8, >= 1.8.4) parallel (1.20.1) @@ -92,29 +92,29 @@ GEM forwardable-extended (~> 2.6) posix-spawn (0.3.15) public_suffix (4.0.6) + racc (1.6.2) rainbow (3.0.0) - rake (13.0.1) + rake (13.0.3) rb-fsevent (0.10.4) rb-inotify (0.10.1) ffi (~> 1.0) - rexml (3.2.4) - rouge (3.23.0) + rexml (3.2.5) + rouge (3.26.0) safe_yaml (1.0.5) sassc (2.4.0) ffi (~> 1.9) - terminal-table (1.8.0) + terminal-table (2.0.0) unicode-display_width (~> 1.1, >= 1.1.1) - thread_safe (0.3.6) typhoeus (1.4.0) ethon (>= 0.9.0) - tzinfo (1.2.7) - thread_safe (~> 0.1) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) unicode-display_width (1.7.0) - uswds-jekyll (5.2.0) + uswds-jekyll (5.3.0) jekyll (>= 4.0, < 5) jekyll-autoprefixer + mini_racer yell (2.2.2) - zeitwerk (2.4.0) PLATFORMS ruby @@ -128,10 +128,10 @@ DEPENDENCIES jemoji (>= 0.12.0) mini_racer rake - uswds-jekyll (~> 5.0) + uswds-jekyll (~> 5.3) RUBY VERSION - ruby 2.7.1p83 + ruby 2.7.2p137 BUNDLED WITH 2.1.4 diff --git a/README.md b/README.md index 8c64a43a..dca513f0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +**⚠️ This guide has moved to the [consolidated 18F guides repository](https://github.com/18F/guides).** + # Technology Transformation Services (TTS) Engineering Practices [TTS](https://www.gsa.gov/about-us/organization/federal-acquisition-service/technology-transformation-services) offices and programs — including [18F](https://18f.gsa.gov), [Centers of Excellence](https://coe.gsa.gov) (CoE), [Presidential Innovation Fellows](https://presidentialinnovationfellows.gov) (PIF), and [Solutions](https://www.gsa.gov/about-us/organization/federal-acquisition-service/technology-transformation-services/tts-solutions) — promote team best practices across specialty areas through guilds. These guilds support their members in whatever way deemed most appropriate by those members themselves. @@ -7,7 +9,7 @@ This repo is where the TTS Engineering Practices Guild keeps its guide to best p ## Quicklinks - Published guide: [engineering.18f.gov](https://engineering.18f.gov) -- Raw content: [_guide/_pages](_guide/_pages) +- Content: [_pages](_pages) - [CONTRIBUTING.md](CONTRIBUTING.md) on how to build this guide locally and submitting PRs/issues. ## Our mission @@ -24,9 +26,9 @@ We use issues in this repo to track work. If you'd like to suggest a new topic o The software development industry is ever-changing, and our guide is a living document. Please suggest edits or changes via pull request. -## Development +Getting new practices into the guide is pretty light on process. Feel free to raise a topic in Slack or at a guild meeting and drive to some consensus. Once you've done that, document your findings, submit a PR, and ask in #dev for a quick review. If you think a proposal might be controversial after getting some consensus prior, please post the draft PR to #dev (and elsewhere if you don’t think target audience is in that channel) and solicit feedback. -This site uses the [18F/isildurs-bane](https://github.com/18F/isildurs-bane) template, which manges all the content outside of [_guide](_guide) directory. Submit pull requests against that repository to effect those files. Only files under [_guide](_guide) should be modified and maintained here. +## Development To run the site locally, we recommend using: - [`git`](https://git-scm.com) @@ -45,6 +47,20 @@ To run the site locally, we recommend using: 1. Open http://localhost:4000 + +To check if the links referenced in the site content are valid, run: + + ```sh + docker-compose run web bundle exec rake test + ``` + +To only check internal links, run: + ```sh + docker-compose run web bundle exec rake ci_test + ``` + +Note that the automated CircleCI integration process will only check internal links, as many websites will generate spurious errors. + ## Public domain This project is in the worldwide [public domain](LICENSE.md). As stated in [CONTRIBUTING](CONTRIBUTING.md): diff --git a/_config.yml b/_config.yml index 917f7a56..e03cd5ee 100644 --- a/_config.yml +++ b/_config.yml @@ -7,19 +7,13 @@ exclude: - Gemfile.lock - LICENSE.md - README.md - - override.yml + - node_modules permalink: pretty sass: style: :compressed -google_analytics_ua: UA-48605964-19 -dap_agency: GSA -dap_subagency: TTS - -collections_dir: _guide - collections: pages: output: true @@ -35,3 +29,17 @@ scripts: - /assets/uswds/js/uswds.min.js - /assets/js/private-eye.js - /assets/js/application.js + +title: TTS Engineering Practices Guide +description: A set of guidelines and best practices for an awesome engineering team +url: "https://engineering.18f.gov/" +search_site_handle: engineering.18f.gov + +google_analytics_ua: UA-48605964-19 +dap_agency: GSA +dap_subagency: TTS + +github_info: + organization: 18F + repository: development-guide + default_branch: main diff --git a/_data/header.yml b/_data/header.yml index 994bd3bc..43224801 100644 --- a/_data/header.yml +++ b/_data/header.yml @@ -1,2 +1,4 @@ usa_banner: true type: extended +primary: + links: primary diff --git a/_data/navigation.yml b/_data/navigation.yml index ddbf65cf..9014ea02 100644 --- a/_data/navigation.yml +++ b/_data/navigation.yml @@ -1 +1,105 @@ -sidenav-breakpoint: 'desktop' +primary: + - text: About this guide + href: /about + name: about + - text: Our approach + href: /workflow/ + name: approach + - text: Tools + href: /integrations/ + name: tools + - text: Languages & Runtimes + href: /language-selection/ + name: languages + - text: Security + href: /security/ + name: security + +about: + - text: About this guide + href: /about + - text: License + href: /license/ + - text: Resources + href: /resources/ + +approach: + - text: Our approach + href: /workflow/ + - text: Feedback + href: /people/ + - text: Code Review + href: /code-review/ + - text: Development Environments + href: /development-environments/ + - text: On-Call + href: /on-call/ + - text: Incident Reports + href: /incident-reports/ + - text: Architecture Reviews + href: /architecture-reviews/ + - text: Front-End Disciplines + href: /frontend/ + - text: APIs + href: /apis/ + - text: Release Strategies + href: /release-strategies/ + - text: Example Workflows + href: /example-workflows/ + +tools: + - text: Tools + href: /integrations/ + - text: Laptop Setup + href: /laptop-setup/ + - text: Project Setup + href: /project-setup/ + - text: Docker for Development + href: /docker/ + - text: Browser Testing + href: /browser-testing/ + - text: Automated Testing + href: /tests/ + - text: Accessibility Scanning + href: /accessibility-scanning/ + - text: Continuous Deployment + href: /continuous-deployment/ + - text: Datastore Selection + href: /datastore-selection/ + - text: Choosing a Web App Architecture + href: /web-architecture/ + - text: SharePoint Primer + href: /sharepoint/ + - text: Books we've read + href: /books-we-have-read/ + +languages: + - text: Languages & Runtimes + href: /language-selection/ + - text: JavaScript + href: /javascript/ + - text: Markdown + href: /markdown/ + - text: Node.js + href: /nodejs/ + - text: Python + href: /python/ + - text: Ruby + href: /ruby/ + - text: CSS + href: /css/ + +# TODO: figure out how to nest links +security: + - text: Security + href: /security/ + - text: Content Security Policy (CSP) + href: /security/content-security-policy/ + - text: Output Encoding + href: /security/output-encoding/ + - text: Vulnerable dependency remediation + href: /security/dependency-remediation/ + - text: Cloud Services + href: /security/cloud-services/ + - text: Incident Response Drills + href: /security/incident-response-drills/ diff --git a/_data/orgs/18F/anchor.yml b/_data/orgs/18F/anchor.yml deleted file mode 100644 index 72b2b125..00000000 --- a/_data/orgs/18F/anchor.yml +++ /dev/null @@ -1,5 +0,0 @@ -site_email: 18F@gsa.gov -org_secondary: 18F -org_secondary_logo: 18f-logo-blue.svg -org_secondary_url: https://18f.gsa.gov -org_secondary_bio: "18F partners with agencies to improve the user experience of government services by helping them build and buy technology." diff --git a/_data/orgs/CoE/anchor.yml b/_data/orgs/CoE/anchor.yml deleted file mode 100644 index 4580e8bf..00000000 --- a/_data/orgs/CoE/anchor.yml +++ /dev/null @@ -1,5 +0,0 @@ -site_email: connectcoe@gsa.gov -org_secondary: the Centers of Excellence -org_secondary_logo: coe-logomark.svg -org_secondary_url: https://coe.gsa.gov -org_secondary_bio: "The Centers of Excellence (CoE) accelerate IT modernization by leveraging private sector innovation and government services while centralizing best practices and expertise." diff --git a/_data/orgs/PIF/anchor.yml b/_data/orgs/PIF/anchor.yml deleted file mode 100644 index 44de2af2..00000000 --- a/_data/orgs/PIF/anchor.yml +++ /dev/null @@ -1,5 +0,0 @@ -site_email: pif-team@gsa.gov -org_secondary: the Presidential Innovation Fellows -org_secondary_logo: pif.png -org_secondary_url: https://presidentialinnovationfellows.gov -org_secondary_bio: "The Presidential Innovation Fellows (PIF) program brings the principles, values, and practices of the innovation economy into government through the most effective agents of change we know: our people. This highly-competitive program pairs talented, diverse technologists and innovators with top civil-servants and change-makers working at the highest levels of the federal government to tackle some our nation’s biggest challenges." diff --git a/_data/orgs/Solutions/anchor.yml b/_data/orgs/Solutions/anchor.yml deleted file mode 100644 index e872ef93..00000000 --- a/_data/orgs/Solutions/anchor.yml +++ /dev/null @@ -1,5 +0,0 @@ -site_email: tts-info@gsa.gov -org_secondary: TTS Solutions -org_secondary_logo: -org_secondary_url: https://www.gsa.gov/about-us/organization/federal-acquisition-service/technology-transformation-services/tts-solutions -org_secondary_bio: "TTS Solutions helps agencies improve delivery of information and services to the public. Our primary focus areas align with larger administration priorities, including: Data and Analytics, Innovation, Public Experience, Secure Cloud, Smarter IT, Cloud.gov, Login.gov, and Free and Low-Cost Tools." diff --git a/_data/anchor.yml b/_data/usa_identifier.yml similarity index 59% rename from _data/anchor.yml rename to _data/usa_identifier.yml index d181b154..c051204f 100644 --- a/_data/anchor.yml +++ b/_data/usa_identifier.yml @@ -1,15 +1,31 @@ -site_email: tts-info@gsa.gov +site_name: TTS Engineering Practices Guide +site_email: 18F@gsa.gov +site_url: https://engineering.18f.gov +site_about: https://engineering.18f.gov agency: U.S. General Services Administration agency_acronym: GSA agency_logo: gsa-logo-blue.svg agency_url: https://www.gsa.gov agency_about_url: https://www.gsa.gov/about org_primary: Technology Transformation Services +org_primary_acronym: TTS org_primary_url: https://www.gsa.gov/tts/ +org_primary_email: tts-info@gsa.gov +org_primary_about: https://www.gsa.gov/tts/ org_primary_bio: "As part of GSA’s Technology Transformation Services (TTS), we apply modern methodologies and technologies to improve the public’s experience with government. We help agencies make their services more accessible, efficient, and effective with modern applications, platforms, processes, personnel, and software solutions." +org_secondary: Technology Transformation Services +org_secondary_acronym: TTS +org_secondary_logo: 18f-logo-blue.svg +org_secondary_url: https://18f.gsa.gov +org_secondary_email: 18F@gsa.gov +org_secondary_about: https://18f.gsa.gov/about/ +org_secondary_bio: "TTS Solutions is a portfolio of products and services that help agencies improve delivery of information and services to the public." foia_request_url: "https://www.gsa.gov/reference/freedom-of-information-act-foia" fraud_waste_abuse_url: "https://www.gsaig.gov/" no_fear_act_url: "https://www.gsa.gov/about-us/organization/office-of-civil-rights/notification-and-federal-employee-antidiscrimination-and-retaliation-act-of-2002" budget_performance_url: "https://www.gsa.gov/reference/reports/budget-performance" accessibility_url: "https://www.gsa.gov/website-information/accessibility-aids" usagov_contact_url: "https://www.usa.gov/contact" +edit_page: + - text: "Edit this page" +privacy_policy_url: "https://www.gsa.gov/website-information/website-policies" diff --git a/_guide/_config.yml b/_guide/_config.yml deleted file mode 100644 index 3baa54d2..00000000 --- a/_guide/_config.yml +++ /dev/null @@ -1,26 +0,0 @@ -# Configuration in this file overrides those in _config.yml. -# Required keys: -# - title -# - description -# - url -# - github_info -# - search_site_handle -# Optional keys -# - org - -title: TTS Engineering Practices Guide -description: A set of guidelines and best practices for an awesome engineering team -url: "https://engineering.18f.gov/" - -# GitHub information -github_info: - organization: 18F - repository: development-guide - default_branch: main - -# Unique identifier across GSA for this website; the repository name is -# usually a good site handle. -search_site_handle: engineering.18f.gov - -# Either 18F, Solutions, CoE, PIF, or unset to default to just TTS -org: diff --git a/_guide/_data/anchor.yml b/_guide/_data/anchor.yml deleted file mode 100644 index 32dbbe75..00000000 --- a/_guide/_data/anchor.yml +++ /dev/null @@ -1,2 +0,0 @@ -edit_page: - text: "Edit this page" diff --git a/_guide/_data/header.yml b/_guide/_data/header.yml deleted file mode 100644 index 64eefee8..00000000 --- a/_guide/_data/header.yml +++ /dev/null @@ -1,2 +0,0 @@ -primary: - links: primary diff --git a/_guide/_data/navigation.yml b/_guide/_data/navigation.yml deleted file mode 100644 index 1a2426f0..00000000 --- a/_guide/_data/navigation.yml +++ /dev/null @@ -1,112 +0,0 @@ -primary: - - text: About this guide - href: / - - text: Our approach - href: /workflow/ - - text: Tools - href: /integrations/ - - text: Languages & Runtimes - href: /language-selection/ - - text: Security - href: /security/ - -about: - - text: About this guide - href: / - - text: License - href: /license/ - - text: Resources - href: /resources/ - -approach: - - text: Our approach - href: /workflow/ - - text: Feedback - href: /people/ - - text: Code Review - href: /code-review/ - - text: Development Environments - href: /development-environments/ - - text: Incident Reports - href: /incident-reports/ - - text: Architecture Reviews - href: /architecture-reviews/ - -tools: - - text: Tools - href: /integrations/ - - text: Laptop Setup - href: /laptop-setup - - text: Project Setup - href: /project-setup/ - - text: Browser Testing - href: /browser-testing/ - - text: Accessibility Scanning - href: /accessibility-scanning/ - - text: Continuous Deployment - href: /continuous-deployment/ - - text: Datastore Selection - href: /datastore-selection/ - - text: SharePoint Primer - href: /sharepoint/ - -languages: - - text: Languages & Runtimes - href: /language-selection/ - - text: JavaScript - href: /javascript/ - - text: Node.js - href: /nodejs/ - - text: Python - href: /python/ - - text: Ruby - href: /ruby/ - - text: CSS - href: /css/ - -# TODO: figure out how to nest links -css: - - text: CSS - href: /css/ - - text: Architecture - href: /css/architecture/ - - text: Documentation - href: /css/documentation/ - - text: Frameworks - href: /css/frameworks/ - - text: Formatting - href: /css/formatting/ - - text: Inheritance - href: /css/inheritance/ - - text: Linting - href: /css/linting/ - - text: Naming - href: /css/naming/ - - text: Preprocessors - href: /css/preprocessors/ - - text: Specificity - href: /css/specificity/ - - text: Units - href: /css/units/ - - text: Variables - href: /css/variables/ - -# TODO: figure out how to nest links -js: - - text: JavaScript - href: /javascript/ - - text: Dependencies - href: /javascript/dependencies/ - - text: Frameworks - href: /javascript/frameworks/ - - text: Style / Linting - href: /javascript/style/ - -# TODO: figure out how to nest links -security: - - text: Security - href: /security/ - - text: Content Security Policy (CSP) - href: /security/content-security-policy/ - - text: Output Encoding - href: /security/output-encoding/ diff --git a/_guide/_pages/accessibility-scanning.md b/_guide/_pages/accessibility-scanning.md deleted file mode 100644 index a1c780d8..00000000 --- a/_guide/_pages/accessibility-scanning.md +++ /dev/null @@ -1,205 +0,0 @@ ---- -title: Accessibility Scanning -sidenav: tools -sticky_sidenav: true ---- - -## Accessibility Scanning using AccessLint - -[AccessLintCI](https://github.com/accesslint/accesslint-ci) is an automated accessibility scanning tool. It is configured with CircleCI (Travis and Jenkins support pending) to leave comments on Pull Requests stating potential accessibility problems with the committed code. - -### Getting started - -Regardless of what framework your project is using, you will need to add `gem: accesslint-ci` to your `Gemfile` with the gem. - -### Setup with Jekyll - -The setup is detailed [here](https://github.com/accesslint/accesslint-ci#installation) for Rails, but can also easily be configured with Jekyll sites as follows. In the `circle.yml` file of your repo add the following: - -```yml -general: - artifacts: - - "tmp" - -machine: - environment: - ACCESSLINT_MASTER_BRANCH: - node: - version: 6.1.0 - -dependencies: - pre: - - gem install bundler - - bundle install - override: - - npm install -g accesslint-cli - - gem install accesslint-ci - -test: - post: - - bundle exec jekyll serve --detach - - accesslint-ci scan http://localhost:4000 -``` - -The `ACCESSLINT_MASTER_BRANCH` should be set to the branch that PRs are being made to. If it is not set, it will default to `master`. For TTS repos, this will generally be `dev` or `development`. - -### Accesslint API access - -In order for AccessLint to access your GitHub webhooks, you will need to - -1. [Create an token](https://accesslint.com/) -1. Reference it. In your Circle CI settings for your repo, create a variable named `ACCESSLINT_API_TOKEN` with the token you created. -1. Also add a variable named `ACCESSLINT_GITHUB_USER` to your Circle CI repo settings, with a value of the GitHub username that was used to create the token in step 1. - -### Configuring other project frameworks - -If your project is not a Rails or Jekyll project, you can still use AccessLintCI! - -To do so, make a few changes to the `post` section of your configuration. Replace `bundle exec jekyll serve --detach` with a repo-specific server command that detaches, and allows accesslint-ci to run on the same process to check your server port. - -```yml -test: - post: - - - - accesslint-ci scan http://localhost: -``` - -### What it does - -Once configured, AccessLintCI will leave a single comment on a Pull Request to the `ACCESSLINT_MASTER_BRANCH`. If errors are accepted, they will be cached, and not checked again in the next PR to that branch. - -## Accessibility Scanning Using Pa11y-ci - -### Introduction - -Building a website or application that is easy accessible toeveryone is not only an important of the user experience, but also a requirement of all federally funded projects. GSA provides a helpful [Section 508](https://section508.gov) portal. [Pa11y](https://github.com/pa11y/pa11y) is an automation tool that helps you scan your static web pages to check for accessibility problems and errors. It can be setup on your machine locally or remotely using a CI tool. - -## Running Pa11y locally - -### Installation and setup (For MacOS) - -1. [Concourse CI](https://concourse.ci/index.html) allows you to run multiple compliance scanning jobs on your machine using a virtual machine. It is highly recommended to go through its [excellent documentation and "Hello World" tutorial ](https://concourse.ci/hello-world.html) before writing custom jobs for your project. - -2. If you want to run locally Pa11y-ci you will need to : - - * [install **vagrant** and **virtualbox** ](http://sourabhbajaj.com/mac-setup/Vagrant/README.html) - * use [The Fly CLI](https://concourse.ci/fly-cli.html) , a command line tool for Concourse which is used for a number of tasks from connecting to a shell in one of your build's containers to uploading new pipeline configuration into a running Concourse. - -3. If you're on MacOS , you will have to `chmod +x` the downloaded binary and put it in your `$PATH`. This can be done in one fell swoop with `install path/to/fly /usr/local/bin/fly` - -4. Run Vagrant - - ```sh - vagrant init concourse/lite # creates ./Vagrantfile - vagrant up # downloads the box and spins up the VM - ``` - -5. Log into fly - - `fly -t lite login -c http://192.168.100.4:8080` - - ​ - -### Running Pa11y-ci on your local machine - - 1. Create a `.yml` file containing the job with tasks that you want to run - - `touch accessibility-scan.yml` - - `vim accessibility-scan.yml` - ```yml - jobs: - - name: accessibility-scan - plan: - - task: run-pa11y - config: - platform: linux - image_resource: - type: docker-image - source: - repository: node - run: - path: sh - args: - - -exc - - | - npm install -g pa11y-ci - npm install -g phantomjs - mkdir accessibility-scan - pa11y-ci --json --sitemap https://18f.gsa.gov/sitemap.xml > accessibility-scan/summary.txt - cat accessibility-scan/summary.txt - ``` - - `type` is almost always going to be `docker-image` . `pa11y-ci` requires node, so we are using a `node` docker-image. - - `run` section contains a series of shell command that we are executing: - - * install `pa11y-ci` and `phantomjs` from the node package manager(`npm`) - - * making a directory and telling pa11y-ci to pipe the results of the scan into a `json` file - - the command is like so `pa11y-ci --json --sitemap https://[18f-static-site-url]/sitemap.xml > dir/file` - - * printing the results in our CLI `cat…` (for debugging purposes, optional) - - **Note that** we are using the `sitemap.xml` file instead of individual files(much more efficient) - - - 2. Run - - ```shell - fly -t lite set-pipeline -p accessibility-scan -c accessibility-scan.yml - ``` - - 3. Go to the `URL` displayed on your CLI. **Click the plus sign on top right corner and toggle side bar and press play on your pipeline**. Pipelines are posed by default. - - ​ - -## Running Pa11y-ci with CI - -### Circle CI Setup Instructions - -If you want to run Pa11y-ci per pull request on your project: - -1. Create a bash file `accessibility-scan.sh` in your project home directory to tell it to run either on a circleci supported branch or your localhost - - ```shell - if [[ -n $CIRCLE_BRANCH ]]; then - - echo "scanning site using sitemap from 18F/${CIRCLE_BRANCH}" - - pa11y-ci --sitemap https://federalist.18f.gov/preview/18F/18f.gsa.gov/${CIRCLE_BRANCH}/sitemap.xml - - else - - echo "scanning site using localhost sitemap" - pa11y-ci --sitemap http://localhost:4000/sitemap.xml - ``` - -2. Modify your `circle.yml` to add pa11y-ci - - ​ - - ```yaml - machine: - ruby: - version: - 2.2.3 - - dependencies: - pre: - - [Your-other-commands] - - nvm install stable && nvm alias default stable - - npm test - - npm install -g pa11y-ci - test: - pre: - - bundle exec htmlproofer _site --disable-external --allow-hash-href --empty-alt-ignore --url-ignore 18f@gsa.gov - - echo CIRCLE_BRANCH - - echo - - npm run --harmony accessibility-scan - ``` - -### Travis CI Setup Instructions(To Be Written) - -## Adding Pa11y To The Compliance Viewer(To Be Written) diff --git a/_guide/_pages/architecture-reviews.md b/_guide/_pages/architecture-reviews.md deleted file mode 100644 index 3b593a32..00000000 --- a/_guide/_pages/architecture-reviews.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Architecture Reviews -sidenav: approach -sticky_sidenav: true ---- - -Though we pride ourselves on our [transparent and remote-friendly -workplace](https://18f.gsa.gov/2015/10/15/best-practices-for-distributed-teams/), -our project focus tends to silo engineers from each other. We can kick-start -knowledge transfer by highlighting some of the more interesting design -decisions from existing projects. - -## Projects - -- [DATA Act Pilot: Simplicity is Key]({{site.baseurl}}/architecture-reviews/data-act-pilot) (2016) -- [Micro-purchase: Do one thing well]({{site.baseurl}}/architecture-reviews/micro-purchase) (2016) diff --git a/_guide/_pages/css.md b/_guide/_pages/css.md deleted file mode 100644 index f537fa48..00000000 --- a/_guide/_pages/css.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: CSS -sidenav: css -sticky_sidenav: true ---- - -The purpose of the CSS coding styleguide is to create consistent CSS or -preprocessor CSS code across TTS. The styleguide should be treated as a guide -— rules can be modified according to project needs. diff --git a/_guide/_pages/css/architecture.md b/_guide/_pages/css/architecture.md deleted file mode 100644 index 19f7be3d..00000000 --- a/_guide/_pages/css/architecture.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: Architecture -sidenav: css -sticky_sidenav: true ---- - -A site's architecture should be based on its goals and purposes. This means the -guidance here should be adapted to different sites and situations. - -## Modular or component architecture -When using a modular or component architecture, every page is broken into a -series of modular components. There are two sets of these components: -`components` and `modules`. The architecture starts out with basic HTML element -rules: HTML, p, a, form, etc tags that than have components and modules written -on top of them. Components are very basic structure such as buttons, blurbs, -navs, and positioning structures like insets, island, and enclosure. From -here, modules are built with these components. This architecture also attempts -to keep the specificity trend in an upwards curve as you move down in the file -(more on this to come). - -- Start with an elements file for all tag rules (a, h1-h5, p, \*, html, body). -- Create component files for each structural element, such as buttons, navs, - etc. These are mainly class-based and use [BEM] or another naming scheme. -- Create more specific structure with modules. For instance, if the logo image - and text needs very specific treatment, use a module. - - Build modules from components through mixins, extends, and HTML. - - Modules can have higher specificity, it’s fine to use deeper nesting. -- Have an overrides file or folder comprised of global rules that are meant to - override components and modules. - - These can be generic utilities. - - A good thing to put here are breakpoint-specific rules, such as hiding - something at small breakpoints. - -### File structure -```sh -_elements.scss -_mixins.scss -_typography.scss -_util.scss -_vars.scss -component/_blurb.scss -component/_button.scss -component/_island.scss -component/_sub_nav.scss -module/_logo.scss -module/_progress_bar.scss -lib/bourbon.scss -lib/neat.scss -_overrides.scss -``` - -For the `util`, `typography`, `elements`, and `overrides` files, once they grow -too large (300 lines or more) in size, split them into their own folder with -sub files. - -```sh -elements/_all.scss -elements/_p.scss -elements/_h.scss -typography/_body.scss -typography/_links.scss -overrides/_breakpoints.scss -overrides/_util.scss -util/_center.scss -util/_clearfix.scss -``` - - -## Importing -As you likely know, CSS rules that are later in the file override earlier -rules. This means Sass imports can be used to control inheritance and -specificity. - -- Start with base elements. -- Move to single nested classes and utils. -- Move next to more specific classes, often with nesting. -- Move next to overrides, possibly with !important rules. -- Import alphabetically. -- Only modify import order for groups of files, not specific files. - -```scss -// Bad -@import 'https://github.com/module/logo'; -@import 'https://github.com/component/mask'; -@import 'https://github.com/component/button'; /* Has to be imported after "mask" */ - -// Good -@import 'https://github.com/component/button'; -@import 'https://github.com/component/mask'; -@import 'https://github.com/module/logo'; -``` - - -[BEM]: http://getbem.com/introduction/ diff --git a/_guide/_pages/css/documentation.md b/_guide/_pages/css/documentation.md deleted file mode 100644 index cfcb4a90..00000000 --- a/_guide/_pages/css/documentation.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Documentation -sidenav: css -sticky_sidenav: true ---- - -## Sass Comments -Be intentional when you use `//` (silent comments) versus `/* */` -(which are preserved in the CSS output). When in doubt, use `//`. - -## KSS -Use KSS for documentation. More information on KSS can be found on the -[official site](http://warpspire.com/kss/). - -### Example - -```scss -// Button -// -// Various buttons on the site. -// -// Markup -// -// Link -// -// .button-modified - A button with a different style. -// -// -// Styleguide component.button -.button { -} - -.button-modified { -} -``` - -### Rationale -KSS is the most common CSS documentation method to date. While it’s not perfect, -the generated documentation can be modified through templates. diff --git a/_guide/_pages/css/formatting.md b/_guide/_pages/css/formatting.md deleted file mode 100644 index 8fa800a7..00000000 --- a/_guide/_pages/css/formatting.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Formatting -sidenav: css -sticky_sidenav: true ---- - -We recommend using [Prettier](https://prettier.io), and enabling it in your -editor by default. Prettier is an automatic code formatter that will make your -code format consistent. This way we don't have to argue over how to format our -code - we just let the tools enforce something! Prettier works with both plain -CSS and SCSS. - -Do not use shorthand declarations unless you need to explicitly set all the -available values. - -```scss -// Bad -margin: inherit 3em; - -// Good -margin-bottom: 3em; -margin-top: 3em; - -margin: 3em 4em 2em 1em; -``` - -Avoid arbitrary numbers that are repeated, or linked, or dependent on other -parts of the code, (aka “magic numbers”). - -```scss -// Bad -.component { - top: 0.327em; -} - -// Better -/** - * 1. Magic number. This value is the lowest I could find to align the top of - * `.foo` with its parent. Ideally, we should fix it properly. - */ -.component { - top: 0.327em; -} - -// Good -$align_top: 100%; -.component { - top: $align_top; -} -``` - -## Order - -- Use the following ordering: - - 1. variables - 2. @extend directives - 3. @include directives - 4. declaration list (`property: name;`) - 5. media queries - 6. pseudo-states (`:checked`, `:target`, etc.) and pseudo-elements - (`::after`, `::selection`, etc.) - 7. nested elements - 8. nested classes - -- Use alphabetical order or type order for declarations. Pick one to keep the - whole project consistent. -- Place a new line before nested selectors unless they are after the first - selector. -- Treat nested includes, such as Neat's media includes – - `@include media($small-screen)` — as a standard media query, rather than a - Sass @include. So they would be sorted directly after the declaration list. -- Place mixin calls with `@content` after nested selectors. -- You may deviate the sorting order to better suit your project's needs, as - long as it's consistent throughout the project. - -```scss -// Bad -.module { - - .module-element { - color: #fff932; - } -} - -// Good -.module { - .module-element { - color: #fff932; - } -} - -// Good -.module { - $amount = 3; - @extend .component; - @include sizing($amount); - margin-top: $amount * 1em; - text-align: center; - - @include media($small-screen) { - margin-top: ($amount + 10em); - } - - &::before { - content: "hello"; - } - - .module__ele { - color: #fff932; - } -} -``` diff --git a/_guide/_pages/css/frameworks.md b/_guide/_pages/css/frameworks.md deleted file mode 100644 index 5fa6e717..00000000 --- a/_guide/_pages/css/frameworks.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Frameworks -sidenav: css -sticky_sidenav: true ---- - -TTS recommends using the [U.S. Web Design System (USWDS)](https://github.com/uswds/uswds) as it is specifically designed to help build fast, accessible, mobile-friendly federal government websites. - -Sometimes, projects utilize other CSS frameworks such as: - -1. [Bourbon](https://www.bourbon.io/) -2. [BassCSS](https://www.basscss.com/) - -These frameworks were chosen because they're relatively unopinionated about -design decisions while still providing the helpers that make frameworks -essential to fast and accurate frontend work, for example, solutions for -responsive design, grids, and common design patterns. In addition, both -frameworks, through modular design and excellent documentation, make it easy -for the designer or developer to only use the parts that they need, rather than -including a hefty library. - -## Do not use Bootstrap - -18F specifically does not recommend using [Bootstrap](http://getbootstrap.com/) for production work -because it can be difficult to adapt its opinionated styles to bespoke design work. diff --git a/_guide/_pages/css/inheritance.md b/_guide/_pages/css/inheritance.md deleted file mode 100644 index 8107e39e..00000000 --- a/_guide/_pages/css/inheritance.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Inheritance -sidenav: css -sticky_sidenav: true ---- - -## Mixins -- Use mixins for groups of properties that appear together intentionally and - are used multiple times. - - ```scss - @mixin clearfix { - &:after { - content: ''; - display: table; - clear: both; - } - } - ``` - -- Use mixins for components to change size. -- Use mixins when something requires parameters. - - ```scss - @mixin size($width, $height: $width) { - width: $width; - height: $height; - } - ``` - -- Do not use mixins for browser prefixes. Use [Autoprefixer](https://github.com/postcss/autoprefixer). - - ```scss - // Bad - @mixin transform($value) { - -webkit-transform: $value; - -moz-transform: $value; - transform: $value; - } - ``` - - -## Extend -Be very careful with using `@extend`. It's a powerful tool that can have -disastrous side-effects. Before using please consider: - -- Where is my current selector going to be appended? -- Am I likely to be causing undesired side-effects? -- How large is the CSS generated by this single extend? - -If you're unsure of using `@extend`, follow these rules to avoid running into -trouble: - -- Use `@extend` from within a module, not across different modules. -- Use `@extend` on [placeholders] exclusively, not on actual selectors. -- Make sure the placeholder you extend is present as little as possible in the - stylesheet. - -You can use [mixins] in place of selectors. While mixins will copy more code, -the difference will often be negligible once the output file has been gzipped. - -[mixins]: http://sass-lang.com/guide#mixins -[placeholders]: http://thesassway.com/intermediate/understanding-placeholder-selectors diff --git a/_guide/_pages/css/linting.md b/_guide/_pages/css/linting.md deleted file mode 100644 index f8d3ae14..00000000 --- a/_guide/_pages/css/linting.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Linting -sidenav: css -sticky_sidenav: true ---- - -The styleguide provides a method of linting [Sass] code to ensure it conforms -to the rules in the styleguide. This linting tool will go through all Sass code -and issue warnings wherever the code differs from the styleguide. We've created -a specific [`.scss-lint.yml` file][scss-lint yaml] that's configured to work -with the css coding styleguide. There are three ways to setup linting: - -* on GitHub with Hound -* locally with ruby -* locally with node - -## On GitHub with Hound -1. Go to [Hound](https://houndci.com/). -2. Sign in with GitHub. -3. Activate the respository through [Hound](https://houndci.com/repos). -4. Add the [`.scss-lint.yml` file][scss-lint yaml] to the base of your - repository. - -## Locally with ruby -1. Add the [`.scss-lint.yml` file][scss-lint yaml] to the base of your - repository. -2. Install the [scss-lint] gem with `gem install scss_lint` -3. Run scss-lint: `scss-lint app/assets/stylesheets/` - -## Locally with node (experimental!) -1. Run `npm install --save-dev @18f/stylelint-rules` to download the package and save it to your package.json -2. The package provides both a gulp task and a cli interface. Detailed usage instructions can be found in the [README](https://github.com/18F/stylelint-rules) - -## Shortcomings - -### scss-lint - -The scss-lint tool currently lacks the functionality to check these rules in -the CSS coding styleguide: - -- Does not limit line width to 80 characters -- Does not check for numeric calculations in parentheses -- Does not sort properties in quite the order we want (defaults to - alphabetical) - -### stylelint - -This tool is still being evaluated, so not every rule in our current styleguide -is supported by stylelint. scss-lint is purpose built for SCSS and is therefore -a bit more feature rich. The following rules are currently not supported: - -- PropertySpelling -- UnecessaryParentReference - -That being said, if you want to avoid a dependency on ruby in your project and -still benefit from reliable SCSS linting, please test out this tool! - - -[Sass]: http://sass-lang.com/ -[scss-lint]: https://github.com/brigade/scss-lint -[scss-lint yaml]: https://raw.githubusercontent.com/18F/frontend/18f-pages-staging/.scss-lint.yml -[stylelint-rules]: https://github.com/18F/stylelint-rules diff --git a/_guide/_pages/css/naming.md b/_guide/_pages/css/naming.md deleted file mode 100644 index 358e8967..00000000 --- a/_guide/_pages/css/naming.md +++ /dev/null @@ -1,201 +0,0 @@ ---- -title: Naming -sidenav: css -sticky_sidenav: true ---- - -- HTML elements should be in lowercase. - - ```scss - body, - div { - } - ``` - -- Classes should be lowercase. -- Avoid camelcase. -- Name things clearly. -- Write classes semantically. Name its function not its appearance. - - ```scss - // Bad - // Avoid uppercase - .ClassNAME { } - - // Avoid camel case - .commentForm { } - - // What is a c1-xr? Use a more explicit name. - .c1-xr { } - ``` - -- Avoid presentation- or location-specific words in names, as this will cause - problems when you (invariably) need to change the color, width, or feature - later. - - ```scss - // Bad - .blue - .text-gray - .100width-box - - // Good - .warning - .primary - .lg-box - ``` - -- Be wary of naming components based on content, as this limits the use of the - class. - - ```scss - // Danger zone - .product_list - - // Better - .item_list - ``` - -- Don't abbreviate unless it’s a well-known abbreviation. - - ```scss - // Bad - .bm-rd - - // Good - .block--lg - ``` - -- Use quotes in type pseudo selectors. - - ```scss - // Good - .top_image[type="text"] { - } - ``` - -- Name CSS components and modules with singular nouns. - - ```scss - .button { - } - ``` - -- Name modifiers and state-based rules with adjectives. - - ```scss - .is_hovered { - } - ``` - -- If your CSS has to interface with other CSS libraries, consider namespacing - every class. - - ```css - .f18-component - ``` - - -## Naming Methodologies - -When it comes to naming, the most important thing is consistency. The -recommended way to do this is using an existing methodology like [BEM](#bem), -or use a custom one that’s clearly defined. - -### BEM - -[BEM][BEM] (**B**lock, **E**lement, **M**odifier) structures CSS such that -every entity is composed of (you guessed it) blocks, elements and modifiers. -From [Harry Roberts][mindbemding]: - -> The point of BEM is to tell other developers more about what a piece of -> markup is doing from its name alone. By reading some HTML with some classes -> in, you can see how – if at all – the chunks are related; something might -> just be a component, something might be a child, or element, of that -> component, and something might be a variation or modifier of that component. - -TTS generally recommends using a modified BEM methodology outlined in the next -subsection. However, you might want to use standard BEM when: - -* You need a naming scheme that general CSS developers will already be familiar - with or an existing naming scheme hasn’t been consistent enough. -* When you want to use JavaScript to modify the BEM class names dynamically. - -Here is an example of BEM in SCSS: - -```scss -// block -.inset { - margin-left: 15%; - - // element - .inset__content { - padding: 3em; - } -} - -// modifier -.inset--sm { - margin-left: 10%; - - .inset__content { - padding: 1em; - } -} - -// modifier -.inset--lg { - margin-left: 20%; -} -``` - - -### Suggested custom methodology - -The TTS recommendation for a naming methodology is a modified version of BEM. -It still uses blocks, sections within blocks and modifiers, but with an -abbreviated syntax. - -``` -.accordion -.accordion-item -.accordion-item-selected - -.nav_bar -.nav_bar-link -.nav_bar-link-clicked -``` - - - -### Naming methodology resources -- [article explaining BEM][mindbemding] -- [BEM website][BEM] - - -## js- flagged classes -Don't attach styles to classes with a `js-` flag. These classes are reserved for javascript. - -```css -// Bad -.js-people { - color: #ff0; -} -``` - -### Rationale -A `js-` flagged class needs to be highly portable. Adding styles to it breaks that portability. - -## test- flagged classes -Don't attach styles to classes with a `test-` flag. These classes are reserved for testing hooks such as those used by selenium. - -```css -// Bad -.test-people { - color: #ff0; -} -``` - - -[BEM]: https://en.bem.info/method/ -[mindbemding]: http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/ diff --git a/_guide/_pages/css/preprocessors.md b/_guide/_pages/css/preprocessors.md deleted file mode 100644 index f317de4e..00000000 --- a/_guide/_pages/css/preprocessors.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Preprocessors -sidenav: css -sticky_sidenav: true ---- - -The most supported CSS preprocessor at TTS is [Sass](http://sass-lang.com/) -(SCSS). Using this pre-processor means you'll get supported resources such as -frameworks, libraries, tutorials, and a comprehensive styleguide as support. - -In addition, TTS uses a [`.scss-lint.yml` -file](https://raw.githubusercontent.com/18F/frontend/18f-pages-staging/.scss-lint.yml) -to keep our CSS code compliant with our own styleguide. - -_That being said, any preprocessor is allowed as long as it's a sound project -and has community support._ - -The recommended way to compile your Sass code is through -[node-sass](https://www.npmjs.com/package/node-sass), rather than Ruby Sass. -This allows eliminating the Ruby dependency for projects that don't already -require it and is the fastest method of compiling Sass. diff --git a/_guide/_pages/css/specificity.md b/_guide/_pages/css/specificity.md deleted file mode 100644 index 7923c881..00000000 --- a/_guide/_pages/css/specificity.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: Specificity -sidenav: css -sticky_sidenav: true ---- - -- IDs should be reserved for JavaScript. Don’t use IDs for styles. - - ```scss - // Bad - #component { } - - // Good - .component { } - ``` - -- Don't nest more than 3 layers deep. -- Do not fix problems with ```!important```. Use ```!important``` purposefully. - - ```scss - // Bad - .component { - width: 37.4% !important; - } - - // Good - .hidden { - display: none !important - } - ``` - -- Keep specificity low and trend upwards in specificity as you move further - down file. See the [specificity graph](#specificity-graph) section for more - info. -- Don't use unnecessary tag selectors. - - ```scss - // Bad - p.body_text { } - - // Good - .body_text - ``` - -- If you have to hack specificity, use a safe hack: the _multi class_. - - ```scss - // multi-class hack - .component.component { } - ``` - -## Specificity graph -An easy rule to use when dealing with specificity is to start from a low -specificity and curve to higher specificity as you move towards the bottom of -the output file. Since CSS rules get replaced by rules further down in the -file, you'll override rules in an expected way. - -There’s a tool that can graph your files’ specificity, [CSS specificity -graph](http://jonassebastianohlsson.com/specificity-graph/). Run your final -output file through this tool and strive for a curve trending upwards. - -### Resources -* [CSS specificity graph](http://jonassebastianohlsson.com/specificity-graph/) -* [Explanation](http://csswizardry.com/2014/10/the-specificity-graph/) - -## Rationale -With specificity comes great responsibility. Broad selectors allow us to be -efficient, yet can have adverse consequences if not tested. Location-specific -selectors can save us time, but will quickly lead to a cluttered stylesheet. -Exercise your best judgement to create selectors that find the right balance -between contributing to the overall style and layout of the DOM. - -* When modifying an existing element for a specific use, try to use specific - class names. Instead of `.listings-layout.bigger` use rules like - `.listings-layout.listings-bigger`. Think about ack/grepping your code in the - future. - -* Use lowercase and separate words with hyphens when naming selectors. Avoid - camelcase and underscores. Use human-readable selectors that describe what - element(s) they style. - -* Attribute selectors should use double quotes around values. Refrain from - using over-qualified selectors; `div.container` can simply be stated as - `.container`. - -* IDs should be reserved for JavaScript. Unless you have a very good reason, - all CSS should be attached to classes rather than IDs. When in doubt, use a - class name. This prevents target confusion and allows CSS devs and JS devs to - co-exist in the same code in peace. If you must use an id selector (`#id`) - make sure that you have no more than one in your rule declaration. diff --git a/_guide/_pages/css/units.md b/_guide/_pages/css/units.md deleted file mode 100644 index 2b202b2d..00000000 --- a/_guide/_pages/css/units.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: Units -sidenav: css -sticky_sidenav: true ---- - -## Measurements -- Use **rem** units for font sizes with a px fallback. This can be done with - the following mixin: - - ```scss - @mixin font-size($sizeValue: 1.6) { - font-size: ($sizeValue * 10) + px; - font-size: $sizeValue + rem; - } - ``` - -- Set the HTML font size to `10px` to ensure that `0.1rem` equals `1px`. - - ```scss - html { - font-size: 10px; - } - ``` - -- Use **em** units for positioning. -- Use **percentages** when layout components stay relational to each other - (e.g. a main content area that takes up 75% of the screen and a sidebar that - takes up 25%). - - ```scss - // Good - .panel-a { - width: 25%; - } - - .panel-b { - width: 75%; - } - ``` - -- Use **px** units for when a measurement shouldn't change based on user set - font size or browser zooming or for when requiring pixel values below 5. - - ```scss - // Bad - selector { - border-width: 55px; - } - - // Good - selector { - border-width: 2px; - } - ``` - -- Use unitless values for `line-height` as this will inherit values from the - `font-size`. -- Use up to 10 decimal places in em units to ensure accuracy. - - ```scss - // Good - .body_copy { - @include rem-font-size(1.4); - // Line height will now be 1.8 of 1.4rem, or 2.5rem. - line-height: 1.8; - } - - // Good - .container { - height: 12em; - margin-left: 10.6666666667em; - width: 82.5%; - } - ``` - -- Do not use a unit with 0. - - ```scss - // Bad - width: 0px; - - // Good - width: 0; - ``` - -- Always use a unit for dimensions, margins, borders, padding, and typography. - - ```scss - // Bad - border-width: 12; - - // Good - border-width: 12px; - ``` - - -## Colors -- Use **hex** notation first, or then **rgb(a)**, or **hsl(a)**. -- Both three-digit and six-digit hexadecimal notation are acceptable. -- When denoting color using hexadecimal notation, use all lowercase letters. -- When using HSL or RGB notation, always add a single space after a comma and - no space between parentheses and content. - -```scss -// Bad -color: #FFF; -color: rgb( 255, 0, 0 ); - -// Good -$light: #fff; -color: $light; - -// Good -$primary: #fe9848; -color: $primary; - -// Good -$secondary: rgba(255, 100, 255, 0.5); -color: $secondary; -``` - -- If you use an rgba rule, include a fallback value in hexadecimal. - - ```scss - // Good - .illustration { - background-color: #eee; // fallback - background-color: rgba(221, 221, 221, 0.75); - } - ``` diff --git a/_guide/_pages/css/variables.md b/_guide/_pages/css/variables.md deleted file mode 100644 index 9d3b81c0..00000000 --- a/_guide/_pages/css/variables.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Variables -sidenav: css -sticky_sidenav: true ---- - -- Create new variables in the following circumstances: - - The value is repeated twice - - The value is likely to be updated at least once - - All occurrences of the value are tied to the variable (for example not by - coincidence) -- When building scss that will be used across multiple projects use the - `!default` flag to allow overriding. - - ```scss - $baseline: 1em !default; - ``` - -- The `!global` flag should only be used when overriding a global variable from - a local scope. -- Variables across the whole scss codebase should be placed in their own file. -- When declaring color variables, don't base the name on the color content. - - ```scss - // Bad - $light_blue: #18f; - $dark_green: #383; - - // Good - $primary: #18f; - $secondary: #383; - $neutral: #ccc; - ``` - -- Be careful when naming variables based on their context. - - ```scss - // Bad - $background_color: #fff; - ``` - -- Don't use the value of dimensional variables in the variable name. - - ```scss - // Bad - $width_100: 100em; - - // Good - $width_lg: 100em; - ``` - -- Name all used z-indexes with a variable. -- Have a z-index variable for each z-index used, and a separate variable, - possibly aliased for where the z-index is used. - - ```scss - $z_index-neg_1: -100; - $z_index-neg_2: -200; - $z_index-1: 100; - - $z_index-hide: $z_index-neg_2; - $z_index-bg: $z_index-neg_1; - $z_index-show: $z_index-1; - ``` - -## Responsive Design & Breakpoints -- Set variables for breakpoints at the top of your stylesheet. This - functionality is built into Bourbon. - - ```scss - $sm: new-breakpoint(min-width 0 max-width 40em $sm_cols); - ``` - -- Use variables to set the queries throughout so they are easy to adapt if - necessary. -- Place media queries nearest to the class they are affecting. -- Rather than focusing on devices when deciding where to put breakpoints, focus - on content; name breakpoint variables relative to each other. - - ```scss - // Bad - $iphone: new-breakpoint(min-width 0 max-width 640px 6); - - // Good - $small: new-breakpoint(min-width 0 max-width 40em 6); - $medium: new-breakpoint(min-width 0 max-width 60em 6); - ``` diff --git a/_guide/_pages/javascript.md b/_guide/_pages/javascript.md deleted file mode 100644 index a7f6b233..00000000 --- a/_guide/_pages/javascript.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: JavaScript -sidenav: js -sticky_sidenav: true ---- - -The purpose of the JavaScript coding styleguide is to create and utilize -consistent JS across TTS. The styleguide should be treated as a guide -— rules can be modified according to project needs. - -## Related topics -* [Node.js]({{site.baseurl}}/nodejs) diff --git a/_guide/_pages/javascript/dependencies.md b/_guide/_pages/javascript/dependencies.md deleted file mode 100644 index 83f1691b..00000000 --- a/_guide/_pages/javascript/dependencies.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Dependencies -sidenav: js -sticky_sidenav: true ---- - -The word "dependency" refers to all of the frameworks, libraries, and other tools that your project relies on. *Dependency management* is the process by which tools are incorporated into your project, removed and updated (for instance, when you need a new version of [jQuery]). Here are the tools that we recommend for managing dependencies: - -## Bower -{%include components/tag-standard.html %} __Do not use Bower.__ - -It's not needed and should be phased out and replaced by npm. More information can be found here: [Why We Should Stop Using Bower – And How to Do It](http://gofore.com/ohjelmistokehitys/stop-using-bower/). - - -## npm -{%include components/tag-default.html %} [npm] informally stands for *N*ode *P*ackage *M*anager, and is the package manager node uses. Its usage is very similar to Bower because the latter was inspired by the former. - -### npm instructions -1. Get [Node.js]. -2. To initialize your project, run `npm init` in your project directory, which will create a `package.json`. -3. Install some dependencies with `npm install --save [name]`, e.g. - - [jQuery](https://npm.im/jquery): `npm install --save jquery` - - [D3](https://npm.im/d3): `npm install --save d3@v3.5.5` (version 3.5.5) - -npm installs its dependencies in the `node_modules` directory. Common conventions dictate that `node_modules` should be excluded from source control by adding it to your project's `.gitignore`, primarily because Node.js-friendly environments (such as [Cloud Foundry] and [Heroku]) recognize the existence of `package.json` and automatically install dependencies as needed. - -### Install npm - -We recommend that developers (note 1) install both node and npm through a tool called nvm. nvm (which stands for Node version manager) is a software that allows you to run multiple versions of node in different projects on the same computer. Its benefits include - -- Installs npm in a manner that doesn't require running sudo to install global packages. -- Easily be able to switch between multiple node versions with a project configuration file or command. - -To install on MacOSX or linux, follow the instructions on the [nvm site](https://github.com/creationix/nvm#installation). If you system has a c++ compiler setup, you'll likely be able to install it with this simple script: - -``` -curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.6/install.sh | bash -``` - -### Configuring git and GitHub - -The npm `package-lock.json` is a big, gnarly file and it changes a lot. Because it's a generated file, there's not really any value or purpose in manually reviewing it. You can tell git to treat it like a binary file to remove it from diff results by creating a `.gitattributes` file. This file can also include a hint to GitHub to collapse the file in diff view: - -``` -package-lock.json -diff -merge -package-lock.json linguist-generated=true -``` - -When git notices a difference during a merge, it will tenatively accept the current version of the file, but it will fail the merge with a message along the lines of "binary files differ." To manage merge conflicts in `package-lock.json` files, consider installing [npm-merge-driver](https://www.npmjs.com/package/npm-merge-driver), which will automatically resolve those conflicts. - -### Safely installing packages from npm -While npm is generally a safe environment to install code from, there are certain aspects of the system that are vulnerable to dangerous script execution. Luckily there are steps that can be taken to minimize these risks. - -It's recommended that developers at TTS follow these guidelines when installing unknown or new packages. - -npm allows various hooks to be executed during the install process. These scripts are where potential dangerous scripts can be executed. To limit this it's recommended to: - -1. install npm in a manner so sudo is never required. The TTS recommended way of doing this is to [install with nvm](#install-npm). -1. check which scripts will be run on install by running `npm show $module scripts`. - - Each script under `preinstall`, `install`, `postinstall` will be run when installing. - - Each script under `postuninstall`, `preuninstall`, `uninstall` will be run on uninstall. -1. Pull a tarball of the whole package down to check that any scripts run during those steps are safe, `wget http://registry.npmjs.org/$module/-/$module-version.tgz`. - - Check any files that are being run as part of the install scripts. - - Check that the file in the package are generally what they are supposed to be. -1. If unsure, install the packages without running any scripts with `npm install $module --ignore-scripts`. - -### Publishing -#### Scoping a package to the 18F npm org -18F has an npm organization called [18f](https://www.npmjs.com/org/18f) that is meant to organize permissions and packages related to 18F. As an 18F developer, when publishing a package, you have the choice whether to scope a package to the 18F org or not. Scoped packages will always be prefixed with `@18f/` before their package name and can have their permissions managed by people in the org. More information about scoped packages can be found on the [npm documentation](https://docs.npmjs.com/misc/scope). - -##### Guidance on when to scope a package or not -- A package *should not* be scoped to 18F if it is not necessary for consumers (either gov or non-gov) of the package to be aware of 18F in order to use it. - - Example: The Draft US Web Design Standards are used by many entities outside of 18f and government. A user does not need to know anything about 18F to use the Web Design Standards package. -- A package *should* be scoped to 18F if its use cases fall mainly inside of 18F. - - Example: [@18f/stylelint-rules](https://github.com/18F/stylelint-rules) is scoped to 18f because it's an 18F specific linting configuration that's directly linked to the 18F guides site. -- A package *should* be scoped to 18f to avoid naming conflicts. - - Example: If 18F made a generic front-end accordion to use across 18F sites, it should probably be scoped to `@18f/accordion` to avoid conflicts with all other accordions out there. - -##### How to scope a package to 18F -- Ensure you are part of the 18f npm org and have at least developer rights. This can be found on the [18f org team page](https://www.npmjs.com/org/18f/members). - - If you don't have the proper access, ask in #g-frontend or #javascript slack channels and an admin will add you. -- If the package has not been published to 18f yet, follow the [instructions on npm](https://docs.npmjs.com/getting-started/scoped-packages) for scoped packages. -- If the package has already been published, it currently cannot be scoped, so may need to be renamed. See the [npm documentation on existing packages](https://docs.npmjs.com/orgs/preexisting-packages) for more information. - -##### General tips for publishing -- Use [semver](http://semver.org/). -- Include instructions on how to use the modules in the README.md. Start from `npm install`, as this is generally a convention on npm. -- Test to ensure that your package works with any required versions of node and works on Windows. - -### Node and the browser -Using [Node.js] modules in the browser can be either straightforward or convoluted, depending on the project. Some project packages come with browser-ready `.js` files, whereas others require build tools such as [Browserify] or [Webpack] to translate some Node-specific JavaScript so that it can be run in browsers. Visit the #javascript channel on Slack if you need help with these tools. - -## Manual dependency management -Many dependencies consist of a single file and can be more easily incorporated simply by copying them into your project. We have some recommendations for how this should be done: - -1. Establish a specific directory for 3rd-party assets, e.g. `js/vendor` for JavaScript or `assets/vendor` for frameworks that consist of CSS, images and/or JavaScript. -2. Download the assets to this directory, e.g. in your terminal: - - ```sh - cd js/vendor - curl -O http://code.jquery.com/jquery.min.js - ``` - -3. Add these dependencies to version control. - -[jQuery]: http://jquery.com/ -[npm]: https://www.npmjs.com/ -[Node.js]: https://nodejs.org/ -[D3]: http://d3js.org/ -[Browserify]: http://browserify.org/ -[Webpack]: http://webpack.github.io/ -[Cloud Foundry]: https://www.cloudfoundry.org/ -[Heroku]: https://www.heroku.com/ diff --git a/_guide/_pages/javascript/frameworks.md b/_guide/_pages/javascript/frameworks.md deleted file mode 100644 index 862ba6b1..00000000 --- a/_guide/_pages/javascript/frameworks.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: Frameworks -sidenav: js -sticky_sidenav: true ---- - -When choosing a JavaScript web framework, also consider if vanilla JavaScript would satisfy your project needs. "Vanilla JavaScript" (or "vanilla JS") refers to using just JavaScript and the [Web APIs](https://developer.mozilla.org/en-US/docs/Web/API) provided natively by web browsers. For simpler project, vanilla JavaScript helps avoid overengineering, can reduce security and compliance complexity, and may reduce maintenance costs by making it possible for any JavaScript developer to work on it. However, vanilla JavaScript can be unwieldy in complex applications. - -## React -{%include components/tag-default.html %} -[React](https://reactjs.org/) (sometimes styled React.js or ReactJS) is an open-source JavaScript library for creating user interfaces that aims to address challenges encountered in developing single-page applications ([Wikipedia](https://en.wikipedia.org/wiki/React_(JavaScript_library))). - -#### When to use: -- Single page apps that requires data manipulation on the front end without a server side request/response architecture. -- When there's a strong need to render JavaScript based UI on the server due to performance or accessibility reasons. -- JavaScript UI that incorperates many nested components. -- A UI with many components and updates that needs to be performance conscious. -- When only a "view" framework is desired/required. -- To ensure all front-end components conform to a single standard. - -#### When not to use: -- When a complex build process is not feasible. React requires transforming "jsx" files to regular JavaScript. -- When developers unfamiliar with JSX and don't have time to learn. -- While open source, is maintained primarily by Facebook. - -#### Goes well with: -- [Redux](https://redux.js.org/) - An application state management library. - - **When to use:** - - When an application has complex internal state that affects how the site is rendered in realtime. - - When one-way data flow is desired for performance. - - **When not to use:** - - When application internal state is simple - - When all state changes result in cheap re-rendering - -## Angular -{%include components/tag-suggestion.html %} -[Angular](https://angular.io/) (sometimes styled Angular 2+) is an open-source web application framework maintained by Google and by a community of individual developers and corporations to address many of the challenges encountered in developing single-page applications ([Wikipedia](https://en.wikipedia.org/wiki/Angular_(web_framework)) - -We don't work with Angular a lot ourselves, but it is a well-maintained, highly-used modern framework and we should not discourage or frown on its use by our partners. In our consulting and acquisition work, we view Angular as a solid choice for a frontend web framework, given the considerations below. - -#### When to use: -- Sites with heavy front end, JavaScript UI interactions (single page apps) such as: - - creating, updating, deleting of information without a server reload - - real-time messaging platforms, such as chat or complex messaging such as email - - complex data visualization dashboards - - lazy-loaded from the back end -- When the site's design specifies a single page app architecture over classic server request and response. -- When the whole site will be built with Angular to maintain front-end code consistency. - -#### When not to use: -- For a single or a few simple components (with the rest of the site not using Angular), instead see React or Web Components. -- Exporting a module that isn't an Angular module. -- If there is a strict requirement that the site should work for users that have JavaScript disabled. -- If there already is an active M**V framework (Backbone, ampersand, Ember) being used on the site. -- When the site's design doesn't benefit from a single page app architecture. -- When the long-term maintenance dev team is very unfamiliar with Angular and don't have the resources to learn or hire for it. - -#### Pros: -- Takes care of a lot of boilerplate code for front-end interactions. -- Attempts to extend HTML itself, and was designed so less experienced devs could use it. -- Being maintained and developed by Google generally means good support. - -#### Cons: -- While open source, is maintained primarily by Google. -- Has been known to implement breaking changes in major version updates. -- Built with Typescript, which is not ECMA standardized (as opposed to vanilla JS or ES6). -- Has a steep learning curve and is very opinionated, meaning you learn Angular rather than JavaScript. - -# Deprecated - -## AngularJS - -{%include components/tag-caution.html %} -AngularJS is the legacy version of Angular and is not actively developed. Maintenance will be discontinued on July 21, 2021. New projects should not use AngularJS. - -([Wikipedia](http://en.wikipedia.org/wiki/AngularJS)). diff --git a/_guide/_pages/javascript/style.md b/_guide/_pages/javascript/style.md deleted file mode 100644 index 9ca73ebd..00000000 --- a/_guide/_pages/javascript/style.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Style / Linting -sidenav: js -sticky_sidenav: true ---- - -{%include components/tag-standard.html %} -We recommend combining [Prettier](https://prettier.io) with the -[Airbnb JavaScript style guide](https://github.com/airbnb/javascript) plugins -for [eslint](https://eslint.org). - -Maintaining stylistic consistency across TTS code helps lower the barrier to -jumping in and helping with or reviewing other projects because we'll all be -familiar with reading and working with code that looks similar. Having -consistent rules for styling also removes generally non-productive discussions -(aka bikeshedding) around personal code-formatting preferences. - -[Prettier](https://prettier.io) is an automatic code formatter that will handle -converting between tabs and spaces, moving brackets onto the appropriate line, -removing excess whitespace, and other stylistic . Using an automatic formatter -makes it easier to keep code consistent while also freeing us from having to -make arbitrary choices on which styles we prefer. It can -[integrate with your code editor](https://prettier.io/docs/en/editors.html) to -apply styles on save automatically. - -[`eslint`](http://eslint.org/) is our preferred tool for analyzing and flagging -(aka "linting") JavaScript that is out of line with a set of stylistic and -semantic rules. There are plugins to integrate eslint with nearly every code -editor and build system, as described at -[http://eslint.org/docs/user-guide/integrations](http://eslint.org/docs/user-guide/integrations). -Using an eslint plugin with your editor makes it easier to quickly see -non-conforming lines of code on the spot, as shown below: - -![Atom eslint plugin screenshot]({{ site.baseurl }}/javascript/atom-eslint-example.png) - -## Why both? - -Prettier and eslint address an overlapping but different set of concerns. -Prettier is _just_ a formatter. It will adjust your whitespace, add or remove -parentheses, add semicolons, etc., but it has nothing to say about the -semantics of your code. eslint, meanwhile, parsers your code into an abstract -syntax tree to fully understand what it's doing and warns you about unusual -patterns and common errors. For example, it can tell you if you reference an -undefined variable, define a variable that never gets used, and even warn you -about accessibility issues such as leaving an `alt` attribute out of `` -tags in JSX. - -## How to set it up - -Prettier has a few [configurable options](https://prettier.io/docs/en/options.html). -Generally we recommend going with its defaults for simplicity, but the -important thing is to pick something and use it consistently. - -eslint is configured with rules, but rather than write all our own rules we -recommend using the rules defined by the [Airbnb Javascript style guide](https://github.com/airbnb/javascript) -and Prettier. Both Prettier and Airbnb provide their rules as sets of npm -modules, depending on your needs: - -- For all projects - - [eslint-config-prettier](https://www.npmjs.com/package/eslint-config-prettier) -- For React projects: - - [eslint-config-airbnb](https://www.npmjs.com/package/eslint-config-airbnb) - - [eslint-plugin-import](https://www.npmjs.com/package/eslint-plugin-import) - - [eslint-plugin-jsx-a11y](https://www.npmjs.com/package/eslint-plugin-jsx-a11y) - - [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react) -- For ES6/2015 projects that don't use React: - - [eslint-config-airbnb-base](https://www.npmjs.com/package/eslint-config-airbnb-base) - - [eslint-plugin-import](https://www.npmjs.com/package/eslint-plugin-import) -- For ES5 or below: - - [eslint-config-airbnb-base/legacy](https://www.npmjs.com/package/eslint-config-airbnb-base#eslint-config-airbnb-baselegacy)) - -Each link above has instructions for installing the required `npm` packages and -configuring `eslint` to use the installed rules. These should be installed for -each project, and saved in each project's `package.json`. - -Generally the process is to `npm install` the required modules and peer -dependencies, for example: - -```sh -npm install --save-dev \ - eslint \ - eslint-config-airbnb \ - eslint-plugin-jsx-a11y \ - eslint-plugin-import \ - eslint-plugin-react -``` - -and then create a local file configuration within your project called -`.eslintrc.json` that looks like: - -```txt -{ - "extends": ["airbnb", "prettier"] -} -``` - -For more information on configuring `eslint`, see its documentation at -[http://eslint.org/docs/user-guide/configuring](http://eslint.org/docs/user-guide/configuring). diff --git a/_guide/_pages/people/2016-Assessment-Guide.md b/_guide/_pages/people/2016-Assessment-Guide.md deleted file mode 100644 index 1986f227..00000000 --- a/_guide/_pages/people/2016-Assessment-Guide.md +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: 18F Engineering 2016 End of Year Assessment Guide ---- - -18F, as a part of GSA, has a mature [performance management and recognition system](https://insite.gsa.gov/portal/content/500278). -This includes an end-of-year performance assessment. 18F Engineering’s goals for the end-of-year assessment are to have -engineers talk with their facilitator and supervisor about the past year and create actionable plans for career growth -in the coming year. These reviews ideally build on a robust, granular, continuous feedback loop between an engineer, their -facilitator, and other coworkers. - -Assessments are based on an individual’s performance plan. GSA’s Office of Human Resources Management (OHRM) has a -[set of appraisal materials](https://insite.gsa.gov/portal/category/532570) applicable to all of GSA. These include a -good guide on [Appraising Objectively and Fairly](https://insite.gsa.gov/portal/getMediaData?mediaId=614006), -and the requirement to evaluate performance on a 5 point scale. Performance plans have what 18F calls “objectives” and OHRM -calls “critical elements.” Each “critical element” in the performance plan is rated, and there is also a summary rating. -Some ratings can earn performance awards. You can find more detail, including what each rating number means, in the -[Appraisal Rating System & Performance Awards](https://docs.google.com/document/d/1YtnP2RoSJZh5IiKWVJwxyAksjafCqlmBXspCV8nlhZM/edit) document. - -End-of-year assessments are given to everyone hired into GSA on or prior to May 15, 2016, and are due by November 14, 2016. - -In late September, a group of Engineering leadership and engineers met to determine what outcomes we wanted from the end-of-year review process, and what we’d do to achieve those outcomes. - -## Desired outcomes - -### Actionable feedback -The number one desired outcome was actionable feedback for individuals. In order for a review to be valuable, the person being reviewed needs to finish the process with knowledge of — and, ideally, a plan for — how to grow over the following year. At the end of the review period, every engineer should have a solid understanding of what to do next to continue to improve and deliver better value to their teams. - -### Fair rating -Individuals deserve fair ratings. These ratings should be calibrated both within Engineering and across 18F. The ratings and feedback should be aligned with the individual’s performance profile (as is required of course), and not biased towards individuals that the raters have interacted with more than others or those whose strengths align the most with their raters’ interests. Positive and constructive feedback should be balanced, and all feedback should be backed by evidence. Ideally the individual agrees with the rating they’re given. - -### Holistic review -Individuals should be rated not only on their technical abilities and contributions, but on their total contribution to their teams and 18F. This means the reviewers must seek to understand the individual's role on their teams: for example, were they doing any project management or design work in addition to committing code. The reviewer should seek feedback from the individual’s project leads and more experienced technical staff they’ve worked with. Additionally, if an individual has contributed to other areas of 18F through guild and working group contributions, the reviewer should gather feedback from leaders and stakeholders in that group. - -## Process -The person conducting the review, usually an Engineering Supervisor, completes these steps. - -1. Have the engineer complete a self-review. -2. Gather feedback from reviewers (key stakeholders including project leads, technical leads, peers identified in step 1, etc) -3. Synthesize that feedback into a review. -4. Review reviews with the Director. -5. Meet with the engineer and their facilitator to deliver and discuss the review. - -More details on each step: - -### 1. Conduct self-reviews -Have each individual complete a self-review. This review should ask for: - -1. Which projects and accomplishments they’ve worked on over the last year, including both major staffed projects and also side-projects, working groups, guilds, etc. -2. A self-assessment against each objective in their performance plan. -3. Peers (in engineering, or elsewhere) that they’d like us to solicit feedback from (in addition to project leads, tech leads, guild leads, etc., which we’ll talk to by default). -4. Any specific areas they’d like feedback on. -5. Answers to these six “engineering climate” questions (the same as we asked in the [mid-year review](https://docs.google.com/document/d/1n0LegkVV6j3HsUJat-cda_5QmPfF_hFFaWjubpv-amA/edit) plus one new one): - * Do you feel you’re growing as an engineer? - * Do you ever feel like you’re not treated fairly? Please explain. - * Do you feel like you can raise work issues? Do you feel like your issues are actually heard? - * On a scale from 1 to 5, how satisfied are you with your work (1 is “not satisfied”, 5 is “very satisfied”)? - * On a scale from 1 to 5, how motivated are you to do your work (1 is “not motivated”, 5 is “very motivated”)? - * On a scale from 1 to 5, how satisfied are you with the feedback you’ve received throughout this year? - -The answers are sensitive, and should only be shared with other supervisors, and director if necessary. - -### 2. Gather feedback from reviewers -Now that you have the self-review, you can collect feedback from reviewers. - -First, identify reviewers. The engineer’s facilitator can help with this. They should be the key stakeholders in the work the person has done: project leads, technical leads, working group and guild leads, and peers the person nominated above. You should identify at least 3-5 people, but if there are too many it’s OK to prioritize and pare the list down. Be sure to include people who can speak to recent project work. - -Send a request for feedback to each of the reviewers you identified above. This should ask for: - -1. An assessment against each objective in their performance plan (as for #2, above). -2. A request for feedback on the specific areas the individual identified in #4 above. -3. A free-form general feedback area. - -Please remind reviewers to aim to be as specific as possible — ask for specific examples to back up any feedback they give. Assure reviewers that their responses will be synthesized and anonymized before they’re presented to the person under review (so we’re not going to say “well, so-and-so thinks you stink at Go!”) - -If necessary, you can arrange short (15-30 minute) meetings with a reviewer to go over their feedback and gather specific examples. Whether you need to do this will depend on how good and specific written feedback is. Arranging a meeting can be a good method of chasing a response: it takes less time for the reviewer to tell you feedback than for them to write it up. - -### 3. Synthesize feedback and draft a written review - -Now you’ve got a bunch of feedback, so the next step is to synthesize it down into a coherent written review. - -First, you’ll want to review all that feedback along with the person’s facilitator (if applicable). You’re looking for patterns, commonalities, or feedback that aligns with what you or the facilitator have personally observed. You’re looking to distill down all that feedback into a review for each objective in the person’s performance profile. Include as many specific examples of behavior as possible — good feedback is specific and actionable (for a deeper treatment if this idea, see this article on [The Situation-Impact-Feedback Tool](https://www.mindtools.com/pages/article/situation-behavior-impact-feedback.htm)). - -It’s important to be especially cognizant of unconscious bias here. Remember that people are especially susceptible to assume that underrepresented people in tech — women, people of color, etc. — are less qualified than their white male counterparts. One way to correct for this bias is to make sure that reviews are concrete and specific (as above). Another way is to be cognizant of the kinds of reviews that are especially applied to underrepresented minorities. For example, [the word “abrasive” is far more common in reviews of women than of men](https://www.fastcompany.com/3034895/strong-female-lead/the-one-word-men-never-see-in-their-performance-reviews). Other similar kinds of phrases to watch out for are “tone”, “aggressive”, “judgemental”, “too nice”, and so on. In general, if you’re writing a review that seems like it speaks to the person’s character, you may be headed in the wrong direction. - -GSA has [guidance on writing objective and fair reviews](https://insite.gsa.gov/portal/getMediaData?mediaId=614006) that’s worth reviewing as you start to write your review. - -You’ll need to provide a score (1-5) for each objective area in the person’s performance profile. The performance plan has criteria for each score; these plans are available in CHRIS. You should also review the overall guidance on the [rating system scores](https://docs.google.com/document/d/1YtnP2RoSJZh5IiKWVJwxyAksjafCqlmBXspCV8nlhZM/edit). You’ll also need to give the engineer a single overall score (1-5), which is calculated from the objective scores. - -### 4. Review your drafts with the Director -Before finalizing the reviews, meet with the Director of Engineering and review your reviews. They’ll check that your reviews are fair, and also compare scores across the whole chapter to check for bias, patterns, and consistency across Engineering. - -### 5. “Ship” the review, and go over it with the engineer -Now that the review is done, you need to file the “paperwork” and deliver the review. - -First, create the review in CHRIS. Then export a PDF version and send it to the engineer at least a day in advance of meeting with them to deliver the review. - -Then, meet with the engineer (and their facilitator, if applicable) to discuss the review. You’ll discuss the rating and possible performance award if applicable. This is also a good opportunity to deliver feedback that didn’t make it into the written review — especially feedback on areas that the engineer requested way back in step 1. Talk about ways the engineer can address specific feedback (and how we can support them). This can feed into a plan for next year, so take notes to help with follow up and evolution of next year’s plan. - -Finally, discuss their answers to the “engineering climate” questions. There may have been details they didn’t want to provide in the survey version. - -Lastly, the engineer will need to digitally sign the PDF. You’ll store those PDFs in a Google Drive folder (Talent will send us the link), Talent’s tracking spreadsheet, and CHRIS. - -## Going forward - -Our intention for this process is that it will be the start of a more regular, granular feedback system. Engineers deserve frequent feedback on their performance, and there have been many organization and leadership changes in Engineering this year that have disrupted regular feedback loops. Our new structure, where engineers will have a more established relationship with their facilitator and supervisor, will allow us to ensure that feedback happens. Providing regular feedback will make the annual review process a simple extension of regular feedback, as it will be more a culmination of the year’s progress. - -## Retrospective - -In November 2016 we conducted a [retro](https://docs.google.com/document/d/1VY7VEneWzfe4eMNIZ8cmIMdDG5W6T0NQCy6P9yehlNU/edit) of the 2016 Engineering end of year assessment. We asked ourselves how the process we used worked, and what we'd improve. Those in 18F can review that document for details. diff --git a/_guide/_pages/security.md b/_guide/_pages/security.md deleted file mode 100644 index 20dcf143..00000000 --- a/_guide/_pages/security.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Security -sidenav: security -sticky_sidenav: true ---- - -Security is everybody's responsibility at TTS. There are practices that we should adhere to as much as possible when building websites and this guide contains the ones that front-end designers and developers need to be aware of. diff --git a/_guide/_pages/workflow.md b/_guide/_pages/workflow.md deleted file mode 100644 index 787cc7c8..00000000 --- a/_guide/_pages/workflow.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: Our approach -sidenav: approach -sticky_sidenav: true ---- - -Project teams may vary, but across TTS engineering we aim for consistency -around deployments, git etiquette, and similar workflow conventions. - -## Continuous Integration & Deployment - -### Standards - -- Ensure that your project is running **automated tests** in CI. Successful - test completion should be a requirement for deployment. -- Generally, **CI should perform deployments**. This ensures the deployments - are repeatable and don’t rely on individual development environments. See - our [documentation on continuous deployment]({{site.baseurl}}/continuous-deployment) for - details on how to set this up. -- Deployments should be **zero-downtime**, achievable through tools like - [Cloud Foundry's rolling deployment process](https://docs.cloudfoundry.org/devguide/deploy-apps/rolling-deploy.html). -- In addition to deployments after code change, we generally need to - (automatically) **re-deploy daily** to ensure the running containers haven’t - been tampered with (an ATO compliance requirement). See CircleCI’s - [“schedule” - docs](https://circleci.com/docs/2.0/configuration-reference/#schedule) for - details. - -## Git & GitHub - -Git is our version control system of choice and GitHub is our current -repository platform, but how to use these tools can be spelled out in a bit -more detail. Note that we are looking to consolidate this with our existing -documentation on [code review]({{site.baseurl}}/code-review) and [example -workflows]({{site.baseurl}}/example-workflows). - -### Requirements - -- [Install](https://github.com/18F/laptop#git-seekret) our version of - **git-seekret** as a pre-commit hook. This will check for many common types - of API tokens and other sensitive information from making its way into - version control. -- Enable [**two-factor - authentication**](https://help.github.com/articles/about-two-factor-authentication/) - for your GitHub account. This is required for all TTS employees. -- Default to **public** for new repositories. See our - [guidelines](https://github.com/18F/open-source-policy/blob/master/practice.md) - about open source for more detail. -- As part of the ATO process, we require any branches which trigger automated - deployment be - [**protected**](https://help.github.com/articles/about-protected-branches/) - by passing CI and peer review. - -### Defaults - -- Generally we prefer **branches** over forks to ease internal collaboration. - If your project has many outside contributors, consider forks instead. -- When in doubt, use feature branches and - [**gitflow**](http://nvie.com/posts/a-successful-git-branching-model/) as - your branch naming scheme. -- Keep your repository **clean**; delete merged branches and avoid committing - files specific to your dev environment (e.g. `.DS_Store`). -- Follow [this - guidance](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) - about **good commit messages**. -- Consider [**signing commits** with a GPG - key](https://help.github.com/articles/signing-commits-with-gpg/) diff --git a/_includes/categorylinks.html b/_includes/categorylinks.html new file mode 100644 index 00000000..6c84b2cd --- /dev/null +++ b/_includes/categorylinks.html @@ -0,0 +1,10 @@ + diff --git a/_includes/components/header.html b/_includes/components/header.html index c9fb601d..6b511090 100644 --- a/_includes/components/header.html +++ b/_includes/components/header.html @@ -83,9 +83,7 @@ {% endif %} {% else %} - {% assign basedir = page.url | remove_first: '/' | split: '/' | first | lstrip %} - {% assign linkdir = _section.href | replace: '/', '' | lstrip %} - + {{ _section.text }} {% endif %} diff --git a/_includes/footer.html b/_includes/footer.html index 2bfda1a1..3e2053f1 100644 --- a/_includes/footer.html +++ b/_includes/footer.html @@ -1,101 +1,90 @@ -{% assign footer = site.data.footer %} +{% assign identifier = site.data.usa_identifier %} -{% if footer.type == 'slim' %} - {% include components/footer--slim.html %} -{% elsif footer.type == 'default' or footer.type == 'medium' %} - {% include components/footer--default.html %} -{% elsif footer.type == 'big' %} - {% include components/footer--big.html %} -{% endif %} - -{% assign anchor = site.data.anchor %} - -
-{% if anchor.edit_page or (anchor.last_updated and page.last_modified_at) %} - {% unless footer.type %} -
-
-
-
-
-

- {% if anchor.last_updated and page.last_modified_at %} - Last updated: {{ page.last_modified_at | date: '%B %d, %Y' }} - {% endif %} - {% if anchor.edit_page %} - - {% include components/github-edit.html footer=anchor path=page.path %} - - {% endif %} -

+
-
-
-
-
-
- Looking for U.S. government information and services?

- Visit USA.gov -
+
+ +
+
+
Looking for U.S. government information and services?
+ Visit USA.gov +
+
- - + diff --git a/_guide/_pages/index.md b/_pages/about.md similarity index 59% rename from _guide/_pages/index.md rename to _pages/about.md index dd8dd597..df2aa8ce 100644 --- a/_guide/_pages/index.md +++ b/_pages/about.md @@ -1,24 +1,25 @@ --- title: About this guide -permalink: / sidenav: about sticky_sidenav: true subnav: - text: How we classify best practices - href: '#how-we-classify-best-practices' + href: "#how-we-classify-best-practices" --- -*A set of guidelines and best practices for an awesome software engineering team.* [Technology Transformation Services (TTS)](https://www.gsa.gov/about-us/organization/federal-acquisition-service/technology-transformation-services) — which includes [18F](https://18f.gsa.gov/), [Centers of Excellence (CoE)](https://coe.gsa.gov/), [Presidential Innovation Fellows (PIF)](https://presidentialinnovationfellows.gov/), and [TTS Solutions](https://www.gsa.gov/about-us/organization/federal-acquisition-service/technology-transformation-services/tts-solutions) — promote best practices across specialty areas through guilds. -This guide is where the TTS Engineering Practices Guild collects its best practices and resources for software development at TTS, as well as on our partner engagements. Our focus is cloud-native digital services and our recommendations in this guide reflect the needs of that domain. +Getting new practices into the guide is pretty light on process. Feel free to raise a topic in Slack or at a guild meeting and drive to some consensus. Once you've done that, document your findings, submit a PR, and ask in #dev for a quick review. If you think a proposal might be controversial after getting some consensus prior, please post the draft PR to #dev (and elsewhere if you don’t think target audience is in that channel) and solicit feedback. ## How we classify best practices -These documents are structured by topic; under each, we include "Requirement", +These documents are structured by topic; under topics we have classified we indicate "Requirement", "Standard", "Default", "Suggestion", and "Caution". -{%include components/tag-requirement.html %} indicates practices that *must* be done for +If a classification is not present on a topic or a reference to a tool or practice, it should be presumed +to be a {%include components/tag-suggestion.html %} and the decision is left at your discretion. If you are unsure, ask in #dev, as the topic or tool may be a good candidate for classification. + +{%include components/tag-requirement.html %} indicates practices that _must_ be done for regulatory, legal, compliance, or other reasons. {%include components/tag-standard.html %} signifies practices that have a strong consensus across TTS; they @@ -34,3 +35,6 @@ they're not widely used enough to be defaults, but are worth considering. {%include components/tag-caution.html %} marks approaches that have significant pitfalls or should not be used for security/compliance reasons. + +If a specific classification is not present on a topic or reference to a tool or practice, it should be presumed +to be a {%include components/tag-suggestion.html %}. diff --git a/_pages/accessibility-scanning.md b/_pages/accessibility-scanning.md new file mode 100644 index 00000000..aa64e1ba --- /dev/null +++ b/_pages/accessibility-scanning.md @@ -0,0 +1,251 @@ +--- +title: Accessibility Scanning +sidenav: tools +sticky_sidenav: true +--- + +Building a website or application that is easy accessible to everyone is not only an important of the user +experience, but also a requirement of all federally funded projects. GSA provides a helpful +[Section 508](https://section508.gov) portal. Accessibility should not just be an afterthought! Start thinking +about how to make your projects accessible before you begin any development. + +While coding a site to be accessible is a responsibility for engineers, accessibility is not just a concern +for engineering. [Accessibility for Teams](https://accessibility.digital.gov/front-end/getting-started/) +is a GSA-owned guide that gives explicit suggestions for the whole team product team can approach accessibility. +It lists out ways to manually test your site, as well as giving automated testing guidance. + +A more exhaustive list of elements and tools can be found at the [18F Accessibility Guide](https://accessibility.18f.gov/). + +# Recommended Tools + +## Pa11y With aXe-core {%include components/tag-standard.html %} + +[Pa11y](https://pa11y.org/) maintains a handful of open-source automated testing tools that scan your +sites to check for accessibility problems. Their tools can be setup on your machine locally or remotely +using a CI tool. + +We are going to focus on [Pa11y-ci](https://github.com/pa11y/pa11y-ci), which is more geared towards use on +projects in CI. (But can be run locally.) + +Pa11y also maintains [Pa11y](https://github.com/pa11y/pa11y) that allows you to look at live sites or +incorporate pa11y tests into an integration testing framework. ([See below](#pa11y-cli)) + +While Pa11y gives you the option of different test runners, we recommend using aXe-core. + +### aXe-core {%include components/tag-standard.html %} +[aXe-core](https://github.com/dequelabs/axe-core) is an open source accessibility testing engine; it includes +a set of accessibility rules that Pa11y will test against. It is also possible to incorporate aXe-core directly +into your integration tests as well. + +### Running Pa11y in CI + +- [GitHub Actions](#github-actions-on-every-pull-request) + - [Jekyll Specific Setup](#jekyll-specific-setup) + - [Eleventy Specific Setup](#eleventy-specific-setup) +- [Circle CI](#circle-ci-setup-instructions) + +#### GitHub Actions On Every Pull Request + +If you are not familiar with GitHub Actions, you may want to start by reading their [quick start guide](https://docs.github.com/en/actions/quickstart). + +Thanks to Daniel Mundra and the folks at CivicActions Accessibility and their [comprehensive documentation](https://accessibility.civicactions.com/posts/automated-accessibility-testing-leveraging-github-actions-and-pa11y-ci-with-axe) +on setting up Pa11y-ci with GitHub Actions. Much of the below code is taken from that blog post; read through for more details. + +Their instructions are specific to Jekyll but can be leveraged for other types of projects. + +Install pa11y locally: + +```bash + $ npm i --save-dev pa11y-ci +``` + +Create a `.pa11yci` in the root of your directory to [configure your pa11y CI run](https://github.com/pa11y/pa11y-ci#configuration). This step is optional, but helpful if you want to change any default configuration. + +For an example, take a look at the [18F accessibility site's .pallyci file](https://github.com/18F/accessibility/blob/18f-pages/.pa11yci): + +```json + { + "defaults": { + "concurrency": 4, + "standard": "WCAG2AA", + "runners": ["axe"] + } + } +``` + +Create a `.github/workflows` directory in the root of your project, and then add a file `accessibility-scan.yml` (or whatever you want to call it). + +```bash + $ mkdir -P .github/workflows + $ touch .github/workflows/accessibility-scan.yml +``` + +Copy the following into your `accessibility-scan.yml` file : + +```yaml +name: accessibility tests + +on: [pull_request] + +jobs: + build: + name: Build site and run pa11y-ci tests + runs-on: ubuntu-latest + + steps: + - name: Checkout source. + uses: actions/checkout@v2 +``` + +Depending on the type of technology you have built your site in, the rest of this file will vary. + +##### Jekyll Specific Setup + +Add pa11y-specific scripts to `package.json`: + +``` json + "scripts": { + "start-detached": + "bundle exec jekyll serve --detach", + "pa11y-ci:sitemap": + "pa11y-ci --sitemap http://localhost:4000/sitemap.xml --sitemap-exclude \"/*.pdf\"" + } +``` + +Add the following lines to your `accessibility-scan.yml` file at the end of the steps key: + +```yaml + # steps: + - name: Install jekyll site dependencies + uses: ruby/setup-ruby@v1 + with: + # your preferred version here + ruby-version: 2.7.2 + bundler-cache: true + + - name: Install JS dependencies including pa11y-ci + run: npm install + + - name: Start up jekyll server + run: npm run start-detached + + - name: Run pa11y-ci + run: npm run pa11y-ci:sitemap +``` + +This installs Ruby and JavaScript dependencies, then starts Jekyll with the `start-detached` script you added to `package.json` in an earlier step. Once Jekyll has started and detached, pa11y-ci will scan URLs from the sitemap. + +To see a pa11y.yml live in the wild, check out [18F Accessibility site's pa11y.yml](https://github.com/18F/accessibility/blob/18f-pages/.github/workflows/pa11y.yml). + + +##### Eleventy Specific Setup + +Install `start-server-and-test`: + +```bash + $ npm i --save-dev start-server-and-test +``` + +Add the following to your `package.json`: + +```json + "scripts": { + "pa11y-ci:sitemap": "pa11y-ci --sitemap http://localhost:8080/sitemap.xml --sitemap-exclude \"/*.pdf\"", + "test:pa11y-ci": "npx start-server-and-test start 8080 pa11y-ci:sitemap" + } +``` + +Add the following lines to your `accessibility-scan.yml` file at the end of the steps key: + +```yaml + # steps: + - name: Install node.js. + uses: actions/setup-node@v2 + with: + # your preferred version here + node-version: '16' + + - name: Install NPM dependencies + run: npm install + + - name: Build eleventy and run pa11y-ci + run: npm run test:pa11y-ci +``` + +Eleventy does not have a `--detach` option unlike Jekyll, so therefore we use `start-server-and-test` to run eleventy and our tests for us. + +You can see an example of this setup in the [Federal Audit Clearinghouse Front-End repository](https://github.com/GSA-TTS/FAC-Frontend). + +#### Circle CI Setup Instructions + +If you want to run Pa11y-ci per pull request on your project: + +1. Create a bash file `accessibility-scan.sh` in your project home directory to tell it to run either on a circleci supported branch or your localhost + + ```shell + if [[ -n $CIRCLE_BRANCH ]]; then + + echo "scanning site using sitemap from 18F/${CIRCLE_BRANCH}" + + pa11y-ci --sitemap https://federalist.18f.gov/preview/18F/18f.gsa.gov/${CIRCLE_BRANCH}/sitemap.xml + + else + + echo "scanning site using localhost sitemap" + pa11y-ci --sitemap http://localhost:4000/sitemap.xml + ``` + +2. Modify your `circle.yml` to add pa11y-ci + + ​ + + ```yaml + machine: + ruby: + version: + 2.2.3 + + dependencies: + pre: + - [Your-other-commands] + - nvm install stable && nvm alias default stable + - npm test + - npm install -g pa11y-ci + test: + pre: + - bundle exec htmlproofer _site --disable-external --allow-hash-href --empty-alt-ignore --url-ignore 18f@gsa.gov + - echo CIRCLE_BRANCH + - echo + - npm run --harmony accessibility-scan + ``` + +### Travis CI Setup Instructions(To Be Written) + +## Adding Pa11y To The Compliance Viewer(To Be Written) + + +### Pa11y CLI + +If you'd like to test a live website, whether or not you have accesss to the code, the Pa11y CLI can help! + +The CLI requires [Node.js](http://nodejs.org/) 8+, which you can install with homebrew or nvm. + +`$ brew install node` +or +`$ nvm install node` + +Install the CLI globally on your machine: + +`$ npm install -g pa11y` + +and then you can run it against a live site. + +> ``` +> $ pa11y https://engineering.18f.gov/ +> +> Welcome to Pa11y +> +> > Running Pa11y on URL https://engineering.18f.gov/ +> +> No issues found! +> ``` diff --git a/_pages/apis.md b/_pages/apis.md new file mode 100644 index 00000000..7c50b7f4 --- /dev/null +++ b/_pages/apis.md @@ -0,0 +1,177 @@ +--- +title: APIs +sidenav: approach +sticky_sidenav: true +--- + +APIs, like other web applications, vary greatly in implementation and design, depending on the situation and the problem the application is solving. + +This document provides a mix of: + +* **High level design guidance** that individual APIs interpret to meet their needs. +* **Low level web practices** that most modern HTTP APIs use. + +## Design for common use cases + +For APIs that syndicate data, consider several common client use cases: + +* **Bulk data.** Clients often wish to establish their own copy of the API's dataset in its entirety. For example, someone might like to build their own search engine on top of the dataset, using different parameters and technology than the "official" API allows. If the API can't easily act as a bulk data provider, provide a separate mechanism for acquiring the backing dataset in bulk. +* **Staying up to date.** Especially for large datasets, clients may want to keep their copy of the dataset up to date without downloading the entire dataset after every change. If this is a use case for the API, prioritize it in the design. +* **Driving expensive actions.** What would happen if a client wanted to automatically send text messages to thousands of people or light up the side of a skyscraper every time a new record appears? Consider whether the API's records will always be in a reliable unchanging order, and whether they tend to appear in clumps or in a steady stream. Generally speaking, consider the "entropy" an API client would experience. + +## Using one's own API + +The #1 best way to understand and address the weaknesses in an API's design and implementation is to use it in a production system. + +Whenever feasible, design an API in parallel with an accompanying integration of that API. + +## Point of contact + +Have an obvious mechanism for clients to report issues and ask questions about the API. + +When using GitHub for an API's code, use the associated issue tracker. In addition, publish an email address for direct, non-public inquiries. + +## Notifications of updates + +Have a simple mechanism for clients to follow changes to the API. + +Common ways to do this include a mailing list, or a [dedicated developer blog](https://developer.github.com/changes/) with an RSS feed. + +## API endpoints + +An "endpoint" is a combination of two things: + +* The verb (e.g. `GET` or `POST`) +* The URL path (e.g. `/articles`) + +Information can be passed to an endpoint in either of two ways: + +* The URL query string (e.g. `?year=2014`) +* HTTP headers (e.g. `X-Api-Key: my-key`) +* The HTTP request body (for `POST` and `PUT` requests) + +When people say "RESTful" nowadays, they really mean designing simple, intuitive endpoints that represent unique functions in the API. + +Generally speaking: + +* **Avoid single-endpoint APIs.** Don't jam multiple operations into the same endpoint with the same HTTP verb. +* **Prioritize simplicity.** It should be easy to guess what an endpoint does by looking at the URL and HTTP verb, without needing to see a query string. +* Endpoint URLs should advertise resources, and **avoid verbs**. + +Some examples of these principles in action: + +* [OpenFEC API](https://api.open.fec.gov/developers/) +* [Sunlight Congress API methods](https://sunlightlabs.github.io/congress/#using-the-api) + +## Always use HTTPS + +{% include components/tag-requirement.html %} Any new API should use and require [HTTPS encryption](https://en.wikipedia.org/wiki/HTTP_Secure). HTTPS provides: + +* **Security**. The contents of the request are encrypted across the Internet. +* **Authenticity**. A stronger guarantee that a client is communicating with the real API. +* **Privacy**. Enhanced privacy for apps and users using the API. HTTP headers and query string parameters (among other things) will be encrypted. +* **Compatibility**. Broader client-side compatibility. For CORS requests to the API to work on HTTPS websites -- to not be blocked as mixed content -- those requests must be over HTTPS. + +The CIO Council provides two relevant guides: + +* **[Technical Guidelines](https://https.cio.gov/technical-guidelines/)** covering how your HTTPS should be configured. +* **[Migrating APIs to HTTPS](https://https.cio.gov/apis/)** covering moving existing HTTP-only APIs to HTTPS. + +## Use UTF-8 + +{% include components/tag-requirement.html %} Just [use UTF-8](http://utf8everywhere.org). + +An API should tell clients to expect UTF-8 by including a charset notation in the `Content-Type` header for responses. For example, an API that returns JSON should use: + +``` +Content-Type: application/json; charset=utf-8 +``` + +Even if you do not believe your API will ever return data outside the ASCII character set, you should assume it could and return data encoded as UTF-8. + +## Just use JSON + +{% include components/tag-standard.html %} [JSON](https://en.wikipedia.org/wiki/JSON) is an excellent, widely supported transport format, suitable for many web APIs. + +Supporting JSON and only JSON is a practical default for APIs, and generally reduces complexity for both the API provider and consumer. + +General JSON guidelines: + +* **Responses should be a JSON object (not an array)**. Using an array to return results limits the ability to include metadata about results, and limits the API's ability to add additional top-level keys in the future. +* **Don't use unpredictable keys**. Parsing a JSON response where keys are unpredictable (e.g. derived from data) is difficult, and adds friction for clients. +* **Use consistent case for keys**. Whether you use `under_score` or `CamelCase` for your API keys, make sure you are consistent. + +## Use a consistent date format + +{% include components/tag-standard.html %} Specifically, [use ISO 8601](https://xkcd.com/1179/), in UTC. + +For dates, that looks like `{{ site.time | date: '%Y-%m-%d' }}`. For dates with times, that's of the form +`{{ site.time | date: '%Y-%m-%dT%TZ' }}`. + +This date format is used all over the web, and puts each field in consistent order -- from least granular to most granular. + +## CORS + +For clients to be able to use an API from inside web browsers, the API must [enable CORS](http://enable-cors.org). + +For the simplest and most common use case, where the entire API should be accessible from inside the browser, enabling CORS is as simple as including this HTTP header in all responses: + +``` +Access-Control-Allow-Origin: * +``` + +It's supported by [every modern browser](http://enable-cors.org/client.html). + +For more advanced configuration, see the [W3C spec](http://www.w3.org/TR/cors/) or [Mozilla's guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS). + +## API keys + +If keys are used to manage and authenticate API access, the API should allow some sort of unauthenticated access, without keys. + +This allows newcomers to use and experiment with the API in demo environments and with simple `curl` / `wget` / etc. requests. + +Consider whether one of your product goals is to allow a certain level of normal production use of the API without enforcing advanced registration by clients. + +## Pagination + +If pagination is required to navigate datasets, use the method that makes the most sense for the API's data. + +### Parameters + +Common patterns: + +* `page` and `per_page`. Intuitive for many use cases. Links to "page 2" may not always contain the same data. +* `offset` and `limit`. This standard comes from the SQL database world, and is a good option when you need stable permalinks to result sets. +* `since` and `limit`. Get everything "since" some ID or timestamp. Useful when it's a priority to let clients efficiently stay "in sync" with data. Generally requires result set order to be very stable. + +### Metadata + +Include enough metadata so that clients can calculate how much data there is, and how and whether to fetch the next set of results. + +Example of how that might be implemented: + +```json +{ + "results": [ ... actual results ... ], + "pagination": { + "count": 2340, + "page": 4, + "per_page": 20 + } +} +``` + +## Error handling + +Handle all errors (including otherwise uncaught exceptions) and return a data structure in the same format as the rest of the API. + +For example, a JSON API might provide the following when an uncaught exception occurs: + +```json +{ + "message": "Description of the error.", + "exception": "[detailed stacktrace]" +} +``` + +HTTP responses with error details should use a `4XX` status code to indicate a client-side failure (such as invalid authorization, or an invalid parameter), and a `5XX` status code to indicate server-side failure (such as an uncaught exception). diff --git a/_pages/architecture-reviews.md b/_pages/architecture-reviews.md new file mode 100644 index 00000000..f7cf7a6d --- /dev/null +++ b/_pages/architecture-reviews.md @@ -0,0 +1,26 @@ +--- +title: Architecture Reviews +sidenav: approach +sticky_sidenav: true +--- + +Maintainable technology projects require handoffs between developers, and with new teammates comes fresh perspectives. Building a [transparent and remote-friendly +workplace](https://18f.gsa.gov/2015/10/15/best-practices-for-distributed-teams/) is a great start to assist in knowledge transfer, as well as keeping projects as simple and obvious as possible and documenting key decisions. + +## Simplicity + +We’ve done two projects exploring different aspects of simplicity — first, the [DATA Act Pilot: Simplicity is Key]({{site.baseurl}}/architecture-reviews/data-act-pilot) (2016) project explored the ideas of: + +- Building for a least common denominator (CSVs) gave the project reach (more users could participate) and reduced code complexity. +- Pulling out validation rules into a separate, easy-to-modify format made the product flexible and simple to maintain. + +The second explores the idea of simplifying acquisitions in [Micro-purchase: Do one thing well]({{site.baseurl}}/architecture-reviews/micro-purchase) (2016) by using code boundaries in projects to define lines between micro-purchases of developer time. + +## Documenting key decisions + +Some 18F projects have found success using [Architecture Decision Records](https://adr.github.io/) to capture key decisions and the context to which they were made, with the goal of allowing future project developers to know if a decision should be revisited or not. The decision records are typically stored in the repository alongside the code, using [this template](https://github.com/joelparkerhenderson/architecture-decision-record/blob/main/templates/decision-record-template-by-michael-nygard/index.md). For example: + +- [18F/piipan](https://github.com/18F/piipan/tree/main/docs/adr) +- [HHS/Head-Start-TTADP](https://github.com/HHS/Head-Start-TTADP/tree/main/docs/adr) +- [HHS/TANF-app](https://github.com/HHS/TANF-app/tree/main/docs/Architecture%20Decision%20Record) +- [transcom/mymove](https://github.com/transcom/mymove/tree/master/docs/adr) diff --git a/_guide/_pages/architecture-reviews/data-act-pilot.md b/_pages/architecture-reviews/data-act-pilot.md similarity index 99% rename from _guide/_pages/architecture-reviews/data-act-pilot.md rename to _pages/architecture-reviews/data-act-pilot.md index 0537479d..532b4445 100644 --- a/_guide/_pages/architecture-reviews/data-act-pilot.md +++ b/_pages/architecture-reviews/data-act-pilot.md @@ -1,5 +1,7 @@ --- title: 'DATA Act Pilot: Simplicity is Key' +sidenav: approach +sticky_sidenav: true --- ## TL;DR diff --git a/_guide/_pages/architecture-reviews/data-act-pilot/data-act-diagram.png b/_pages/architecture-reviews/data-act-pilot/data-act-diagram.png similarity index 100% rename from _guide/_pages/architecture-reviews/data-act-pilot/data-act-diagram.png rename to _pages/architecture-reviews/data-act-pilot/data-act-diagram.png diff --git a/_guide/_pages/architecture-reviews/data-act-pilot/data-act-diagram.svg b/_pages/architecture-reviews/data-act-pilot/data-act-diagram.svg similarity index 100% rename from _guide/_pages/architecture-reviews/data-act-pilot/data-act-diagram.svg rename to _pages/architecture-reviews/data-act-pilot/data-act-diagram.svg diff --git a/_guide/_pages/architecture-reviews/micro-purchase.md b/_pages/architecture-reviews/micro-purchase.md similarity index 99% rename from _guide/_pages/architecture-reviews/micro-purchase.md rename to _pages/architecture-reviews/micro-purchase.md index 225e5831..e61c6ccb 100644 --- a/_guide/_pages/architecture-reviews/micro-purchase.md +++ b/_pages/architecture-reviews/micro-purchase.md @@ -1,5 +1,7 @@ --- title: 'Micro-purchase: Do one thing well' +sidenav: approach +sticky_sidenav: true --- ## TL;DR diff --git a/_guide/_pages/architecture-reviews/micro-purchase/roles.png b/_pages/architecture-reviews/micro-purchase/roles.png similarity index 100% rename from _guide/_pages/architecture-reviews/micro-purchase/roles.png rename to _pages/architecture-reviews/micro-purchase/roles.png diff --git a/_guide/_pages/architecture-reviews/micro-purchase/roles.svg b/_pages/architecture-reviews/micro-purchase/roles.svg similarity index 100% rename from _guide/_pages/architecture-reviews/micro-purchase/roles.svg rename to _pages/architecture-reviews/micro-purchase/roles.svg diff --git a/_guide/_pages/architecture-reviews/micro-purchase/service.png b/_pages/architecture-reviews/micro-purchase/service.png similarity index 100% rename from _guide/_pages/architecture-reviews/micro-purchase/service.png rename to _pages/architecture-reviews/micro-purchase/service.png diff --git a/_guide/_pages/architecture-reviews/micro-purchase/service.svg b/_pages/architecture-reviews/micro-purchase/service.svg similarity index 100% rename from _guide/_pages/architecture-reviews/micro-purchase/service.svg rename to _pages/architecture-reviews/micro-purchase/service.svg diff --git a/_pages/books-we-have-read.md b/_pages/books-we-have-read.md new file mode 100644 index 00000000..6ff08582 --- /dev/null +++ b/_pages/books-we-have-read.md @@ -0,0 +1,52 @@ +--- +title: Books we've read +sidenav: tools +sticky_sidenav: true +--- + +Engineers at TTS like to read! Here are a few books and other publications that folks have mentioned that they have read in #dev and elsewhere. + +- *Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations* by Nicole Forsgren, Jez Humble, and Gene Kim +- *Being Wrong: Adventures in the Margin of Error* by Kathryn Schulz +- *Debugging Teams: Better Productivity through Collaboration* by Brian W. Fitzpatrick +- *The Design of Everyday Things* by Don Norman +- *Domain-Driven Design Distilled* by Vaughn Vernon +- *Domain-Driven Design: Tackling Complexity in the Heart of Software* by Eric Evans +- *The Effective Engineer* by Edmond Lau and Bret Taylor +- *Fifty Quick Ideas to Improve Your User Stories* by Gojko Adzic and David Evans +- *The Field Guide to Understanding 'Human Error'* by Sidney Dekker +- *Inviting Disaster: Lessons From the Edge of Technology* by James R. Chiles +- *It Doesn't Have to Be Crazy at Work* by Jason Fried and David Heinemeier Hansson +- *Kill It with Fire: Manage Aging Computer Systems (and Future Proof Modern Ones)* by Marianne Bellotti +- *The Manager's Path: A Guide for Tech Leaders Navigating Growth and Change* by Camille Fournier +- *Monolith to Microservices: Evolutionary Patterns to Transform Your Monolith* by Sam Newman +- *The Mythical Man-Month: Essays on Software Engineering* by Frederick Brooks Jr. +- *[Prototyping for tiny fingers](http://fpl.cs.depaul.edu/jriely/360/extras/prototyping-for-tiny-fingers.pdf)* by Marc Rettig +- *[Reflections on Trusting Trust ](https://www.cs.cmu.edu/~rdriley/487/papers/Thompson_1984_ReflectionsonTrustingTrust.pdf)* by Ken Thompson +- *[Shape Up: Stop Running in Circles +and Ship Work that Matters](https://basecamp.com/shapeup/webbook)* by Ryan Singer +- *[Site Reliability Engineering: How Google Runs Production Systems](https://sre.google/sre-book/table-of-contents/)* by Betsy Beyer, Chris Jones, Jennifer Petoff, and Niall Richard Murphy +- *Systems Performance: Enterprise and the Cloud* by Brendan Gregg +- *Threat Modeling: Designing for Security* by Adam Shostack +- *[Twenty Ways to Split Stories](https://xp123.com/articles/twenty-ways-to-split-stories/)* by Bill Wake +- *A Whack on the Side of the Head: How You Can Be More Creative* by Roger von Oech +- *[You Reap What You Code](https://ferd.ca/you-reap-what-you-code.html)* by Fred Hebert + + + + + + + + + + + + + + + + + + + diff --git a/_guide/_pages/browser-testing.md b/_pages/browser-testing.md similarity index 92% rename from _guide/_pages/browser-testing.md rename to _pages/browser-testing.md index 24eb0f04..2e464019 100644 --- a/_guide/_pages/browser-testing.md +++ b/_pages/browser-testing.md @@ -47,4 +47,4 @@ For Safari on iOS: ## Chrome-family browsers and Firefox - [Cypress](https://www.cypress.io/features) - * Ask in #infrastructure + * The command-line test runner and local GUI is [approved for use](https://handbook.tts.gsa.gov/software/search/#cypress). However, the [Cypress Dashboard SaaS](https://www.cypress.io/dashboard/) is not. diff --git a/_guide/_pages/code-review.md b/_pages/code-review.md similarity index 91% rename from _guide/_pages/code-review.md rename to _pages/code-review.md index a5b81b41..5d357a02 100644 --- a/_guide/_pages/code-review.md +++ b/_pages/code-review.md @@ -45,12 +45,12 @@ Some guiding questions for your team's code review discussion: with the feature request and discuss each step until a feature is considered "done." - Do contributors use forks or branches? -- What's the git workflow? E.g. is master always deployable? Rebase or merge? +- What's the git workflow? E.g. is main always deployable? Rebase or merge? - Are pull requests assigned? If so what process is used? - How many people are expected to review each pull request? - If a patch is worked on in a pairing session, how does it get merged? - Does your team make use of any tools to aid in code reviews? (eg: CI, Static - Analysis, linters) + Analysis, linters, [Conventional Comments syntax](https://conventionalcomments.org/)) - Are there any automated tools that you are not using that you would like to try? - If commit messages aren't up to par, should they be modified before the PR is? - What do you look for when conducting a code review? @@ -119,6 +119,7 @@ accomplish this, everyone should consider these tips. them. ("What do you think about such-and-such here?") - Sign off on the pull request with a :thumbsup: or "Ready to merge" comment. - Wait to merge the branch until it has passed Continuous Integration testing. +- Consider using a syntax like [Conventional Comments](https://conventionalcomments.org/) in order to clarify whether a comment is blocking or non-blocking for merging the PR. ### Who merges @@ -129,17 +130,14 @@ issue quickly in the future. ### Opening a PR -We want to receive feedback quickly and make our team members aware of our -proposed solutions early, so it's often a good idea to open a Pull Request for -your new feature/bugfix soon after your first commit. We strongly recommend -that in-progress work is pushed up at least once a day. - [Pull Requests initiate discussion about your -commits.](https://guides.github.com/introduction/flow/) Tag your pull request -with `WIP` (either as a Github tag or in the PR title) if you're not yet ready -for a final review. The more information you provide to reviewers in the +commits.](https://guides.github.com/introduction/flow/) +We want to receive feedback quickly and make our team members aware of our +proposed solutions early, so it's encouraged to open a Draft Pull Request for +your new feature/bugfix soon after your first commit. The more information you provide to reviewers in the description, the more context they will have. This leads to faster reviews, and less back and forth between everyone. +We strongly recommend that in-progress work is pushed up at least once a day. CFPB has published a nice [PR Template](https://github.com/cfpb/development/blob/main/.github/PULL_REQUEST_TEMPLATE.md) which might make this easier. @@ -166,7 +164,7 @@ When reviewing code, you should be able to check off each of the following: - Do the changes respect the project's existing style? - Does the new code avoid reproducing existing functionality? - Are functions/classes as simple as possible? -- Is the code as efficient as possible? +- Is the code reasonably efficient? - Is the usage of each function/class clear? - Have edge cases been considered and tested for? - Does the code represent a logical unit of work? diff --git a/_guide/_pages/continuous-deployment.md b/_pages/continuous-deployment.md similarity index 68% rename from _guide/_pages/continuous-deployment.md rename to _pages/continuous-deployment.md index 11b239b4..e4dfe871 100644 --- a/_guide/_pages/continuous-deployment.md +++ b/_pages/continuous-deployment.md @@ -7,13 +7,13 @@ sticky_sidenav: true ## Pre-requisites This guide assumes that you already have: -- [a GitHub account](https://handbook.18f.gov/github/) and a GitHub repository, typically [under the 18F organization](https://github.com/18F) +- [a GitHub account](https://handbook.18f.gov/github/) and a GitHub repository, typically under the [18F GitHub organization](https://github.com/18F) - [a CircleCI account](https://circleci.com/signup/) (Log In with GitHub) - [a cloud.gov account](https://cloud.gov/docs/getting-started/accounts/?) ## 1. Getting deployer credentials -Use the instructions on [Cloud.gov](https://cloud.gov/docs/apps/continuous-deployment/#provisioning-deployment-credentials) to create a deployer account for your app. Your deployer credentials will regularly expire, so please make sure to update them periodically. +Use the [instructions on Cloud.gov](https://cloud.gov/docs/apps/continuous-deployment/#provisioning-deployment-credentials) to create a deployer account for your app. Your deployer credentials will regularly expire, so please make sure to update them periodically. ## 2. Configure the continuous integration service @@ -78,7 +78,7 @@ Done! ## Add manifests Cloud.gov (and Cloud Foundry) use manifest files to specify how an app should be built on cloud.gov. You will now add two separate files, a `manifest.yml` for your production app and a `manifest-staging.yml` for your development application. -Generally your production application will have multiple instances while your staging will only have one. Manifests can be short and sweet, or extensive. For the full cloud foundry documentation on manifests see here: . +Generally your production application will have multiple instances while your staging will only have one. Manifests can be short and sweet, or extensive. See the full [cloud foundry documentation on manifests](https://docs.cloudfoundry.org/devguide/deploy-apps/manifest.html#minimal-manifest). For an example manifest and manifest-staging see here: [Acquisitions Manifest](https://github.com/18F/acquisitions.18f.gov/blob/develop/manifest.yml) @@ -86,7 +86,8 @@ For an example manifest and manifest-staging see here: ## Zero Downtime Deploy Options -- `v3-zdt-push` is an official command, yet is in active development. See -- `zero-downtime-push` is the popular Autopilot plugin used by a lot of TTS projects and used in both of the above examples. It is now unmaintained and archived though. Does not support buildpacks. If your application successfully deploys to cloud.gov but does not start, which may happen for an application that does not have an adequate test suite, you may have to go into the cf target space and manually delete the "APP_NAME-venerable" application in order to make use of `autopilot` again. -- `blue-green-deploy` another plugin similar to autopilot. +- {%include components/tag-standard.html %} The native Cloud Foundry [rolling app deployments](https://docs.cloudfoundry.org/devguide/deploy-apps/rolling-deploy.html#deploy) CLI is preferred over other options. +- {%include components/tag-caution.html %} [Autopilot](https://github.com/contraband/autopilot) is a plugin historically used by a lot of TTS projects and used in both of the above examples. **It is now unmaintained and archived and does not support buildpacks.** We recommend moving to the official CF deployment commands. + - If you are using autopilot and your application successfully deploys to cloud.gov but does not start, which may happen for an application that does not have an adequate test suite, you may have to go into the cf target space and manually delete the "APP_NAME-venerable" application in order to make use of `autopilot` again. +- [`blue-green-deploy`](https://github.com/bluemixgaragelondon/cf-blue-green-deploy) another plugin similar to autopilot. - An official CircleCI / Cloud Foundry Orb is also available at diff --git a/_pages/css.md b/_pages/css.md new file mode 100644 index 00000000..147d33da --- /dev/null +++ b/_pages/css.md @@ -0,0 +1,902 @@ +--- +title: CSS +sidenav: languages +sticky_sidenav: true +redirect_from: + - /css/architecture/ + - /css/documentation/ + - /css/frameworks/ + - /css/formatting/ + - /css/inheritance/ + - /css/linting/ + - /css/naming/ + - /css/preprocessors/ + - /css/specificity/ + - /css/units/ + - /css/variables/ +subnav: + - text: Architecture + href: "#architecture" + - text: Documentation + href: "#documentation" + - text: Frameworks + href: "#frameworks" + - text: Formatting + href: "#formatting" + - text: Inheritance + href: "#inheritance" + - text: Linting + href: "#linting" + - text: Naming + href: "#naming" + - text: Preprocessors + href: "#preprocessors" + - text: Specificity + href: "#specificity" + - text: Units + href: "#units" + - text: Variables + href: "#variables" +--- + +The purpose of the CSS coding styleguide is to create consistent CSS or +preprocessor CSS code (such as [Sass]) in your projects. The styleguide should be treated as a guide +— rules can be modified according to project needs. + +# Architecture +A site's architecture should be based on its goals and purposes. This means the +guidance here should be adapted to different sites and situations. + +## Modular or component architecture +When using a modular or component architecture, every page is broken into a +series of modular components. There are two sets of these components: +`components` and `modules`. The architecture starts out with basic HTML element +rules: HTML, p, a, form, etc tags that than have components and modules written +on top of them. Components are very basic structure such as buttons, blurbs, +navs, and positioning structures like insets, island, and enclosure. From +here, modules are built with these components. This architecture also attempts +to keep the specificity trend in an upwards curve as you move down in the file +(more on this to come). + +- Start with an elements file for all tag rules (a, h1-h5, p, \*, html, body). +- Create component files for each structural element, such as buttons, navs, + etc. These are mainly class-based and use [BEM] or another naming scheme. +- Create more specific structure with modules. For instance, if the logo image + and text needs very specific treatment, use a module. + - Build modules from components through mixins, extends, and HTML. + - Modules can have higher specificity, it’s fine to use deeper nesting. +- Have an overrides file or folder comprised of global rules that are meant to + override components and modules. + - These can be generic utilities. + - A good thing to put here are breakpoint-specific rules, such as hiding + something at small breakpoints. + +### File structure +```sh +_elements.scss +_mixins.scss +_typography.scss +_util.scss +_vars.scss +component/_blurb.scss +component/_button.scss +component/_island.scss +component/_sub_nav.scss +module/_logo.scss +module/_progress_bar.scss +lib/bourbon.scss +lib/neat.scss +_overrides.scss +``` + +For the `util`, `typography`, `elements`, and `overrides` files, once they grow +too large (300 lines or more) in size, split them into their own folder with +sub files. + +```sh +elements/_all.scss +elements/_p.scss +elements/_h.scss +typography/_body.scss +typography/_links.scss +overrides/_breakpoints.scss +overrides/_util.scss +util/_center.scss +util/_clearfix.scss +``` + + +## Importing +As you likely know, CSS rules that are later in the file override earlier +rules. This means Sass imports can be used to control inheritance and +specificity. + +- Start with base elements. +- Move to single nested classes and utils. +- Move next to more specific classes, often with nesting. +- Move next to overrides, possibly with !important rules. +- Import alphabetically. +- Only modify import order for groups of files, not specific files. + +```scss +// Bad +@import 'https://github.com/module/logo'; +@import 'https://github.com/component/mask'; +@import 'https://github.com/component/button'; /* Has to be imported after "mask" */ + +// Good +@import 'https://github.com/component/button'; +@import 'https://github.com/component/mask'; +@import 'https://github.com/module/logo'; +``` + +[BEM]: http://getbem.com/introduction/ +} + +# Documentation +## Sass Comments +Be intentional when you use `//` (silent comments) versus `/* */` +(which are preserved in the CSS output). When in doubt, use `//`. + +## KSS +Use KSS for documentation. More information on KSS can be found on the +[official site](http://warpspire.com/kss/). + +### Example + +```scss +// Button +// +// Various buttons on the site. +// +// Markup +// +// Link +// +// .button-modified - A button with a different style. +// +// +// Styleguide component.button +.button { +} + +.button-modified { +} +``` + +### Rationale +KSS is the most common CSS documentation method to date. While it’s not perfect, +the generated documentation can be modified through templates. +} + +# Frameworks +TTS recommends using the [U.S. Web Design System (USWDS)](https://github.com/uswds/uswds) as it is specifically designed to help build fast, accessible, mobile-friendly federal government websites. + +Sometimes, projects utilize other CSS frameworks such as: + +1. [Bourbon](https://www.bourbon.io/) +2. [BassCSS](https://basscss.com/) + +These frameworks were chosen because they're relatively unopinionated about +design decisions while still providing the helpers that make frameworks +essential to fast and accurate frontend work, for example, solutions for +responsive design, grids, and common design patterns. In addition, both +frameworks, through modular design and excellent documentation, make it easy +for the designer or developer to only use the parts that they need, rather than +including a hefty library. + +## Do not use Bootstrap + +18F specifically does not recommend using [Bootstrap](http://getbootstrap.com/) for production work +because it can be difficult to adapt its opinionated styles to bespoke design work. + +# Formatting +We recommend using [Prettier](https://prettier.io), and enabling it in your +editor by default. Prettier is an automatic code formatter that will make your +code format consistent. This way we don't have to argue over how to format our +code - we just let the tools enforce something! Prettier works with both plain +CSS and SCSS. + +Do not use shorthand declarations unless you need to explicitly set all the +available values. + +```scss +// Bad +margin: inherit 3em; + +// Good +margin-bottom: 3em; +margin-top: 3em; + +margin: 3em 4em 2em 1em; +``` + +Avoid arbitrary numbers that are repeated, or linked, or dependent on other +parts of the code, (aka “magic numbers”). + +```scss +// Bad +.component { + top: 0.327em; +} + +// Better +/** + * 1. Magic number. This value is the lowest I could find to align the top of + * `.foo` with its parent. Ideally, we should fix it properly. + */ +.component { + top: 0.327em; +} + +// Good +$align_top: 100%; +.component { + top: $align_top; +} +``` + +## Order + +- Use the following ordering: + + 1. variables + 2. @extend directives + 3. @include directives + 4. declaration list (`property: name;`) + 5. media queries + 6. pseudo-states (`:checked`, `:target`, etc.) and pseudo-elements + (`::after`, `::selection`, etc.) + 7. nested elements + 8. nested classes + +- Use alphabetical order or type order for declarations. Pick one to keep the + whole project consistent. +- Place a new line before nested selectors unless they are after the first + selector. +- Treat nested includes, such as Neat's media includes – + `@include media($small-screen)` — as a standard media query, rather than a + Sass @include. So they would be sorted directly after the declaration list. +- Place mixin calls with `@content` after nested selectors. +- You may deviate the sorting order to better suit your project's needs, as + long as it's consistent throughout the project. + +```scss +// Bad +.module { + + .module-element { + color: #fff932; + } +} + +// Good +.module { + .module-element { + color: #fff932; + } +} + +// Good +.module { + $amount = 3; + @extend .component; + @include sizing($amount); + margin-top: $amount * 1em; + text-align: center; + + @include media($small-screen) { + margin-top: ($amount + 10em); + } + + &::before { + content: "hello"; + } + + .module__ele { + color: #fff932; + } +} +``` + +# Inheritance +## Mixins +- Use mixins for groups of properties that appear together intentionally and + are used multiple times. + + ```scss + @mixin clearfix { + &:after { + content: ''; + display: table; + clear: both; + } + } + ``` + +- Use mixins for components to change size. +- Use mixins when something requires parameters. + + ```scss + @mixin size($width, $height: $width) { + width: $width; + height: $height; + } + ``` + +- Do not use mixins for browser prefixes. Use [Autoprefixer](https://github.com/postcss/autoprefixer). + + ```scss + // Bad + @mixin transform($value) { + -webkit-transform: $value; + -moz-transform: $value; + transform: $value; + } + ``` + + +## Extend +Be very careful with using `@extend`. It's a powerful tool that can have +disastrous side-effects. Before using please consider: + +- Where is my current selector going to be appended? +- Am I likely to be causing undesired side-effects? +- How large is the CSS generated by this single extend? + +If you're unsure of using `@extend`, follow these rules to avoid running into +trouble: + +- Use `@extend` from within a module, not across different modules. +- Use `@extend` on [placeholders] exclusively, not on actual selectors. +- Make sure the placeholder you extend is present as little as possible in the + stylesheet. + +You can use [mixins] in place of selectors. While mixins will copy more code, +the difference will often be negligible once the output file has been gzipped. + +[mixins]: http://sass-lang.com/guide#mixins +[placeholders]: http://thesassway.com/intermediate/understanding-placeholder-selectors + +# Linting +Using a linter will ensure that CSS code conforms to some consistent rules. A linting tool like +(Stylelint)[https://stylelint.io/] can issue warnings wherever your code differs from established rules. + +## Setting up Stylelint locally +1. Run `npm install --save-dev stylelint stylelint-config-standard` to download the package and save it to your package.json +2. Create a .stylelintrc.json configuration file in the root of your project with the following content: +```json +{ + "extends": "stylelint-config-standard" +} +``` +3. Run Stylelint on all the CSS files in your project: +`npx stylelint "**/*.css"` + +This utilizes stylelint's standard rules configuration for css linting. +If your project needs different rules or defaults, or you'd like to extend linting to other types of +files, you can utilize custom syntaxes or write your own. + +Stylelint has a [user guide](https://stylelint.io/user-guide/get-started) that will give you more +details about how to configure and extend your linting rules. + +# Naming +- HTML elements should be in lowercase. + + ```scss + body, + div { + } + ``` + +- Classes should be lowercase. +- Avoid camelcase. +- Name things clearly. +- Write classes semantically. Name its function not its appearance. + + ```scss + // Bad + // Avoid uppercase + .ClassNAME { } + + // Avoid camel case + .commentForm { } + + // What is a c1-xr? Use a more explicit name. + .c1-xr { } + ``` + +- Avoid presentation- or location-specific words in names, as this will cause + problems when you (invariably) need to change the color, width, or feature + later. + + ```scss + // Bad + .blue + .text-gray + .100width-box + + // Good + .warning + .primary + .lg-box + ``` + +- Be wary of naming components based on content, as this limits the use of the + class. + + ```scss + // Danger zone + .product_list + + // Better + .item_list + ``` + +- Don't abbreviate unless it’s a well-known abbreviation. + + ```scss + // Bad + .bm-rd + + // Good + .block--lg + ``` + +- Use quotes in type pseudo selectors. + + ```scss + // Good + .top_image[type="text"] { + } + ``` + +- Name CSS components and modules with singular nouns. + + ```scss + .button { + } + ``` + +- Name modifiers and state-based rules with adjectives. + + ```scss + .is_hovered { + } + ``` + +- If your CSS has to interface with other CSS libraries, consider namespacing + every class. + + ```css + .f18-component + ``` + + +## Naming Methodologies + +When it comes to naming, the most important thing is consistency. The +recommended way to do this is using an existing methodology like [BEM](#bem), +or use a custom one that’s clearly defined. + +### BEM + +[BEM][BEM] (**B**lock, **E**lement, **M**odifier) structures CSS such that +every entity is composed of (you guessed it) blocks, elements and modifiers. +From [Harry Roberts][mindbemding]: + +> The point of BEM is to tell other developers more about what a piece of +> markup is doing from its name alone. By reading some HTML with some classes +> in, you can see how – if at all – the chunks are related; something might +> just be a component, something might be a child, or element, of that +> component, and something might be a variation or modifier of that component. + +TTS generally recommends using a modified BEM methodology outlined in the next +subsection. However, you might want to use standard BEM when: + +* You need a naming scheme that general CSS developers will already be familiar + with or an existing naming scheme hasn’t been consistent enough. +* When you want to use JavaScript to modify the BEM class names dynamically. + +Here is an example of BEM in SCSS: + +```scss +// block +.inset { + margin-left: 15%; + + // element + .inset__content { + padding: 3em; + } +} + +// modifier +.inset--sm { + margin-left: 10%; + + .inset__content { + padding: 1em; + } +} + +// modifier +.inset--lg { + margin-left: 20%; +} +``` + + +### Suggested custom methodology + +The TTS recommendation for a naming methodology is a modified version of BEM. +It still uses blocks, sections within blocks and modifiers, but with an +abbreviated syntax. + +``` +.accordion +.accordion-item +.accordion-item-selected + +.nav_bar +.nav_bar-link +.nav_bar-link-clicked +``` + + + +### Naming methodology resources +- [article explaining BEM][mindbemding] +- [BEM website][BEM] + + +## js- flagged classes +Don't attach styles to classes with a `js-` flag. These classes are reserved for javascript. + +```css +// Bad +.js-people { + color: #ff0; +} +``` + +### Rationale +A `js-` flagged class needs to be highly portable. Adding styles to it breaks that portability. + +## test- flagged classes +Don't attach styles to classes with a `test-` flag. These classes are reserved for testing hooks such as those used by selenium. + +```css +// Bad +.test-people { + color: #ff0; +} +``` + + +[BEM]: https://en.bem.info/method/ +[mindbemding]: http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/ + +# Preprocessors +The most supported CSS preprocessor at TTS is [Sass]. Using this preprocessor means you'll +get supported resources such as frameworks, libraries, tutorials, and a comprehensive styleguide +as support. + +_That being said, any preprocessor is allowed as long as it's a sound project +and has community support._ + +[Dart Sass](https://sass-lang.com/dart-sass) is the primary implementation of Sass and is +recommended for use in your projects. + +## Command line installation + +### With npm + +* run: `npm install -g sass` + +### With homebrew + +* run `brew install sass/sass/sass` + +### Other installations + +You can read about other installation methods on [their website](https://sass-lang.com/install). + +# Specificity +- IDs should be reserved for JavaScript. Don’t use IDs for styles. + + ```scss + // Bad + #component { } + + // Good + .component { } + ``` + +- Don't nest more than 3 layers deep. +- Do not fix problems with ```!important```. Use ```!important``` purposefully. + + ```scss + // Bad + .component { + width: 37.4% !important; + } + + // Good + .hidden { + display: none !important + } + ``` + +- Keep specificity low and trend upwards in specificity as you move further + down file. See the [specificity graph](#specificity-graph) section for more + info. +- Don't use unnecessary tag selectors. + + ```scss + // Bad + p.body_text { } + + // Good + .body_text + ``` + +- If you have to hack specificity, use a safe hack: the _multi class_. + + ```scss + // multi-class hack + .component.component { } + ``` + +## Specificity graph +An easy rule to use when dealing with specificity is to start from a low +specificity and curve to higher specificity as you move towards the bottom of +the output file. Since CSS rules get replaced by rules further down in the +file, you'll override rules in an expected way. + +There’s a tool that can graph your files’ specificity, [CSS specificity +graph](http://jonassebastianohlsson.com/specificity-graph/). Run your final +output file through this tool and strive for a curve trending upwards. + +### Resources +* [CSS specificity graph](http://jonassebastianohlsson.com/specificity-graph/) +* [Explanation](http://csswizardry.com/2014/10/the-specificity-graph/) + +## Rationale +With specificity comes great responsibility. Broad selectors allow us to be +efficient, yet can have adverse consequences if not tested. Location-specific +selectors can save us time, but will quickly lead to a cluttered stylesheet. +Exercise your best judgement to create selectors that find the right balance +between contributing to the overall style and layout of the DOM. + +* When modifying an existing element for a specific use, try to use specific + class names. Instead of `.listings-layout.bigger` use rules like + `.listings-layout.listings-bigger`. Think about ack/grepping your code in the + future. + +* Use lowercase and separate words with hyphens when naming selectors. Avoid + camelcase and underscores. Use human-readable selectors that describe what + element(s) they style. + +* Attribute selectors should use double quotes around values. Refrain from + using over-qualified selectors; `div.container` can simply be stated as + `.container`. + +* IDs should be reserved for JavaScript. Unless you have a very good reason, + all CSS should be attached to classes rather than IDs. When in doubt, use a + class name. This prevents target confusion and allows CSS devs and JS devs to + co-exist in the same code in peace. If you must use an id selector (`#id`) + make sure that you have no more than one in your rule declaration. + +# Units +## Measurements +- Use **rem** units for font sizes with a px fallback. This can be done with + the following mixin: + + ```scss + @mixin font-size($sizeValue: 1.6) { + font-size: ($sizeValue * 10) + px; + font-size: $sizeValue + rem; + } + ``` + +- Set the HTML font size to `10px` to ensure that `0.1rem` equals `1px`. + + ```scss + html { + font-size: 10px; + } + ``` + +- Use **em** units for positioning. +- Use **percentages** when layout components stay relational to each other + (e.g. a main content area that takes up 75% of the screen and a sidebar that + takes up 25%). + + ```scss + // Good + .panel-a { + width: 25%; + } + + .panel-b { + width: 75%; + } + ``` + +- Use **px** units for when a measurement shouldn't change based on user set + font size or browser zooming or for when requiring pixel values below 5. + + ```scss + // Bad + selector { + border-width: 55px; + } + + // Good + selector { + border-width: 2px; + } + ``` + +- Use unitless values for `line-height` as this will inherit values from the + `font-size`. +- Use up to 10 decimal places in em units to ensure accuracy. + + ```scss + // Good + .body_copy { + @include rem-font-size(1.4); + // Line height will now be 1.8 of 1.4rem, or 2.5rem. + line-height: 1.8; + } + + // Good + .container { + height: 12em; + margin-left: 10.6666666667em; + width: 82.5%; + } + ``` + +- Do not use a unit with 0. + + ```scss + // Bad + width: 0px; + + // Good + width: 0; + ``` + +- Always use a unit for dimensions, margins, borders, padding, and typography. + + ```scss + // Bad + border-width: 12; + + // Good + border-width: 12px; + ``` + + +## Colors +- Use **hex** notation first, or then **rgb(a)**, or **hsl(a)**. +- Both three-digit and six-digit hexadecimal notation are acceptable. +- When denoting color using hexadecimal notation, use all lowercase letters. +- When using HSL or RGB notation, always add a single space after a comma and + no space between parentheses and content. + +```scss +// Bad +color: #FFF; +color: rgb( 255, 0, 0 ); + +// Good +$light: #fff; +color: $light; + +// Good +$primary: #fe9848; +color: $primary; + +// Good +$secondary: rgba(255, 100, 255, 0.5); +color: $secondary; +``` + +- If you use an rgba rule, include a fallback value in hexadecimal. + + ```scss + // Good + .illustration { + background-color: #eee; // fallback + background-color: rgba(221, 221, 221, 0.75); + } + ``` + +# Variables +- Create new variables in the following circumstances: + - The value is repeated twice + - The value is likely to be updated at least once + - All occurrences of the value are tied to the variable (for example not by + coincidence) +- When building scss that will be used across multiple projects use the + `!default` flag to allow overriding. + + ```scss + $baseline: 1em !default; + ``` + +- The `!global` flag should only be used when overriding a global variable from + a local scope. +- Variables across the whole scss codebase should be placed in their own file. +- When declaring color variables, don't base the name on the color content. + + ```scss + // Bad + $light_blue: #18f; + $dark_green: #383; + + // Good + $primary: #18f; + $secondary: #383; + $neutral: #ccc; + ``` + +- Be careful when naming variables based on their context. + + ```scss + // Bad + $background_color: #fff; + ``` + +- Don't use the value of dimensional variables in the variable name. + + ```scss + // Bad + $width_100: 100em; + + // Good + $width_lg: 100em; + ``` + +- Name all used z-indexes with a variable. +- Have a z-index variable for each z-index used, and a separate variable, + possibly aliased for where the z-index is used. + + ```scss + $z_index-neg_1: -100; + $z_index-neg_2: -200; + $z_index-1: 100; + + $z_index-hide: $z_index-neg_2; + $z_index-bg: $z_index-neg_1; + $z_index-show: $z_index-1; + ``` + +## Responsive Design & Breakpoints +- Set variables for breakpoints at the top of your stylesheet. This + functionality is built into Bourbon. + + ```scss + $sm: new-breakpoint(min-width 0 max-width 40em $sm_cols); + ``` + +- Use variables to set the queries throughout so they are easy to adapt if + necessary. +- Place media queries nearest to the class they are affecting. +- Rather than focusing on devices when deciding where to put breakpoints, focus + on content; name breakpoint variables relative to each other. + + ```scss + // Bad + $iphone: new-breakpoint(min-width 0 max-width 640px 6); + + // Good + $small: new-breakpoint(min-width 0 max-width 40em 6); + $medium: new-breakpoint(min-width 0 max-width 60em 6); + ``` + + [Sass]: http://sass-lang.com diff --git a/_guide/_pages/datastore-selection.md b/_pages/datastore-selection.md similarity index 100% rename from _guide/_pages/datastore-selection.md rename to _pages/datastore-selection.md diff --git a/_guide/_pages/development-environments.md b/_pages/development-environments.md similarity index 74% rename from _guide/_pages/development-environments.md rename to _pages/development-environments.md index de0ffb95..43cc63b9 100644 --- a/_guide/_pages/development-environments.md +++ b/_pages/development-environments.md @@ -4,13 +4,13 @@ sidenav: approach sticky_sidenav: true --- -## Why this guide? +Development environments should be designed so as as to be _Easy to set up_, _Well-documented_, and _Reproducible_. -This guide discusses some principles we should strive to achieve when architecting development environments along with some examples techniques for achieving them. By following this guide, you'll learn how to create environments that are easy to setup, well-documented, and are reproducible (great for finding and fixing bugs). This will keep your colleagues happy, save you time from supporting developer ramp-up, make your repo much more likely to receive open source contributions, and is also generally a good practice as a matter of course. +These principles help keep your colleagues happy, save you time from supporting developer ramp-up, make your repo much more likely to receive open source contributions, and will make it easier to find and fix bugs. -## Principles +We elaborate on each principle below. In a related guide section, we show how [Docker is a good supporting tool](../docker/) to achieve these aims. -The _why_ section sort of gives it away, but a development environment should be: +## Principles **Easy to set up** @@ -18,11 +18,11 @@ Dependencies should be easy to install, and a new developer should be able to cl **Well-documented** -At minimum, there should be a README.md file describing what the software does, how to run its "hello world" equivalent, how to run tests, and all dependencies. If the software is easy to set up, the documentation need not be very long, which is easier to maintain and to keep accurate. +At minimum, there should be a README.md file describing what the software does, how to run its "hello world" equivalent, how to run tests, and all external dependencies (like APIs it talks to). If the software is easy to set up, the documentation need not be very long, which is easier to maintain and to keep accurate. Moreover, while it's great to use code comments or other documentation tools, often the best documentation is the code itself--that is, if the code is easy to comprehend and contextualize, there might not be a pressing need for extraneous explanation of each and every function. -Sometimes configuration files (e.g. `.travis.yml`) get more as scripts. This should be avoided. Instead, leverage these files as "runnable" documentation. For example, the declarative nature of a `.travis.yml` file is a perfect opportunity to document how to do everything needed to set up and run tests. +Make your continuous integration configuration as concise and readable as possible. Instead of: @@ -64,7 +64,6 @@ before_script: Now each set of scripts are much easier run in other environments: locally, in a different CI environment, etc. Moreover, think of the YAML keys as annotations for the scripts. - **Reproducible** A good development environment should be reproducible across different computers, platforms, and environments. Reproducibility helps ensure that bugs are not idiosyncratic to any one person's bespoke computing environment--rather they are intrinsic to the repository itself such that time can be spent debugging the repository code and not the environment on a person's computer. Pinning dependencies such as language runtimes and databases to specific versions is a great way to help achieve this. diff --git a/_guide/_pages/project-setup/docker.md b/_pages/docker.md similarity index 84% rename from _guide/_pages/project-setup/docker.md rename to _pages/docker.md index 42bd6b20..0a9185d9 100644 --- a/_guide/_pages/project-setup/docker.md +++ b/_pages/docker.md @@ -1,5 +1,9 @@ --- -title: Docker for development +title: Docker for Development +sidenav: tools +sticky_sidenav: true +redirect_from: + - /project-setup/docker/ --- Below we lay out recommendations for using Docker to wrap development @@ -26,6 +30,8 @@ into a consistent, reproducible environment. While we don't generally support Docker in production, we can create a setup that matches cloud.gov relatively closely and which makes running our app painless. +Within GSA, [Docker Desktop](https://www.docker.com/products/docker-desktop) can be installed through [Self Service](https://handbook.tts.gsa.gov/gsa-internal-tools/#self-service) without [admin rights](https://handbook.tts.gsa.gov/equipment/#admin-rights). This allows people doing "light" development (like editing content) to run the site locally. Use of Docker can also hide the complexity of setting up a development environment from them. + ## Recommendations We hope to have an end-to-end recommendation in the future, but for now we @@ -126,6 +132,14 @@ my-service: "my-elastic-service": [{"more": "settings"}]} ``` +### Jekyll + +The Docker configuration from [the Handbook](https://github.com/18F/handbook) is very copy-able for other [Jekyll](https://jekyllrb.com/) sites. Specifically, see the: + +- [`Dockerfile`](https://github.com/18F/handbook/blob/master/Dockerfile) +- [Docker Compose configuration](https://github.com/18F/handbook/blob/master/docker-compose.yml) +- [Instructions to run the site](https://github.com/18F/handbook#development) + ## For further debate As with any new tool, we need time to derive best practices. Below we catalog @@ -175,9 +189,11 @@ have several strategies at our disposal. Before we dive too deep, it's important to first discuss `docker-compose run`. Consider + ```sh docker-compose run --rm my-service py.test --pdb ``` + This starts your `my-service` (as defined in your docker-compose manifest), including any necessary dependencies, such as databases. It doesn't execute `my-service`'s startup command, however; instead it runs `py.test` within the @@ -192,18 +208,22 @@ by writing wrapping shell scripts or command aliases. A second strategy places those commands within the docker-compose manifest as pseudo-services, e.g. + ```yml services: py.test: image: thing-that-contains-pytest volumes: - - $PWD:/apps-dir + - $PWD:/apps-dir entrypoint: py.test ``` + These would be executed via + ```sh docker-compose run --rm py.test --pdb ``` + This approach defines a concise list of the entry points to your software suite, but may require additional image rebuilding and can be confusing when combined with `docker-compose up`. If taking this approach, be sure to use @@ -226,18 +246,20 @@ Can we get by without an application image, then? For example, consider a docker-compose manifest that referred only to official images but shared a Docker volume: + ```yml services: my-app: image: python:3.5 volumes: - - dependencies:/path/to/dependency/storage + - dependencies:/path/to/dependency/storage volumes: dependencies: ``` Then we could execute all of our application setup _without_ an application image: + ```sh docker-compose run --rm my-app pip install docker-compose run --rm my-app gunicorn # start app @@ -250,27 +272,36 @@ settling), but it's worth considering. ### Docker as primary dev env -* [calc](https://github.com/18F/calc) -* [e-QIP](https://github.com/18F/e-QIP-prototype) -* [omb-eregs](https://github.com/18F/omb-eregs) -* [pa11y-lambda](https://github.com/18F/pa11y-lambda) -* [tock](https://github.com/18F/tock) -* [federalist](https://github.com/18F/federalist) +- [calc](https://github.com/18F/calc) +- [e-QIP](https://github.com/18F/e-QIP-prototype) +- [omb-eregs](https://github.com/18F/omb-eregs) +- [pa11y-lambda](https://github.com/18F/pa11y-lambda) +- [tock](https://github.com/18F/tock) +- [federalist](https://github.com/18F/federalist) ### Docker as alternative dev env -* [acqstackdb](https://github.com/18F/acqstackdb) -* [autoapi](https://github.com/18F/autoapi) -* [checklistomania](https://github.com/18F/checklistomania) -* [continua11y](https://github.com/18F/continua11y) -* [domain-scan](https://github.com/18F/domain-scan) -* [iaa-gem](https://github.com/18F/iaa-gem) -* [identity-idp](https://github.com/18F/identity-idp) -* [micropurchase](https://github.com/18F/micropurchase) +- [acqstackdb](https://github.com/18F/acqstackdb) +- [autoapi](https://github.com/18F/autoapi) +- [checklistomania](https://github.com/18F/checklistomania) +- [continua11y](https://github.com/18F/continua11y) +- [domain-scan](https://github.com/18F/domain-scan) +- [iaa-gem](https://github.com/18F/iaa-gem) +- [identity-idp](https://github.com/18F/identity-idp) +- [micropurchase](https://github.com/18F/micropurchase) + +## Docker Hub + +TTS has a couple of organizations in [Docker Hub](https://hub.docker.com/): + +- [18F](https://hub.docker.com/u/18fgsa) +- [cloud.gov](https://hub.docker.com/u/cloudgovoperations) +- [data.gov](https://hub.docker.com/u/datagov) +- [login.gov](https://hub.docker.com/u/logindotgov) ## Additional reading -* Atul's [Reflections on Docker-based +- Atul's [Reflections on Docker-based development](https://github.com/18F/dev-environment-standardization/blob/18f-pages/pages/virtualization/docker.md) -* OMB eRegs' [Resolving common container +- OMB eRegs' [Resolving common container issues](https://github.com/18F/omb-eregs#resolving-common-container-issues) diff --git a/_guide/_pages/example-workflows.md b/_pages/example-workflows.md similarity index 96% rename from _guide/_pages/example-workflows.md rename to _pages/example-workflows.md index 91031ecf..fbb98b3b 100644 --- a/_guide/_pages/example-workflows.md +++ b/_pages/example-workflows.md @@ -1,8 +1,8 @@ --- title: Example Workflows +sidenav: approach +sticky_sidenav: true --- -## Example Workflows - Here we've collected descriptions of team processes (particularly around submitting code) that various projects have used in the past. Please consider using one as an example until a more formal template is provided. diff --git a/_guide/_pages/frontend.md b/_pages/frontend.md similarity index 95% rename from _guide/_pages/frontend.md rename to _pages/frontend.md index 4f83483b..0ff301a5 100644 --- a/_guide/_pages/frontend.md +++ b/_pages/frontend.md @@ -1,10 +1,8 @@ --- title: Front-End Disciplines +sidenav: approach +sticky_sidenav: true --- -## Related topics -* [CSS]({{site.baseurl}}/css) -* [JavaScript]({{site.baseurl}}/javascript) -* [Security]({{site.baseurl}}/security) ## What is front end? @@ -33,3 +31,8 @@ should feel comfortable developing and implementing client-side interactions and frameworks using semantic HTML5 and JavaScript, and should be able to help with debugging, testing, and performance optimization of the code base. + +## Related topics +* [CSS]({{site.baseurl}}/css) +* [JavaScript]({{site.baseurl}}/javascript) +* [Security]({{site.baseurl}}/security) \ No newline at end of file diff --git a/_guide/_pages/incident-reports.md b/_pages/incident-reports.md similarity index 91% rename from _guide/_pages/incident-reports.md rename to _pages/incident-reports.md index 6214a710..a3e39504 100644 --- a/_guide/_pages/incident-reports.md +++ b/_pages/incident-reports.md @@ -2,6 +2,8 @@ title: Incident Reports sidenav: approach sticky_sidenav: true +redirect_from: + /incident-reports/cloud-gov/ --- Though we fully expect to write dependable applications, every project will @@ -19,7 +21,7 @@ see: * Slack: #infrastructure, #incident-response, #cloud-gov-support ## Key components -At the high level, we want to follow Mark Imbriaco's [formula for writing a great post-mortem report](https://www.digitalocean.com/company/blog/inside-digitalocean-mark-imbriaco/#departing-from-github): +At the high level, we want to follow Mark Imbriaco's [formula for writing a great post-mortem report](https://www.digitalocean.com/blog/inside-digitalocean-mark-imbriaco/#:~:text=Departing%20From%20GitHub): 1. Apologize for what happened. 1. Demonstrate you understand what happened. 1. Explain what you will do to reduce the likelihood of it happening again. @@ -33,7 +35,7 @@ certain events caused the incident, those events should also be added Analyze the **factors** that contributed to the incident. Here it's important to emphasize the [Retrospective Prime -Directive](http://www.retrospectives.com/pages/retroPrimeDirective.html); +Directive](https://retrospectivewiki.org/index.php?title=The_Prime_Directive); paraphrased: everyone did their best; there should be no judgment of individuals. If lucky, we will discover a single **root cause**, but often we will find a sort-of comedy of errors or serious of unfortunate events that @@ -50,12 +52,11 @@ Don't make folks search for the information. ## Examples * [C2](./C2/c2-outage-report-2016-08-10.pdf) -* [Cloud.gov](./cloud-gov) ## Additional resources * John Allspaw's [introduction](https://codeascraft.com/2012/05/22/blameless-postmortems/) * This [great * presentation](http://www.slideshare.net/danmil30/how-to-run-a-postmortem-with-humans-not-robots-velocity-2013) by Dan Milstein -* Mark Imbriaco's [formula for writing a great post-mortem report](https://www.digitalocean.com/company/blog/inside-digitalocean-mark-imbriaco/#departing-from-github), +* Mark Imbriaco's [formula for writing a great post-mortem report](https://www.digitalocean.com/blog/inside-digitalocean-mark-imbriaco/#:~:text=Departing%20From%20GitHub), and [an example with some commentary](https://medium.com/@faruque/post-mortem-communication-789f396c7dd6#.t1u4ziduf) * @peculiaire's [template for retrospective meetings](https://github.com/peculiaire/incident-lifecycle/blob/master/retrotemplate.md) (adapted from what Heroku uses) diff --git a/_guide/_pages/incident-reports/C2/c2-outage-report-2016-08-10.pdf b/_pages/incident-reports/C2/c2-outage-report-2016-08-10.pdf similarity index 100% rename from _guide/_pages/incident-reports/C2/c2-outage-report-2016-08-10.pdf rename to _pages/incident-reports/C2/c2-outage-report-2016-08-10.pdf diff --git a/_guide/_pages/incident-reports/cloud-gov.md b/_pages/incident-reports/cloud-gov.md similarity index 78% rename from _guide/_pages/incident-reports/cloud-gov.md rename to _pages/incident-reports/cloud-gov.md index b1c55b5a..4e92abee 100644 --- a/_guide/_pages/incident-reports/cloud-gov.md +++ b/_pages/incident-reports/cloud-gov.md @@ -1,5 +1,5 @@ --- -title: Cloud.gov post mortems +title: 'Cloud.gov post mortems' --- Cloud.gov post mortems (including incident response) are hosted at diff --git a/_pages/index.md b/_pages/index.md new file mode 100644 index 00000000..72447cd4 --- /dev/null +++ b/_pages/index.md @@ -0,0 +1,21 @@ +--- +title: Guidelines and Best Practices +permalink: / +sticky_sidenav: true +--- + +This guide is where the TTS Engineering Practices Guild collects its best practices and resources for software development at TTS, as well as on our partner engagements. Our focus is cloud-native digital services and our recommendations in this guide reflect the needs of that domain. + +
+
+ {% include categorylinks.html links=site.data.navigation.about %} + {% include categorylinks.html links=site.data.navigation.approach %} +
+
+ {% include categorylinks.html links=site.data.navigation.tools %} + {% include categorylinks.html links=site.data.navigation.languages %} +
+
+ {% include categorylinks.html links=site.data.navigation.security %} +
+
diff --git a/_guide/_pages/integrations.md b/_pages/integrations.md similarity index 96% rename from _guide/_pages/integrations.md rename to _pages/integrations.md index b1e32d8b..d8dfc5f6 100644 --- a/_guide/_pages/integrations.md +++ b/_pages/integrations.md @@ -20,7 +20,7 @@ otherwise. | Back end Performance Monitoring | [New Relic APM](https://newrelic.com/products/application-monitoring) | | Continuous Integration | [CircleCI](https://circleci.com) and/or [GitHub Actions](https://github.com/features/actions) | | Dependency Analysis | [Snyk](https://snyk.io) and/or [GitHub](https://docs.github.com/en/github/managing-security-vulnerabilities/managing-vulnerabilities-in-your-projects-dependencies) | -| Front end Performance Monitoring | [Google Analytics](https://codelabs.developers.google.com/codelabs/performance-analytics/) (via [DAP][dap])
Note: New Relic is not approved. | +| Front end Performance Monitoring | [Google Analytics](https://developers.google.com/analytics/devguides/collection/analyticsjs/user-timings) (via [DAP][dap])
Note: New Relic is not approved. | | Infrastructure as a Service (IaaS) | [_See Before You Ship_](https://before-you-ship.18f.gov/infrastructure/#infrastructure-as-a-service-iaas) | | Platform as a Service (PaaS) | [cloud.gov](https://cloud.gov) | | Source Control | [GitHub](https://handbook.tts.gsa.gov/github/) | diff --git a/_pages/javascript.md b/_pages/javascript.md new file mode 100644 index 00000000..a40240a9 --- /dev/null +++ b/_pages/javascript.md @@ -0,0 +1,298 @@ +--- +title: JavaScript +sidenav: languages +sticky_sidenav: true +redirect_from: + - /javascript/dependencies/ + - /javascript/frameworks/ + - /javascript/style/ +subnav: + - text: Dependencies + href: "#dependencies" + - text: Framework Suggestions + href: "#frameworks" + - text: Style + href: "#style" + - text: Related Topics + href: "#related-topics" +--- + +The purpose of the JavaScript coding styleguide is to create and utilize +consistent JS across TTS. The styleguide should be treated as a guide +— rules can be modified according to project needs. + +# Dependencies + +The word "dependency" refers to all of the frameworks, libraries, and other tools that your project relies on. *Dependency management* is the process by which tools are incorporated into your project, removed and updated (for instance, when you need a new version of [jQuery]). Here are the tools that we recommend for managing dependencies: + +## Bower +{%include components/tag-caution.html %} __Do not use Bower.__ + +It's not needed and should be phased out and replaced by npm. More information can be found here: [Why We Should Stop Using Bower – And How to Do It](http://gofore.com/ohjelmistokehitys/stop-using-bower/). + + +## npm +{%include components/tag-default.html %} [npm] informally stands for *N*ode *P*ackage *M*anager, and is the package manager node uses. Its usage is very similar to Bower because the latter was inspired by the former. + +### Install npm + +{%include components/tag-standard.html %} +We recommend installing both node and npm through a tool called nvm. nvm (which stands for Node version manager) is a software that allows you to run multiple versions of node in different projects on the same computer. Its benefits include + +- Installs npm in a manner that doesn't require running sudo to install global packages. +- Easily be able to switch between multiple node versions with a project configuration file or command. + +To install on MacOSX or linux, follow the instructions on the [nvm site](https://github.com/creationix/nvm#installation). If you system has a c++ compiler setup, you'll likely be able to install it with this simple script: + +``` +curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.6/install.sh | bash +``` + +### npm instructions + +{%include components/tag-caution.html %} If you can't use nvm, you can install node and npm globally. + +1. Get [Node.js]. +2. To initialize your project, run `npm init` in your project directory, which will create a `package.json`. +3. Install some dependencies with `npm install --save [name]`, e.g. + - [jQuery](https://npm.im/jquery): `npm install --save jquery` + - [D3](https://npm.im/d3): `npm install --save d3@v3.5.5` (version 3.5.5) + +npm installs its dependencies in the `node_modules` directory. Common conventions dictate that `node_modules` should be excluded from source control by adding it to your project's `.gitignore`, primarily because Node.js-friendly environments (such as [Cloud Foundry] and [Heroku]) recognize the existence of `package.json` and automatically install dependencies as needed. + +### Configuring git and GitHub + +The npm `package-lock.json` is a big, gnarly file and it changes a lot. Because it's a generated file, there's not really any value or purpose in manually reviewing it. You can tell git to treat it like a binary file to remove it from diff results by creating a `.gitattributes` file. This file can also include a hint to GitHub to collapse the file in diff view: + +``` +package-lock.json -diff -merge +package-lock.json linguist-generated=true +``` + +When git notices a difference during a merge, it will tenatively accept the current version of the file, but it will fail the merge with a message along the lines of "binary files differ." To manage merge conflicts in `package-lock.json` files, consider installing [npm-merge-driver](https://www.npmjs.com/package/npm-merge-driver), which will automatically resolve those conflicts. + +### Safely installing packages from npm +While npm is generally a safe environment to install code from, there are certain aspects of the system that are vulnerable to dangerous script execution. Luckily there are steps that can be taken to minimize these risks. + +It's recommended that developers at TTS follow these guidelines when installing unknown or new packages. + +npm allows various hooks to be executed during the install process. These scripts are where potential dangerous scripts can be executed. To limit this it's recommended to: + +1. install npm in a manner so sudo is never required. The TTS recommended way of doing this is to [install with nvm](#install-npm). +1. check which scripts will be run on install by running `npm show $module scripts`. + - Each script under `preinstall`, `install`, `postinstall` will be run when installing. + - Each script under `postuninstall`, `preuninstall`, `uninstall` will be run on uninstall. +1. Pull a tarball of the whole package down to check that any scripts run during those steps are safe, `wget http://registry.npmjs.org/$module/-/$module-version.tgz`. + - Check any files that are being run as part of the install scripts. + - Check that the file in the package are generally what they are supposed to be. +1. If unsure, install the packages without running any scripts with `npm install $module --ignore-scripts`. + +### Publishing +#### Scoping a package to the 18F npm org +18F has an npm organization called [18f](https://www.npmjs.com/org/18f) that is meant to organize permissions and packages related to 18F. As an 18F developer, when publishing a package, you're encouraged to scope a package to the 18F org to clearly identify the package as being maintained by 18F, and to limit the chance of naming conflicts or [typosquatting attacks](https://snyk.io/blog/typosquatting-attacks/). Scoped packages will always be prefixed with `@18f/` before their package name and can have their permissions managed by people in the org. More information about scoped packages can be found on the [npm documentation](https://docs.npmjs.com/misc/scope). + +##### How to scope a package to 18F +- Ensure you are part of the 18f npm org and have at least developer rights. This can be found on the [18f org team page](https://www.npmjs.com/org/18f/members). + - If you don't have the proper access, ask in #g-frontend or #javascript slack channels and an admin will add you. +- If the package has not been published to 18f yet, follow the [instructions on npm](https://docs.npmjs.com/getting-started/scoped-packages) for scoped packages. +- If the package has already been published, it currently cannot be scoped, so may need to be renamed. See the [npm documentation on existing packages](https://docs.npmjs.com/orgs/preexisting-packages) for more information. + +##### General tips for publishing +- Use [semver](http://semver.org/). +- Include instructions on how to use the modules in the README.md. Start from `npm install`, as this is generally a convention on npm. +- Test to ensure that your package works with any required versions of node and works on Windows. + +### Node and the browser +Using [Node.js] modules in the browser can be either straightforward or convoluted, depending on the project. Some project packages come with browser-ready `.js` files, whereas others require build tools such as [Browserify] or [Webpack] to translate some Node-specific JavaScript so that it can be run in browsers. Visit the #javascript channel on Slack if you need help with these tools. + +## Manual dependency management +Many dependencies consist of a single file and can be more easily incorporated simply by copying them into your project. We have some recommendations for how this should be done: + +1. Establish a specific directory for 3rd-party assets, e.g. `js/vendor` for JavaScript or `assets/vendor` for frameworks that consist of CSS, images and/or JavaScript. +2. Download the assets to this directory, e.g. in your terminal: + + ```sh + cd js/vendor + curl -O http://code.jquery.com/jquery.min.js + ``` + +3. Add these dependencies to version control. + +[jQuery]: http://jquery.com/ +[npm]: https://www.npmjs.com/ +[Node.js]: https://nodejs.org/ +[D3]: http://d3js.org/ +[Browserify]: http://browserify.org/ +[Webpack]: http://webpack.github.io/ +[Cloud Foundry]: https://www.cloudfoundry.org/ +[Heroku]: https://www.heroku.com/ + +# Frameworks +When choosing a JavaScript web framework, also consider if vanilla JavaScript would satisfy your project needs. "Vanilla JavaScript" (or "vanilla JS") refers to using just JavaScript and the [Web APIs](https://developer.mozilla.org/en-US/docs/Web/API) provided natively by web browsers. For simpler project, vanilla JavaScript helps avoid overengineering, can reduce security and compliance complexity, and may reduce maintenance costs by making it possible for any JavaScript developer to work on it. However, vanilla JavaScript can be unwieldy in complex applications. + +## React +{%include components/tag-default.html %} +[React](https://reactjs.org/) (sometimes styled React.js or ReactJS) is an open-source JavaScript library for creating user interfaces that aims to address challenges encountered in developing single-page applications ([Wikipedia](https://en.wikipedia.org/wiki/React_(JavaScript_library))). + +### When to use: +- Single page apps that requires data manipulation on the front end without a server side request/response architecture. +- When there's a strong need to render JavaScript based UI on the server due to performance or accessibility reasons. +- JavaScript UI that incorperates many nested components. +- A UI with many components and updates that needs to be performance conscious. +- When only a "view" framework is desired/required. +- To ensure all front-end components conform to a single standard. + +### When not to use: +- When a complex build process is not feasible. React requires transforming "jsx" files to regular JavaScript. +- When developers unfamiliar with JSX and don't have time to learn. +- While open source, is maintained primarily by Facebook. + +### Goes well with: +- [Redux](https://redux.js.org/) - An application state management library. + - **When to use:** + - When an application has complex internal state that affects how the site is rendered in realtime. + - When one-way data flow is desired for performance. + - **When not to use:** + - When application internal state is simple + - When all state changes result in cheap re-rendering + +## Angular +{%include components/tag-suggestion.html %} +[Angular](https://angular.io/) (sometimes styled Angular 2+) is an open-source web application framework maintained by Google and by a community of individual developers and corporations to address many of the challenges encountered in developing single-page applications ([Wikipedia](https://en.wikipedia.org/wiki/Angular_(web_framework)) + +We don't work with Angular a lot ourselves, but it is a well-maintained, highly-used modern framework and we should not discourage or frown on its use by our partners. In our consulting and acquisition work, we view Angular as a solid choice for a frontend web framework, given the considerations below. + +### When to use: +- Sites with heavy front end, JavaScript UI interactions (single page apps) such as: + - creating, updating, deleting of information without a server reload + - real-time messaging platforms, such as chat or complex messaging such as email + - complex data visualization dashboards + - lazy-loaded from the back end +- When the site's design specifies a single page app architecture over classic server request and response. +- When the whole site will be built with Angular to maintain front-end code consistency. + +### When not to use: +- For a single or a few simple components (with the rest of the site not using Angular), instead see React or Web Components. +- Exporting a module that isn't an Angular module. +- If there is a strict requirement that the site should work for users that have JavaScript disabled. +- If there already is an active M**V framework (Backbone, ampersand, Ember) being used on the site. +- When the site's design doesn't benefit from a single page app architecture. +- When the long-term maintenance dev team is very unfamiliar with Angular and don't have the resources to learn or hire for it. + +### Pros: +- Takes care of a lot of boilerplate code for front-end interactions. +- Attempts to extend HTML itself, and was designed so less experienced devs could use it. +- Being maintained and developed by Google generally means good support. + +### Cons: +- While open source, is maintained primarily by Google. +- Has been known to implement breaking changes in major version updates. +- Built with Typescript, which is not ECMA standardized (as opposed to vanilla JS or ES6). +- Has a steep learning curve and is very opinionated, meaning you learn Angular rather than JavaScript. + +# Deprecated + +## AngularJS + +{%include components/tag-caution.html %} +AngularJS is the legacy version of Angular and is not actively developed. Maintenance will be discontinued on July 21, 2021. New projects should not use AngularJS. + +([Wikipedia](http://en.wikipedia.org/wiki/AngularJS)). + +# Style +{%include components/tag-standard.html %} +We recommend combining [Prettier](https://prettier.io) with the +[Airbnb JavaScript style guide](https://github.com/airbnb/javascript) plugins +for [eslint](https://eslint.org). + +Maintaining stylistic consistency across TTS code helps lower the barrier to +jumping in and helping with or reviewing other projects because we'll all be +familiar with reading and working with code that looks similar. Having +consistent rules for styling also removes generally non-productive discussions +(aka bikeshedding) around personal code-formatting preferences. + +[Prettier](https://prettier.io) is an automatic code formatter that will handle +converting between tabs and spaces, moving brackets onto the appropriate line, +removing excess whitespace, and other stylistic . Using an automatic formatter +makes it easier to keep code consistent while also freeing us from having to +make arbitrary choices on which styles we prefer. It can +[integrate with your code editor](https://prettier.io/docs/en/editors.html) to +apply styles on save automatically. + +[`eslint`](http://eslint.org/) is our preferred tool for analyzing and flagging +(aka "linting") JavaScript that is out of line with a set of stylistic and +semantic rules. There are plugins to integrate eslint with nearly every code +editor and build system, as described at +[http://eslint.org/docs/user-guide/integrations](http://eslint.org/docs/user-guide/integrations). +Using an eslint plugin with your editor makes it easier to quickly see +non-conforming lines of code on the spot, as shown below: + +![Atom eslint plugin screenshot]({{ site.baseurl }}/javascript/atom-eslint-example.png) + +## Why both? + +Prettier and eslint address an overlapping but different set of concerns. +Prettier is _just_ a formatter. It will adjust your whitespace, add or remove +parentheses, add semicolons, etc., but it has nothing to say about the +semantics of your code. eslint, meanwhile, parsers your code into an abstract +syntax tree to fully understand what it's doing and warns you about unusual +patterns and common errors. For example, it can tell you if you reference an +undefined variable, define a variable that never gets used, and even warn you +about accessibility issues such as leaving an `alt` attribute out of `` +tags in JSX. + +## How to set it up + +Prettier has a few [configurable options](https://prettier.io/docs/en/options.html). +Generally we recommend going with its defaults for simplicity, but the +important thing is to pick something and use it consistently. + +eslint is configured with rules, but rather than write all our own rules we +recommend using the rules defined by the [Airbnb Javascript style guide](https://github.com/airbnb/javascript) +and Prettier. Both Prettier and Airbnb provide their rules as sets of npm +modules, depending on your needs: + +- For all projects + - [eslint-config-prettier](https://www.npmjs.com/package/eslint-config-prettier) +- For React projects: + - [eslint-config-airbnb](https://www.npmjs.com/package/eslint-config-airbnb) + - [eslint-plugin-import](https://www.npmjs.com/package/eslint-plugin-import) + - [eslint-plugin-jsx-a11y](https://www.npmjs.com/package/eslint-plugin-jsx-a11y) + - [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react) +- For ES6/2015 projects that don't use React: + - [eslint-config-airbnb-base](https://www.npmjs.com/package/eslint-config-airbnb-base) + - [eslint-plugin-import](https://www.npmjs.com/package/eslint-plugin-import) +- For ES5 or below: + - [eslint-config-airbnb-base/legacy](https://www.npmjs.com/package/eslint-config-airbnb-base#eslint-config-airbnb-baselegacy)) + +Each link above has instructions for installing the required `npm` packages and +configuring `eslint` to use the installed rules. These should be installed for +each project, and saved in each project's `package.json`. + +Generally the process is to `npm install` the required modules and peer +dependencies, for example: + +```sh +npm install --save-dev \ + eslint \ + eslint-config-airbnb \ + eslint-plugin-jsx-a11y \ + eslint-plugin-import \ + eslint-plugin-react +``` + +and then create a local file configuration within your project called +`.eslintrc.json` that looks like: + +```txt +{ + "extends": ["airbnb", "prettier"] +} +``` + +For more information on configuring `eslint`, see its documentation at +[http://eslint.org/docs/user-guide/configuring](http://eslint.org/docs/user-guide/configuring). +} + +# Related topics +* [Node.js]({{site.baseurl}}/nodejs) diff --git a/_guide/_pages/javascript/atom-eslint-example.png b/_pages/javascript/atom-eslint-example.png similarity index 100% rename from _guide/_pages/javascript/atom-eslint-example.png rename to _pages/javascript/atom-eslint-example.png diff --git a/_guide/_pages/language-selection.md b/_pages/language-selection.md similarity index 57% rename from _guide/_pages/language-selection.md rename to _pages/language-selection.md index acb413d5..a53e4070 100644 --- a/_guide/_pages/language-selection.md +++ b/_pages/language-selection.md @@ -7,13 +7,13 @@ sticky_sidenav: true Many factors should influence how TTS engineers make technology selections for their projects. Here, we discuss recommendations on how to select the _language_ used in your projects. This document doesn't offer hard-and-fast -rules, focusing instead on several language aspects[1](#aspect) +rules, focusing instead on several language aspects which should be balanced against each other. Also, we explicitly note that language selection is ultimately the decision (and responsibility) of the project team. The guidance below is meant to _assist_ your team make this decision. -This is a living document[2](#doctype). After looking at [existing +This is a living document. After looking at [existing tickets](https://github.com/18F/development-guide/issues), [start an issue](https://github.com/18F/development-guide/issues/new) or pull request in GitHub to suggest changes to these standards. @@ -22,7 +22,7 @@ GitHub to suggest changes to these standards. TTS has historically worked in three **primary** languages: JavaScript, Python, and Ruby. While we certainly have a healthy smattering of other odds -and ends, these three are our primary strength[3](#strong) as +and ends, these three are our primary strength as indicated by data from past projects, engineer skill sets, and billable hours. These languages are generally a safe bet as we know we can support them and be productive with them. @@ -30,7 +30,7 @@ productive with them. Looking at this same data and applying preferences from the guiding factors below, we also see a **second tier** of familiarity around Go, Java, and PHP. These languages may be good fits depending on the project at hand. In -particular, domain[4](#dsl) preference and client familiarity may +particular, domain preference and client familiarity may be major reasons to select one of these languages for your project. We feel relatively comfortable supporting these languages, but if all other factors are equal, we encourage selecting from our first tier. @@ -41,13 +41,13 @@ The following are used widely in TTS: | Purpose | Tool | | ------------------------------------ | ------------------------------------------------------------------------------------------------------------ | -| CSS framework | [_More info_]({{site.baseurl}}/css/frameworks/) | +| CSS framework | [_More info_]({{site.baseurl}}/css/#frameworks) | | Infrastructure/configuration as code | [Terraform](https://www.terraform.io/) | | Static site generator | [Jekyll](https://jekyllrb.com/) (with the [uswds-jekyll](https://github.com/18F/uswds-jekyll) theme) or Hugo | ## Project scope -Perhaps the most important factor[5](#factor) to weigh when +Perhaps the most important factor to weigh when considering languages is the estimated project scope. If we anticipate a large, long-standing project which will be handed off to our agency partners, we should be conservative in our language selection. These projects warrant @@ -56,85 +56,64 @@ of our primary languages. On the other hand, if writing a one-off script or small internal project, we have significantly more latitude to try experimental languages. -Let's consider some examples for reference[6](#reference). As a +Let's consider some examples for reference. As a reminder, in almost all situations, selecting one of our primary languages is a viable option. * Scrape GitHub statistics one-shot - R would be a fine solution. Due to the - small scope[7](#scope) of the project, we get much more value + small scope of the project, we get much more value from R than we lose due to risk of unmaintainability, etc. * Integration tests for an internal app - Here, we've - ratcheted[8](#racket) up risk: a team will need to maintain these + ratcheted up risk: a team will need to maintain these tests in the future. However, if the team were so inclined, using something like Perl might still be a viable option due to the limited impact of these tests. -* Agency-centric open[9](#open) data API - Given the public-facing +* Agency-centric open data API - Given the public-facing project scope and assuming other factors are equal, we should write this in one of our primary languages. We can be confident we'll do the best job, most efficiently with this approach. ## Factors -Languages are not all equal[10](#triple-equal). We next consider a +Languages are not all equal. We next consider a handful of factors to weigh when selecting a language for a project. In no particular order: * Open source - TTS is a strong proponent of open source; we want our language - selection[11](#select) to reflect that. We want open APIs, open + selection to reflect that. We want open APIs, open source binaries, and community participation. * Domain preference - certain problem domains emphasize particular languages. For example, the Cloud Foundry community has a preference for Go, while - SOAP-heavy specs[12](#specs) are more friendly in Java, and Rails + SOAP-heavy specs are more friendly in Java, and Rails projects promote CoffeeScript. We want to use the tools appropriate for the job. -* Team familiarity - avoid the bus problem. The more TTS engineers who are - comfortable with a language, the safer[13](#safe) it is to use. - We want our project to be accessible to many both within TTS and without. +* Team familiarity - The more TTS engineers who are + comfortable with a language, the safer it is to use. + We want our project to be accessible to many, both within TTS and without. * Stability - bleeding edge languages are more risky. If the standard API is changing every few months, we aren't going to be able to maintain the - project. Try to fathom[14](#fantom) how this bodes when we're + project. Try to fathom how this bodes when we're handing this project off. * Active ecosystem - some languages are on the rise while others are falling - or never gained traction. We will be leaning[15](#lein) on the + or never gained traction. We will be leaning on the community for support and potentially to hire contractors and vendors. Less active communities make this more difficult. * Inclusive communities - TTS promotes welcoming cultures and we want to see that reflected in our language selection. We want to reward language leaders who promote diverse opinions and have open standards processes. We see - languages led by cabals[16](#cabal) as risks. -* Library support - we don't want to reinvent the wheel[17](#ring) + languages led by cabals as risks. +* Library support - we don't want to reinvent the wheel (or the database adapter). Languages with a thriving library ecosystem will be easier and most cost effective to work with. * Hand-off considerations - is our agency partner comfortable with a particular framework? If they already know how to deploy - XYZ[18](#yapc) apps (and hire XYZ developers), it behooves us to + XYZ apps (and hire XYZ developers), it behooves us to write an XYZ app. ## Other impact -By setting forth[19](#forth) the above, we can imagine potential +By setting forth the above, we can imagine potential impact on our hiring, project selection, and larger processes. The progression is logical and we may want to use this document as evidence when deciding how to iterate those systems. Concrete details are outside the scope of this document, however, and we anticipate (and proclaim) no immediate changes. - ---- -*
1: Not to be confused with [AspectJ](https://en.wikipedia.org/wiki/AspectJ) -* 2: Not to be confused with [DOCTYPEs](https://en.wikipedia.org/wiki/Document_type_declaration) -* 3: Not to be confused with [strong params](https://github.com/rails/strong_parameters) -* 6: Not to be confused with [domain specific languages](https://en.wikipedia.org/wiki/Domain-specific_language) -* 5: Not to be confused with [Factor](https://en.wikipedia.org/wiki/Factor_(programming_language)) -* 6: Not to be confused with [references](https://en.wikipedia.org/wiki/Reference_%28computer_science%29) -* 7: Not to be confused with [variable scoping](https://en.wikipedia.org/wiki/Scope_%28computer_science%29) -* 8: Not to be confused with [Racket](https://en.wikipedia.org/wiki/Racket_%28programming_language%29) -* 9: Not to be confused with [OpenJDK](http://openjdk.java.net/) -* 10: Not to be confused with [JavaScript equality](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness) -* 11: Not to be confused with [SELECT](https://en.wikipedia.org/wiki/Select_%28SQL%29) -* 12: Not to be confused with [rspec](http://rspec.info/) -* 13: Not to be confused with [type safety](https://en.wikipedia.org/wiki/Type_safety) -* 14: Not to be confused with [Fantom](https://en.wikipedia.org/wiki/Fantom_%28programming_language%29) -* 15: Not to be confused with [*lein*](http://leiningen.org/) -* 16: Not to be confused with [*cabal*](https://www.haskell.org/cabal/) -* 17: Not to be confused with [ring](https://github.com/ring-clojure/ring) -* 18: Not to be confused with [YAPC](http://www.yapc.org/) -* 19: Not to be confused with [Forth](https://en.wikipedia.org/wiki/Forth_%28programming_language%29) diff --git a/_guide/_pages/laptop-setup.md b/_pages/laptop-setup.md similarity index 81% rename from _guide/_pages/laptop-setup.md rename to _pages/laptop-setup.md index 7403e2fa..9e1fcbdb 100644 --- a/_guide/_pages/laptop-setup.md +++ b/_pages/laptop-setup.md @@ -9,13 +9,12 @@ While you are welcome to customize your laptop, here are some tools that have wo * [ChromeDriver] for headless website testing * [chruby] for managing [Ruby] versions. * [Cloud Foundry CLI] for command line access to 18F's Cloud Foundry-based application platform -* [Docker] for all your containerization needs -* [git-seekret] for preventing you from committing passwords and other sensitive information to a git repository +* [Caulking] checks for many common types of API tokens and other [sensitive information](https://handbook.tts.gsa.gov/sensitive-information/) before you commit * [GitHub Desktop] for setting up your SSH keys automatically * [Homebrew] for managing operating system libraries * [Homebrew Cask] for quickly installing Mac apps from the command line * [Homebrew Services] so you can easily stop, start, and restart services -* [hub] for interacting with the GitHub API +* [gh] (official) or [hub] (unofficial) GitHub-maintained CLI tools for interacting with the GitHub API * [nvm] for managing Node.js versions if you do not have [Node.js] already installed (Includes latest [Node.js] and [NPM], for running apps and installing JavaScript packages) * [pyenv] for managing Python versions if you do not have [Python] already installed (includes the latest 3.x [Python]) * [ruby-install] for installing different versions of Ruby @@ -28,17 +27,17 @@ While you are welcome to customize your laptop, here are some tools that have wo [ChromeDriver]: http://chromedriver.chromium.org/ [chruby]: https://github.com/postmodern/chruby [Cloud Foundry CLI]: https://github.com/cloudfoundry/cli -[Docker]: https://www.docker.com/ -[git-seekret]: https://github.com/18F/git-seekret +[Caulking]: https://github.com/cloud-gov/caulking [Github Desktop]: https://desktop.github.com/ [Homebrew]: http://brew.sh/ [Homebrew Cask]: https://github.com/Homebrew/homebrew-cask [Homebrew Services]: https://github.com/Homebrew/homebrew-services +[gh]: https://cli.github.com/ [hub]: https://github.com/github/hub [Node.js]: http://nodejs.org/ [NPM]: https://www.npmjs.org/ [nvm]: https://github.com/nvm-sh/nvm -[pyenv]: https://github.com/yyuu/pyenv/ +[pyenv]: https://github.com/pyenv/pyenv [Python]: https://www.python.org/ [Ruby]: https://www.ruby-lang.org/en/ [ruby-install]: https://github.com/postmodern/ruby-install @@ -48,6 +47,16 @@ While you are welcome to customize your laptop, here are some tools that have wo [Virtualenvwrapper]: http://virtualenvwrapper.readthedocs.org/en/latest/# [Zsh]: http://www.zsh.org/ +## Licensed Software + +* [Docker] for all your containerization needs + + The docker daemon and docker CLI tools are available on a free license. + + [Docker Desktop] requires a paid license. Ask in [#admins-docker](https://gsa-tts.slack.com/app_redirect?channel=admins-docker) in Slack to get a license. + +[Docker]: https://www.docker.com/ +[Docker Desktop]: https://www.docker.com/products/docker-desktop/ ## Other customizations @@ -76,4 +85,4 @@ While you are welcome to customize your laptop, here are some tools that have wo These suggestions were culled from the deprecated (as of October 2020) [laptop script]. If you are looking for references on how to build personal dotfiles, that repo may be of use. -[laptop script]: https://github.com/18F/laptop \ No newline at end of file +[laptop script]: https://github.com/18F/laptop diff --git a/_guide/_pages/license.md b/_pages/license.md similarity index 97% rename from _guide/_pages/license.md rename to _pages/license.md index 8135f192..c32feae5 100644 --- a/_guide/_pages/license.md +++ b/_pages/license.md @@ -8,18 +8,17 @@ subnav: - text: Other information href: "#other-information" --- - As a work of the [United States government](https://www.usa.gov/), this project is in the public domain within the United States of America. Additionally, we waive copyright and related rights in the work worldwide through the [CC0 1.0 Universal public domain dedication](https://creativecommons.org/publicdomain/zero/1.0/legalcode). -### No copyright +## No copyright The person who associated a work with this deed has dedicated the work to the public domain by waiving all of their rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. You can copy, modify, distribute, and perform the work, even for commercial purposes, all without asking permission. -### Other information +## Other information In no way are the patent or trademark rights of any person affected by CC0, nor are the rights that other persons may have in the work or in how the work is used, such as publicity or privacy rights. diff --git a/_pages/markdown.md b/_pages/markdown.md new file mode 100644 index 00000000..ff6d51bf --- /dev/null +++ b/_pages/markdown.md @@ -0,0 +1,9 @@ +--- +title: Markdown Guide +sidenav: languages +sticky_sidenav: true +--- + +["Markdown is a text-to-HTML conversion tool for web writers. Markdown allows you to write using an easy-to-read, easy-to-write plain text format."](https://daringfireball.net/projects/markdown/) + +Use [Prettier](https://prettier.io/) for automatic code formatting. diff --git a/_guide/_pages/nodejs.md b/_pages/nodejs.md similarity index 100% rename from _guide/_pages/nodejs.md rename to _pages/nodejs.md diff --git a/_pages/on-call.md b/_pages/on-call.md new file mode 100644 index 00000000..8d9a761a --- /dev/null +++ b/_pages/on-call.md @@ -0,0 +1,167 @@ +--- +title: On call recommendations +sidenav: approach +sticky_sidenav: true +--- +Different types of projects have unique on-call support needs. +Regardless of the type of project, there are a number of things that +could be considered at different stages of development that would +allow any type of team and product to be set up for on-call success. + +## Staffing/resourcing phase +Resourcing is very important to the support success of a team. + +For short, emergent projects, staffing *at least one* more engineer than estimated, +without increasing scope will better allow: + - opportunities for engineers to pair, + - higher quality code review, and + - dedicated time for creating comprehensive documentation. + +Staffing an engineering role that has ownership over documentation and technical +writing will also ease some of this stress. + +It should be clear from the beginning of staffing discussions for a project with +possible on-call expectations that providing out-of-regular hours support is a part +of the assignment. + +The incentives for being on-call also need to be very clear. Will overtime be paid? +Is there a limit to the amount of hours staff can work? These incentives need to be +clearly defined and clarified for the team before anyone is expected to accept an +on-call shift. Some of the limitations like hour caps may be level-specific, and so +we will need to build an organizational fluency at the supervisory level to help +individual people navigate them. + +### Start talking about support *now* +Support can look a lot of different ways. Will this be an ongoing, highly-available +product that needs ongoing 24-hour support? Will this be a short-term project that +needs 24-hour support for two weeks? Does it only need support during Eastern-time +work hours, or throughout-all-US-time-zone work hours? + +Discussion about what type of support the project may need, both in the short- and +long-term, should be inserted into the staffing/planning stage as soon as possible. +The shape of support may not be clear this early in the product life cycle, but +starting those conversations now will guide what kind of documentation and telemetry +needs to be built into the project. + +## Development phase + +### Documentation is part of the development cycle +Documentation makes it easier to onboard a new team member, explain and justify +historic decision-making, and ultimately ensure long-term on-call success. All team +members, from the product manager to the engineers, should be in alignment about the +importance of documentation. + +This includes architectural decision records (ADRs), but it also includes details +that evolve as the system does such as: +- Setting up local development from zero, + - Including what local config/variables are necessary, and + - Who to contact to grant permissions to access various systems +- The entirety of the tech stack/dependencies, +- Runbooks of common problems, +- CI and deployment workflows, +- What external accounts are necessary, +- How to read and interpret logging information and metrics, +- How to log into the production instance in case live debugging is necessary, and +- The human processes for getting code to production and how those might differ in an emergency situation + +### Telemetry and monitoring is part of the product +As development proceeds, it is important to think about monitoring, alerts, and +telemetry into the system itself. Questions you should be thinking about from the +very first line of code: +- How will the application know when something goes wrong? +- How will we be alerted that something is going wrong? +- How will we debug or troubleshoot what’s going wrong? + +Ensure that this is in place during development cycles will make it a lot easier to +transition to a live product needing support. + +### Create a checklist for onboarding staff +As you add secrets, credentials, and third-party tools to the tech stack, you should +be documenting exactly what a new team member needs access to in order to be able to +provide support. Adding an onboarding checklist[^1] that you validate often makes it +easy not to overlook an important account or piece of information. + +## Support phase +In an ideal world, the folks providing support will be the same folks who have been +working on the product. While we don’t often live in an ideal world, doing the work +to make support seamless for team members will also set external support people up +for success! + +These recommendations will help reduce the cognitive load of your support staff. Even +developers deeply knowledgeable about the product may forget obvious things to check +if they are tired or stressed about a highly visible incident. + +### Establish scope of support +Before the support phase begins, the team should align and document the scope of +support, and what responsibilities are expected of the support staff. The person +on-call should know definitively what is expected of them in different types of +scenarios, and whether they are in charge of troubleshooting, fully resolving or +escalating an incident. + +### Develop the infrastructure +18F should establish the go-to infrastructure for on-call support. This includes (but +is not limited to): +- An established alerting system with SMS, email, and (ideally) Slack integrations, +- A way for support staff and development team to manage on-call schedules, +- A way for support staff to be alerted and, +- A way for support staff to acknowledge an incident + +### Making pairing a priority +Pairing in the development phase will make your code more robust and spread expertise +across the team. In the support phase, making time for pairing sessions for newer or +non team members will make it easier for everyone to understand how the code works as +well as surface gaps in understanding and access. + +### Have easy entry-points for anyone +Developing a series of quick references for on-call staff will give them an entry +point into an incident. These can include: +- An incident response checklist, +- A quick reference troubleshooting guide that contains common/known issues and how to debug them, +- Timeline expectations (often defined in the compliance process), and +- An escalation chain so that the on-call staff knows who to contact if they need to; + - Escalate the incident or, + - Locate someone with specific area expertise + +### Create an incident response guide +Quick references are not enough! Your on-call staff needs an in-depth incident response +guide that includes an incident response checklist as well as documenting likely +scenarios will give anyone on-call guardrails to be successful. The documentation that +is generated during development can be directly applied into this guide, so the more +up-front work you do, the easier it will be! + +It is impossible to plan for every possible scenario[^2], but even common issues can +be difficult to keep top-of-mind if an incident happens in the middle of the night. +Creating step-by-step instructions will reduce cognitive load for the support staff, +reducing panic and allowing them to focus on the issue at hand. + +The guide should be: +- Located somewhere easily accessible, +- Written in as plain language as possible, +- Tested by the team and, +- If support includes non-team members, validated by someone not familiar with the development cycle + +The shape of this guide is outside the scope of this recommendation document; however, +it would greatly benefit 18F to develop a template for this and the quick references. + +The [login.gov guide](https://handbook.login.gov/articles/secops-incident-response-guide.html) +is a good starting place for thinking about what a guide can and should look like. + +### Test and iterate your support guides with simulations +Running “chaos engineering” simulations of incidents will allow you to test the +efficacy of your guides and quick references. Chaos engineering is the practice of +“experimenting” on a system to test resiliency. These exercises should be performed +before the production system goes live to test team readiness, as well as periodically +after go-live to continue improving team practices. + +The basic premise is to simulate an incident that could possibly occur in production, +and see how quickly and effectively the team can respond and resolve the issue. + +These simulations: +- Mimic incidents and measure your system’s ability to be resilient, +- Build confidence in the team’s ability to navigate and solve complex issues that may arise in production, and +- Expose systemic weaknesses that can be fixed + +Prioritize events that are likely to happen within the context of your system and have outsized impacts. Incidents that may be relevant include (but are not limited to) massive spikes in traffic or network outages. + +[^1]: See data.gov’s [new member issue template](https://github.com/GSA/datagov-deploy/blob/master/.github/ISSUE_TEMPLATE/onboard-team-member.md) as an example. +[^2]: For more in-depth information about developing resilient systems, see Logan McDonald’s Introduction to Resilience Engineering. Presentation [here](https://drive.google.com/file/d/18edrkHIemf1gvcekZOklmZx5Rvj4SzLv/view?usp=sharing), deck [here](https://docs.google.com/presentation/d/1W9wKibgBvxCFpvLPNtGnkPiPDigAE1ih7MFFwTduLGI/edit#slide=id.g5ecdbbee9e_0_0). \ No newline at end of file diff --git a/_guide/_pages/people.md b/_pages/people.md similarity index 87% rename from _guide/_pages/people.md rename to _pages/people.md index f1901c09..1e707341 100644 --- a/_guide/_pages/people.md +++ b/_pages/people.md @@ -3,31 +3,29 @@ title: Feedback Guide sidenav: approach sticky_sidenav: true --- - Here are some attributes of giving feedback in a highly constructive way that we have learned and used over the years. -### Timely +## Timely Ideally feedback, positive or negative, is given as close to the event as possible. Regular [1:1 meetings](https://handbook.18f.gov/one-on-ones/) are a great venue for delivering feedback. -### Evidence +## Evidence Gather evidence for the feedback instead of relying on vague reports or hunches. Have concrete examples, ideally more than one for negative feedback. -### Behaviors +## Behaviors Describe behaviors (is late to meetings) rather than traits or emotions (doesn't care about coworkers). You'll never know anyone else's thoughts, feelings, or motivations. You can observe behaviors in an objective and factual manner. This can be a hard habit change if you've built up years of giving feedback in the other way, but keep at it, it is worth switching. -### Results +## Results When you describe a behavior, also say the result. This goes for positive and negative feedback. "When you review pull requests right away, you really help the velocity of the whole team." "When you are regularly late for meetings, the effectiveness of the rest of the meeting is reduced because the meeting leader has to repeat information or wait for you." -### Future Focus +## Future Focus Don't dwell on the past, but focus on the future. The future can be altered, the past will never change. -### Top Performers +## Top Performers Giving constructive feedback to a top performer is not nitpicking, it is actually some of the highest leverage work we can do. Most folks (not everyone of course) are eager to hear ways they can keep growing. We don't help folks by having no ideas for them. -### End of Year Assessment Guides +## End of Year Assessment Guides TTS, as a part of GSA, has a mature [performance management and recognition system](https://insite.gsa.gov/portal/content/500278). This includes an end-of-year performance assessment. -* [2016 Assessment Guide]({{site.baseurl}}/people/2016-Assessment-Guide) -* [2017 Assessment Guide]({{site.baseurl}}/people/2017-Assessment-Guide) +* [Historical Engineering Assessment Guide]({{site.baseurl}}/people/assessment) diff --git a/_guide/_pages/people/2017-Assessment-Guide.md b/_pages/people/assessment.md similarity index 94% rename from _guide/_pages/people/2017-Assessment-Guide.md rename to _pages/people/assessment.md index 886c7a42..90fe1aa6 100644 --- a/_guide/_pages/people/2017-Assessment-Guide.md +++ b/_pages/people/assessment.md @@ -1,5 +1,7 @@ --- -title: 18F Engineering 2017 End of Year Assessment Guide +title: 18F Engineering End of Year Assessment Guide +sidenav: approach +sticky_sidenav: true --- 18F, as a part of GSA, has a mature [performance management and recognition system](https://insite.gsa.gov/topics/hr-pay-and-leave/employee-performance-management). @@ -8,6 +10,9 @@ engineers talk with their facilitator and supervisor about the past year and cre in the coming year. These reviews ideally build on a robust, granular, continuous feedback loop between an engineer, their facilitator, and other coworkers. +This guide is *historical* although still largely applicable, although there may be changes from current practices. +Please submit a PR if you see an explanation or process that needs updating! + Assessments are based on an individual’s performance plan. GSA’s Office of Human Resources Management (OHRM) has a [set of appraisal materials](https://insite.gsa.gov/topics/hr-pay-and-leave/performance-management/performance-management-appraising) applicable to all of GSA. These include a good guide on [Appraising Objectively and Fairly](https://insite.gsa.gov/cdnstatic/insite/Appraising_Objectively_and_Fairly.pdf), @@ -15,9 +20,6 @@ and the requirement to evaluate performance on a 5 point scale. Performance plan Some ratings can earn performance awards. You can find more detail, including what each rating number means, in the [Appraisal Rating System & Performance Awards](https://docs.google.com/document/d/1YtnP2RoSJZh5IiKWVJwxyAksjafCqlmBXspCV8nlhZM/edit) document. -End-of-year assessments are given to everyone hired into GSA on or prior to May 15, 2017, and are due by November 14, 2017. - -In September 2016, a group of Engineering leadership and engineers met to determine what outcomes we wanted from the end-of-year review process, and what we’d do to achieve those outcomes. This 2017 guide is largely the same as the 2016 guide. ## Desired outcomes @@ -106,7 +108,3 @@ Lastly, the engineer will need to sign the review. You’ll store those PDFs in ## Continuous feedback Our intention for this process is that it is part of a regular, granular feedback system. Engineers deserve frequent feedback on their performance. Our structure, where engineers will have an established relationship with their facilitator and supervisor, allows us to ensure that feedback happens. Providing regular feedback makes the annual review process a simple extension of regular feedback, as it is a culmination of the year’s progress. - -## Retrospective - -In November 2017 we will conducte a retro of the 2017 Engineering end of year assessment. We will ask ourselves how the process we used worked, and what we'd improve. Those in 18F will be able to review that document for details. diff --git a/_guide/_pages/project-setup.md b/_pages/project-setup.md similarity index 81% rename from _guide/_pages/project-setup.md rename to _pages/project-setup.md index 86a7db08..dbf79e4a 100644 --- a/_guide/_pages/project-setup.md +++ b/_pages/project-setup.md @@ -52,6 +52,21 @@ visual regression tests don't make sense for an API). 1. Integration test setup (e.g., [Selenium](https://www.selenium.dev/) {%include components/tag-suggestion.html %}) 1. Visual regression setup (e.g., [Backstop](https://github.com/garris/BackstopJS) {%include components/tag-suggestion.html %}) +## Branch protection {%include components/tag-requirement.html %} + +Set up branch protection rules for each repository. The [most current ATO checklist](https://github.com/18F/tts-tech-portfolio/blob/master/.github/ISSUE_TEMPLATE/ato.md) requires it; +it's also a good practice to prevent mistakes like an accidental force-push to main. + +We recommend at the very least enabling: +* Require pull request reviews before merging +* Restrict who can push to your main branch + +Please refer to GitHub's [branch protection documentation](https://docs.github.com/en/github/administering-a-repository/managing-a-branch-protection-rule) +to help determine what other configuration settings are best for your project. + +By default, protected branch rules do not apply to people with admin permissions to a repository, +allowing admins to merge PRs without an external review when necessary. + ## Project Management Tool Every project, no matter the size, should use a project management tool to keep @@ -59,8 +74,13 @@ track of ongoing tasks and to do items. The project management tool should be linked to somewhere in the project's GitHub repository so that others can find it easily. +Choose a tool that will work for you and your partner. Remember, they will be the ones +using it once the engagement is over! + - [GitHub Issues](https://guides.github.com/features/issues/) {%include components/tag-default.html %} - [Trello](https://trello.com/) {%include components/tag-suggestion.html %} +- [Jira](https://www.atlassian.com/software/jira) {%include components/tag-suggestion.html %} + ## Continuous Integration/Continuous Deployment @@ -89,7 +109,6 @@ are aggregated and reported on the entire project, in addition to reports on individual components. - [Code Climate Quality](https://codeclimate.com/quality/) {%include components/tag-suggestion.html %} -- [CodeCov](https://codecov.io/) {%include components/tag-suggestion.html %} ## Static analysis for code quality @@ -100,7 +119,8 @@ project, that might not be caught in a code review. Static analysis tools catch duplication, security concerns, and more. Also see [Static Security Analysis](https://before-you-ship.18f.gov/security/static-analysis/). -- [Code Climate Quality](https://codeclimate.com/quality/) {%include components/tag-suggestion.html %} +- [CodeQL on GitHub](https://docs.github.com/en/code-security/secure-coding/automatically-scanning-your-code-for-vulnerabilities-and-errors/setting-up-code-scanning-for-a-repository) (for security analysis) {%include components/tag-default.html %} +- [Code Climate Quality](https://codeclimate.com/quality/) (for maintainability metrics) {%include components/tag-suggestion.html %} ## Dependency management @@ -110,7 +130,7 @@ solution helps abstract that complexity and makes it easier for cross-functional teams to create consistent, reproducible, local development environments. - [Docker](https://www.docker.com/why-docker) {%include components/tag-suggestion.html %}
- See our [Docker for development](./docker/) recommendations. + See our [Docker for Development](../docker/) recommendations. ## Deployment infrastructure diff --git a/_guide/_pages/python.md b/_pages/python.md similarity index 96% rename from _guide/_pages/python.md rename to _pages/python.md index fd357df2..04614935 100644 --- a/_guide/_pages/python.md +++ b/_pages/python.md @@ -63,6 +63,8 @@ isort](https://pypi.python.org/pypi/flake8-isort) for import order. We ecosystem](https://pypi.python.org/pypi?%3Aaction=search&term=flake8&submit=search) for more functionality. +Use [Black](https://black.readthedocs.io/en/stable/) for automatic code formatting. + Using Code Climate to measure complexity scores (by way of [radon](https://pypi.python.org/pypi/radon)) is also a reasonable **default** to ensure you see potentially confounding functions and classes. @@ -80,7 +82,7 @@ recommend when trying to solve them. | ORM | [Django] | Default | | API | [Django Rest Framework](http://www.django-rest-framework.org/) | Default | | HTTP Client | [Requests](http://docs.python-requests.org/en/master/) | Default | -| Task Queue | [Celery](http://www.celeryproject.org/) | Suggestion | +| Task Queue | [Celery](https://github.com/celery/celery) | Suggestion | ## Type support diff --git a/_pages/release-strategies.md b/_pages/release-strategies.md new file mode 100644 index 00000000..c59e00fb --- /dev/null +++ b/_pages/release-strategies.md @@ -0,0 +1,123 @@ +--- +title: Releasing Software +sidenav: approach +sticky_sidenav: true +--- + +Releasing software is hard. Over time, we have developed strategies that can help reduce risk and uncertainity in the release process. + +## Small, iterative releases + +We recommend on all projects to get into the habit of releasing software as early and often as possible. The first +iteration of your software should not aim to have full functionality; a better goal for the very first release is to have as [little +functionality as possible](https://18f.gsa.gov/2017/01/11/the-best-way-to-build-big-is-to-start-small/#start-small-make-it-end-to-end). +A small-and-quick first release can help you [test your deployment pipeline and environments, while setting expectations for a rapid, +iterative release cadence](https://blog.thepete.net/blog/2019/10/04/hello-production/). + +## Big Bang Releases + +We do not recommend "big bang releases," defined here as when a team works many months on some code with the expectation that it will be +"turned on" in a big release event. We recommend, whenever it's possible, rapid release cycles and iteration, coupled with usability research. + +However, many times we are working on projects that, for reasons we cannot control, are scheduled for this kind of waterfall, big bang release, +and our partners are unable or unwilling to take our advice around an iterative rollout. While releasing a lot of software into the wild all +at once is inherently more risky than an iterative roll-out, we have identified ways that may help you mitigate this risk. And even if you're +already practicing rapid, iterative releases, the tips here may offer ways you can improve your releases. + +### When a Big Bang release is necessary + +#### Give your team a lot of time + +Recommendation: Give yourselves *at least* a month to address issues that may be hard to predict before the release deadline. + +Big bang releases heighten the risk of unknowns that can crop up as the release date looms closer. Estimate your time very conservatively +and set expectations with your partner to allow space and time for your team, leading up to the release date, to address unexpected critical +issues. + +#### Release to different user groups at different times + +Recommendation: Release to a subset of users at a time. This lets you test, creates a better user experience for them, and a better time +post-release for your team. + +There are always going to be immediate bug fixes and customer asks in the aftermath of a release. +Initally scoping a big release to a subset of user types at a time will narrow the developer and customer success team's focus, making +debugging and prioritizing fixes easier. + +#### Practice data migrations often + +Recommendation: Do dry runs of any critical data or infrastructure migrations. + +Practice makes perfect! Try out your migrations regularly in the months leading up to the release so that everyone feels very comfortable +with how they work and what to expect. + +#### Develop mature incident response practices + +Recommendation: Build [Incident Response practices and run drills](/security/incident-response-drills/) before releasing. + +It's impossible to completely de-risk a release. Developing a plan ahead of time addressing how you will approach an incident will +enable your team to focus on fixing the issue as soon as possible. Once you have a response plan, you should conduct +[incident type drills](/security/incident-response-drills/#example-incident-response-drills) so that your team is well-practiced in +what do if something goes wrong. + +#### Develop training strategies in advance + +Recommendation: Conduct usability research and develop training strategies ahead of time to help users ease into the new system. + +It can be jarring as a user to be surprised by a completely new system. Spending some time before release working with critical users of the +system to understand the common pitfalls a user may experience or uncover will help you develop training materials to address those issues +(or make the system more intuitive). Releasing training materials for users to look at before the release will create better familiarity and +make users less wary or uncomfortable with the big change. Your critical users can then become effective evangelists and trainers post-release +for others suddenly learning the new system. + +#### Prepare customer support response templates + +Recommendation: Develop templates and scripts so that expected support requests have consistent messaging and advice. + +Launches often have predictable support requests, such as: +* "Why doesn't the system do X?" +* "This is broken." +* "I can't find Z." + +Preparing responses ahead of time allows the customer support team to give the same suppport to anyone facing a predictable issue, allowing them +to focus their energies on unexpected support needs. It also helps ensure a better, customer experience as users are consistently given +thorough and well-thought-out answers to these common problems. + +### Pushing back against Big Bang Release releases + +Partners are often deeply attached to big bang releases, but there are strategies you can deploy to try to convince partners to pivot to a +smaller, more iterative release strategy. + +These factors are often project signs that a project may have some trouble brewing. If you are seeing any of these factors with your +partner, consider logging them as risks in your project health tracking. + +#### The partner doesn't want to pick a cohort of controlled users + +Understanding why a partner doesn't want to single out some controlled users is important. They may be nervous about creating inequity (or +a perception of inequity) that might have some political blowback. Perhaps they feel overwhelmed about the effort required to narrow down +to a subset of users, and so feel it's simpler to release to all users at once. + +*Mitigation strategies:* +* Listen to and discuss fears with your partner to fully understand their reluctance. +* Frame this step as the first of many interactions with their different user groups, and use that framing to help them better engage and +understand their users. Having a more mature idea of their user groups will help them have confidence to stand behind their decisions better. + +#### A long, arduous ATO process + +Partners have a valid fear of the ATO process, and may be nervous that they must repeat the ATO process every time a change is made to the +system. That perspective easily lends itself to fear of iterative releases. + +*Mitigation strategies:* +* Engage security and ATO personnel early in the development process, or, ideally, embed someone onto the project team who can help advise. This strategy (among other improvements) helped GSA bring average ATO time from [six months to thirty days](https://18f.gsa.gov/2018/07/19/taking-the-ato-process-from-6-months-to-30-days/). +* Familiarize yourself with TTS's [Launching Software](https://handbook.tts.gsa.gov/#launching-software) strategies so you can personally help alleviate some of their concerns. +* Teams at 18F have also found success in employing the "Walking Skeleton" technique, where the main architectural components of a system are +deployed early in a minumum viable way. Frontloading the infrastructure work creates an MVP for ATO work, and makes space for early +compliance and security oversight. + +#### Legislative mandate + +When the system is a byproduct of a legislative mandate, there can be political or legal implications if a deadline is missed. A mandate +for a specific type or level of service may make partners wary of more iterative work. + +*Mitigation Strategies:* +* Explore options for beta or trial release of services. Sometimes releasing a website or digital service under the banner of +"beta" can provide needed flexibility for a rollout, making a big bang release less necessary. diff --git a/_guide/_pages/resources.md b/_pages/resources.md similarity index 72% rename from _guide/_pages/resources.md rename to _pages/resources.md index 18853ce8..6c7c2c37 100644 --- a/_guide/_pages/resources.md +++ b/_pages/resources.md @@ -11,9 +11,11 @@ This guide evolved from work spearheaded by the 18F Engineering Chapter and the ## Related links -- [TTS Before You Ship](https://before-you-ship.18f.gov/) +- [Launching software at TTS](https://handbook.tts.gsa.gov/#launching-software) - [18F De-risking guide](https://derisking-guide.18f.gov/) - [Agile Principles and 18F Practices](https://agile.18f.gov/) +- [18F guide to Consulting Engineering](https://handbook.tts.gsa.gov/18f/projects-partners/consulting-engineering-guide/) +- [18F Engineering Field Guide](https://docs.google.com/document/d/1ipYaMx2oyuI4RUMdiDgIG1Q4BiiWZn6cVXp6-RcMFjI) - [U.S. Web Design System](https://designsystem.digital.gov/) - [Cloud.gov Production-ready guide](https://cloud.gov/docs/deployment/production-ready/) - [Login.gov Identity Playbook](https://login.gov/playbook/) diff --git a/_guide/_pages/ruby.md b/_pages/ruby.md similarity index 81% rename from _guide/_pages/ruby.md rename to _pages/ruby.md index 6f00f1fb..725cc377 100644 --- a/_guide/_pages/ruby.md +++ b/_pages/ruby.md @@ -3,14 +3,13 @@ title: Ruby Guide sidenav: languages sticky_sidenav: true --- -This is a **WORK IN PROGRESS**. Help us make it better by +Help us make this section better by [submitting an issue](https://github.com/18F/development-guide) or joining us in the [#ruby](https://18f.slack.com/messages/ruby/) channel! -## Ruby Guide A guide for writing and maintaining Ruby and Rails applications -### Style Guide +## Style Guide Follow the [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) and enforce it via static analysis tools such as [Code Climate] and [Rubocop]. You @@ -25,5 +24,13 @@ Whenever a `Style` Rubocop setting provides multiple options, at least one option must be chosen. A cop that supports different styles must never be disabled outright. The point is to pick one style and use it consistently. +## Testing + +### Validating HTML output + +We use HTMLProofer for testing rendered HTML automatically. Please see +the [test page] for more details. + [Code Climate]: https://codeclimate.com [Rubocop]: https://github.com/bbatsov/rubocop +[test page]: /tests#html-output-ruby diff --git a/_guide/_pages/ruby/rubocop.yml b/_pages/ruby/rubocop.yml similarity index 100% rename from _guide/_pages/ruby/rubocop.yml rename to _pages/ruby/rubocop.yml diff --git a/_pages/security.md b/_pages/security.md new file mode 100644 index 00000000..227c9b4d --- /dev/null +++ b/_pages/security.md @@ -0,0 +1,83 @@ +--- +title: Security +sidenav: security +sticky_sidenav: true +--- + +Security is everybody's responsibility at TTS but if you're not used to thinking about security in your day-to-day job, +that's understandable. We come from a range of different backgrounds, some of which involved security more than others. + +There are practices that we as developers should adhere to as much as possible when building websites. We aim to give everyone +a framework to think about security, and ways to approach it with our partners. + +This is an ever-expanding list; if an important issue is unrepresented, please feel free to open up a PR with your expertise +or add an issue! + +## FISMA +Every system you'll work on at TTS has a FISMA level of impact. +The [Federal Information Security Modernization Act](https://www.cisa.gov/federal-information-security-modernization-act) +(FISMA) was introduced to ensure that all government systems have a framework to handle confidential and sensitive information +in a secure way. + +The impact level of a system is determined by how adverse the impact would be if the confidentiality, integrity and/or +availability of system was compromised. + +``` +The potential impact is LOW if the loss of confidentiality, integrity, or availability could be expected to have a limited adverse effect on organizational operations, organizational assets, or individuals. +... +The potential impact is MODERATE if the loss of confidentiality, integrity, or availability could be expected to have a serious adverse effect on organizational operations, organizational assets, or individuals. +... +The potential impact is HIGH if the loss of confidentiality, integrity, or availability could be expected to have a severe or catastrophic adverse effect on organizational operations, organizational assets, or individual +``` +[Standards for Security Categorization of Federal Information and Information Systems](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.199.pdf) + +## When Should I Be Thinking About Security? + +The short answer: Always! + +Some longer answers: + +### When starting work on a new system + +When starting work on a brand new system, it can feel like everything is going to go perfectly! But it's important to begin +building keeping in mind that things can (and likely will!) go wrong in unexpected ways. + +Make sure you, or the system owners, have a way of knowing when something goes wrong. Start by asking some difficult questions: + +* How will we know if the system is hacked? +* How will we know if there is a data leak? +* What will happen if there is a data breach? +* What is our escalation policy when things go wrong? + +If the project requires an [ATO](https://atos.open-control.org/) (or has one already), some of these topics may be explicitly covered in that process. Even if an ATO is not required, these are still important questions to ask. + +### When starting work on an existing system + +Ideally, every vendor would be employing security best practices! But sometimes we'll start working on a project, and encounter a security +flaw or potential breach that needs to be addressed ASAP. While those flaws need to be escalated, we should be thinking about how to +communicate those kinds of issues without potentially alienating important relationships. + +*Before* getting access to a project's code base, it's a good idea to ask about a preferred escalation policy. + +* If I see a security problem, what is the best way to communicate that? +* If it's an issue that needs to be addressed immediately, how should we work together to escalate? + +Premptively asking these questions can help keep focus on the security issues at hand if you immediately see problems when you get code +access -- and having an answer to those questions is important for every project! + +After you get access, it's a good idea to ensure that there are also answers to the questions listed in the New System section + +### Data Flow + +Security is paramount when thinking about how data flows into, through, and out of your system. + +When the boundaries of different systems or domains bump up against each other, there are opportunities for security breaches. +These "boundaries" can be in forms such as: + +* third party API +* installed agent +* form that posts input to your database +* downloading/uploading to any part of the cloud +* webhook integration + +Thinking about the edges of your system, how they're exposed, and to whom will help you make better decisions about security. \ No newline at end of file diff --git a/_pages/security/cloud-services.md b/_pages/security/cloud-services.md new file mode 100644 index 00000000..d1b9d7d8 --- /dev/null +++ b/_pages/security/cloud-services.md @@ -0,0 +1,86 @@ +--- +title: Cloud Services +sidenav: security +sticky_sidenav: true +--- +A common practice is storing files in the cloud; places like [Amazon Simple Storage Service](https://docs.aws.amazon.com/s3/index.html) +(Amazon S3), [Google Cloud](https://cloud.google.com/storage/docs/introduction), or +[Azure Storage](https://docs.microsoft.com/en-us/rest/api/storageservices/delegate-access-with-shared-access-signature). +These services give developer an easy way to store data in the cloud, and download it when needed. But this +introduces security considerations. + +When thinking about how to upload or download data in your application, there are always tradeoffs to think about -- often +processes that are easier to use are less secure; likewise a workflow that is more complex is often more secure. + +These tradeoffs get more significant depending on the FISMA level of your system. + +## Presigned URLs +A common method of allowing users to transfer data without credentials is to use [presigned urls](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ShareObjectPreSignedURL.html). +(Azure refers to these as [shared access signatures](https://docs.microsoft.com/en-us/azure/hdinsight/hdinsight-storage-sharedaccesssignature-permissions), but they are a similar concept.) + +There are some differences between service providers; the below details are specific to S3 as that has +been our most common use case and is supported by [cloud.gov](https://cloud.gov/docs/services/s3/). + +### Some Things to know about S3 presigned URLs +* They can be reused until they expire + * Default expiration time is 15 minutes +* They can be used by *anyone* +* There is no default file size limit on uploads +* Uploads use PUT by default + +A presigned URL is an *easily-shareable* URL that is generated with an authenticated user's security credentials. They +are created with specific actions attached to them, as well as an expiration date and time; the URL will remain valid +until that expiration moment. + +A shareable URL that bypasses security authentication is very convenient to use! However, the tradeoff is that anyone +with access to that URL can use it. If a user for some reason decided to post a presigned upload URL to the internet, +anyone could use that URL to upload data to your bucket until the expiration time was passed. + +This introduces a "user error" or "insider threat" security vulnerability to your system. Even if your users are good actors, +some attack vectors could be: +* A bad actor scanning spaces of URLs to find publicly-available files. +* Anything with access to the client would have access to the URLs and the accompanying actions - this could include an installed untrustworthy browser extension. + +### FISMA Low: +Be cautious but proceed with presigned URLs if you feel it is the right choice for your system. + + We recommend taking [mitigation steps](#mitigation-steps) to secure your system. + +### FISMA Medium: +Really consider the tradeoffs. What kind of adverse impact might happen if a bad actor gets hold of a presigned URL to your system? + +* Can they access PII? +* Can they upload junk data or other harmful information? + +If you've thought things through and it's the best or only option, proceed but definitely take [mitigation steps](#mitigation-steps) +to secure your system. + +### FISMA High: +{%include components/tag-caution.html %} We do not recommend using presigned URLs for this kind of system. The only real barrier +between a bad actor and user data is the obscurity/randomness of the URL and the expiration duration. + +### Mitigation Steps +**All Actions** +* Generate expiration times that are *very* short lived -- think seconds rather than minutes. +* Don't log unencrypted presigned URLs + +**Upload Actions** +* Use a [POST action](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-UsingHTTPPOST.html) rather than PUT +* Construct a [POST policy](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html) to + * limit file size as appropriate to your use case + * limit file type as appropriate to your use case +* Scan for viruses + +## Proxying the file download + +This option is less "convenient" in that there is no easily-shareable URL that is generated. However, if your +system has a higher FISMA impact level, or if you don't need to generate a shareable URL, this is often a more +secure option. + +This will be more specific to your server, but the basic steps are: + +* Create an endpoint in your server that the client can call +* Check authentication and authorization when the endpoint is hit + * Gracefully capture the issue and respond with an error if the client is not authorized for this action +* If the client is authenticated and authorized, construct an authenticated GET to the cloud provider +* Serve the file to the client as a response to the endpoint \ No newline at end of file diff --git a/_guide/_pages/security/content-security-policy.md b/_pages/security/content-security-policy.md similarity index 99% rename from _guide/_pages/security/content-security-policy.md rename to _pages/security/content-security-policy.md index decf2a4a..a48e1dd9 100644 --- a/_guide/_pages/security/content-security-policy.md +++ b/_pages/security/content-security-policy.md @@ -18,7 +18,7 @@ All of the above supported browsers support CSP 1.0, with 100% support for 2.0 i ## Usage CSP is straigtforward to implement, and supports providing a policy server-side [via HTTP header](#server-side-implementation) or client-side via a [`` tag](#client-side-implementation). -#### Policies +### Policies The most important aspect of CSP is the policy itself, which is written as a string of **directives**. Directives describe how the browser should handle loading different content types. These directives are represented as a `;` delimited key-value pair. The values in this pair can either be **keywords**, **schemes**, **mime-types**, or **urls**. Keywords are always enclosed in single quotes, while all other values are left unquoted. Multiple values may be supplied in a single directive, they are always separated by a space. @@ -52,7 +52,7 @@ The `default-src` directive should always be defined! This directive acts as a f It might be useful to test your policies before letting them loose on your users. To do this, use the `Content-Security-Policy-Report-Only` HTTP header. Combined with the reporting information in the next section, you can monitor the kinds of content your user's are encountering and tweak the your policy accordingly. -#### Reporting +### Reporting CSP can also be configured to send reports to an endpoint you control when content that violates your policies is encountered. To do this, use the `report-uri` directive, passing it a fully qualified URI, e.g. `https://my-public-site.gov/reports/csp`. Now, each time content from an invalid source is encountered, your browser will POST a JSON payload to the provided URI. diff --git a/_pages/security/dependency-remediation.md b/_pages/security/dependency-remediation.md new file mode 100644 index 00000000..c1626b13 --- /dev/null +++ b/_pages/security/dependency-remediation.md @@ -0,0 +1,74 @@ +--- +title: Remediating vulnerable dependencies +sidenav: security +sticky_sidenav: true +--- + +Your application should have dependency scanning to ensure that the +libraries your code relies on do not have vulnerabilities within them. +For more on how to set up vulnerability scanning see the +[Before You Ship +guide](https://before-you-ship.18f.gov/security/static-analysis/#dependency-analysis)’s +suggestions. + +In operating a system with a dependency scan you’ll find that +vulnerabilities do pop up in your dependencies, and this is a guide on +how to remediate those vulnerabilities to keep your application secure. + +The following suggestions are in the order in which you would try these +strategies. + +## Apply a patch + +Oftentimes when your dependency scanner finds a vulnerability, it will +provide a suggested patch to remediate the vulnerability. If the scanner +doesn’t provide a patch a quick search of the package’s documentation +may also reveal a patch that you can use. In this case, create a new +branch via git version control and ensure that your tests pass; that the +application still runs as expected; and finally, run your code with your +continuous integration suite. If there are unexpected behaviors or +failing tests, you may have to refactor your code to incorporate the +patch. Once you’ve applied the patch and refactored it, you can submit a +pull request to fix your application. + +## Use selective resolutions + +In some cases, your dependency scanner will not be able to provide an +immediate patch but it will indicate a package version in which the +vulnerability is fixed. In some package managers such as \`yarn\` you +can pin your dependency to the fixed version by using a +“[selective +resolution](https://classic.yarnpkg.com/en/docs/selective-version-resolutions/)”. +This will bump up versions that are children of top level dependencies. +If you are using \`npm\` you can install +\`[https://www.npmjs.com/package/npm-force-resolutions](https://www.npmjs.com/package/npm-force-resolutions)\` +to draw the same behavior. + +## Check if it is a false positive + +If there is no existing patch or version update that will remediate the +vulnerabilities, you may want to investigate the offending code and see +if your use of that library would even trigger that part of the code. If +it does not, the vulnerability may be a false positive. If you can +confirm this, you should document this — ideally in your dependency +scanners configuration (ex. .snyk) or somewhere within your code +repository. + +## Pull upstream + +In cases where the maintainer of a package has not yet resolved the +security vulnerability and you are able to patch it yourself, fork the +original package to fix it locally and then create a pull request in the +package repository. Not only does this help fix the security concern, +but also promotes good open-source culture. Because this requires the +maintainer of the package to review and accept your pull request, this +strategy may take longer to complete. If your pull request is accepted, +be sure to update your dependency file back to the main distribution of +the dependency. + +## Accept the risk + +If the risk is low, take a look at where the vulnerability resides in +your dependency tree. If the vulnerability is associated with a +development dependency rather than with public code, the risk associated +with the vulnerability might be acceptable (in the short term). diff --git a/_pages/security/incident-response-drills.md b/_pages/security/incident-response-drills.md new file mode 100644 index 00000000..8d3959c0 --- /dev/null +++ b/_pages/security/incident-response-drills.md @@ -0,0 +1,230 @@ +--- +title: Incident Response Drills +sidenav: security +sticky_sidenav: true +--- + +*Table of Contents* + +* [Why do Incident Response Drills?](#why-do-incident-response-drills) +* [How to Build Incident Response Drills](#how-to-run-an-incident-response-drill) +* [Example Incident Response Drills](#example-incident-response-drills) +* [Using this Drill as Part of Your ATO](#congratulations-you-accidentally-did-compliance-too) + +## Why do Incident Response Drills? + +You don't want to be creating or testing recovery processes while things are on fire. 🔥 + +When things are on fire, you want to be able to focus on fixing the issues and getting your system back online and in working order as soon as possible. Having an already established incident recovery practice will allow you and your team to focus on the problem, rather than the process. + +Preparing and practicing ahead of time is a good idea. Running incident response drills on an annual basis at the very least is a good idea! + +## How to Run an Incident Response Drill + +### Identify Your Top Risks + +First, create a [boundary diagram](https://www.fedramp.gov/assets/resources/documents/CSP_A_FedRAMP_Authorization_Boundary_Guidance.pdf) if you don't already have one. You will very likely need to create a boundary diagram as part of your system's security and compliance process, anyway. + +Then, review your boundary diagram and determine where your system can be accessed. Make sure that you include third party products (analytics, CI/CD pipelines, code hosting) in this analysis. + +Look at each box and each connection on the diagram separately. Figure out how someone who isn't supposed to be there could get there, or how each component could fail unexpectedly. + +This will help you build a set of incident scenarios to practice recovering from. + +### Gather Organizational Policies + +It is likely that your Agency or OCIO has existing policies around reporting for security or data breach incidents. Gather them to ensure they are built into your response. + +### Create the Drill + +See [Example Incident Response Drills](#example-incident-response-drills) for inspiration! + +### Invite Everyone to the Drill + +Be sure to invite developers, infrastructure, and compliance professionals on your team to the drill. An open invitation for your team is a good idea! Letting the team know that you're doing this kind of activity builds confidence and assurance that the team takes security seriously. + +Give advance warning to any third parties that might want to know that you're planning an incident response drill, such as cloud.gov or login.gov. + +Schedule more time than you think you will need! If you schedule half a day, you may find you'll need the whole day! + +Ask for a volunteer to take notes throughout the incident response drill. + +### Conduct the Drill + +Follow the steps in the drill, making sure good notes are taken. + +Team members can rotate being the "driver" who shares their screen and walks through the steps in the drill. + +![Image of a hardware drill]({{site.baseurl}}/assets/images/drill-small-wikimedia.png) + + This is a drill.
Image attribution: Włodzimierz Wysocki. License: CC BY-SA 3.0
+ + +### After the Drill + +You could end the drill with a practice "blameless post-incident retrospective." This is a low-pressure way to figure out your team's format for conducting retrospectives after an incident. + +[cloud.gov's retrospective meeting guide](https://cloud.gov/docs/ops/service-disruption-guide/#retrospective-meeting-guide) has ideas and checklists for organizing a successful post-incident retrospective. + +Send an email recapping the drill to all stakeholders. Include the outcomes of the drill, what you learned from the drill, and any follow-up actions. + +## Example Incident Response Drills + +Scenarios worth practicing for a web app include: + +* [Scenario: A Deploy Goes Wrong](#scenario-a-deploy-goes-wrong) +* [Scenario: API Keys or Passwords Exposed](#scenario-api-keys-or-passwords-exposed) +* [Scenario: Compromised Account](#scenario-compromised-account) +* [Scenario: PII Exposed](#scenario-pii-exposed) +* [Scenario: Oops, I Deleted the Database](#scenario-oops-i-deleted-the-database) +* [Scenario: Oops, I Erased the S3 Bucket](#scenario-oops-i-erased-the-s3-bucket) + +You don't need to drill each and every one of these scenarios each time, but they are good to plan for. + +These examples are for a web application hosted on [cloud.gov](https://cloud.gov) that generally follows [our approach](/workflow). + +Please adjust for your infrastructure. + +## Scenario: A Deploy Goes Wrong + +It turns out, the new release doesn't deploy properly. It has successfully deployed in all the other environments. Let's re-deploy. + +![Rerun job workflow in CircleCI]({{site.baseurl}}/assets/images/rerun-workflow-circleci-screenshot.png) + + Screenshot of how to re-run a workflow in a CI/CD tool (in this case, CircleCI) + + +### Example mitigation steps: + +Re-deploy last successful release from your CI/CD pipeline. (You are deploying from a CI/CD pipeline, right?) + +1. Go to `<>` to view recent deploys. +1. Rerun the deploy step for the last known-good deploy. +1. If necessary, roll back the database to the correct version. `<>` + +### Example drill: + +Follow the mitigation steps above in a development environment. + +## Scenario: API Keys or Passwords Exposed + +An API Key for an AWS service was accidentally committed to our public code repository! (Use tools like [caulking](https://github.com/cloud-gov/caulking) to prevent issues like this from happening in the first place.) + +### Example mitigation steps: + +1. Contact `<>` and inform them of a breach. +1. Write down which keys and services were exposed. +1. Rotate all exposed keys. +1. Remove any exposed keys from the commit history. + +### Example drill steps: + +1. Acknowledge that the first step would be to inform points of contact; establish that everyone knows who to inform in the event of an incident. +1. To simulate the real thing, push up a file to GitHub or whichever code repository is in use with a fake service key. (No using real keys for drills, please.) +1. Practice rotating the keys for that service in a development context. +1. Practice scrubbing the fake key from the commit history. + +## Scenario: Compromised Account + +The website has been hacked due to a compromised key! Now instead of our link to submit a report, we have a cute image of a cat and a spam link to follow cute cats on instagram. + +![Screenshot of Engineering Practices Guide homepage with cute cat photo in the middle of it]({{site.baseurl}}/assets/images/screenshot-fake-epg-hacked.png) + + Oh no! Who added this cute cat photo to our website?!?
Photo attribution: Tran Mau Tri Tam. Unsplash License.
+ + +What happened? Was a GitHub account compromised? A cloud.gov account? A deploy key? + +### Example mitigation steps: + +1. Contact `<>` and inform them of a breach. +1. The first priority is to remove the unauthorized access so that there can't be further damage or information leakage. Figure out where the deploy came from. + * *If the deploy was triggered from GitHub*, you would be able to see it in CI/CD history. In this case, the GitHub admin should immediately remove the account that triggered the malicious deployment. Rotate any deploy credentials that may have been compromised. + * If you don't see the deploy in CI/CD, that means either deployment keys were compromised, or a cloud.gov account was compromised. Look at the logs to see which deployment method was used. + * *If you see that the deploy came from a compromised cloud.gov account*: Remove the compromised account from the org, all spaces (starting with prod), and all application (starting with prod apps). + * *If you see that the deploy came from a compromised deploy key*: In cloud.gov delete the current deployment keys, remake them and add the new keys to your CI/CD tool. +1. Isolate resources: incidents that are likely to be malicious need to be handled with care to preserve forensics. The most important things to remember: do not delete an instance that has been tampered with, and do not redeploy from the last release without removing routes and renaming the instances. That could get rid of valuable forensic information. Instead: + * Remove the route to the affected instances. (This will make the bad deploy inaccessible to the public.) + * Rename the instance. (This will preserve forensics as you redeploy.) + + +### Example drill steps: + +1. Acknowledge that the first step would be to inform points of contact; establish that everyone knows who to inform in the event of an incident. +1. Choose a scenario to drill: compromised GitHub account, compromised cloud.gov account, or compromised deploy key. (Compromised deploy key might be easiest to drill.) +1. Practice the steps to remove compromised accounts or credentials, for example, by deleting the current deployment keys, remaking them, and adding them to CI/CD. +1. Using a development application instance, practice removing the route to a instance that may have been compromised and then renaming it to preserve forensics. + +## Scenario: PII Exposed + +It's discovered that PII is being leaked to unauthorized users through the site. + +### Example mitigation steps: + +1. Contact `<>` and inform them of a breach. +1. Stop the exposure. + * Assess the severity and impact of the potential leak. + * Decide if the site needs to be set into a maintenance mode to stop further exposure. If yes, then bring up the maintenance page. + * If you are able to isolate the section of the site where the issue is occurring and remove/hide the page. +1. Identify root cause of the issue and deploy a hotfix. +1. Take necessary corrective action as directed by your agency security team. If there are corrective actions that the PO is able to handle in terms of contacting the affected users, do so. + +### Example drill steps: + +1. Acknowledge that the first step would be to inform points of contact; establish that everyone knows who to inform in the event of an incident. +1. In a development environment, practice putting the site into a maintenance mode or removing/hiding a page on the site, whichever would be most relevant to your project. +1. Review any relevant corrective action / affected user notification procedures. + + +## Scenario: Oops, I Deleted the Database + +The database needs to be restored from a backup. + +### Example mitigation steps: + +1. If you're using cloud.gov, follow [cloud.gov database backup procedures](https://cloud.gov/docs/services/relational-database/#backups). + +### Example drill steps: + +Assuming you have a staging database using a dedicated cloud.gov database plan: + +1. Delete some data from your staging database. (No deleting data from a production database, please.) +2. Reach out to cloud.gov using the [the non-emergency email address provided in thir docs](https://cloud.gov/docs/services/relational-database/#backups); request a backup. +3. Practice restoring the staging database to the point in time before you deleted the data. + +## Scenario: Oops, I Erased the S3 Bucket + +Let's re-create and restore from a backup. + +### Example mitigation steps: + +1. If the bucket no longer exists, create a new bucket in cloud.gov in the space where the bucket was deleted, ideally using infrastructure-as-code or a deploy script. +2. Restore bucket contents from a backup. +3. Verify the bucket settings, permissions, and contents are correct. + +### Example drill steps: + +Follow the mitigation steps above in a development environment. + +## Congratulations, you accidentally did compliance too! + +For your project, you will need an [ATO](https://before-you-ship.18f.gov/ato/). Part of that ATO is providing required documentation of controls. Controls are different security considerations. This process varies from agency to agency, so, work with your security partners to know which controls they need documented. Don't forget that you can inherit a substantial number of [controls by using cloud.gov](https://cloud.gov/docs/security/conforming-federal-security-regulations/) and you just need to reference that it's covered. The [Before You Ship guide](https://before-you-ship.18f.gov/) is a great resource for ATOs. + +By doing this exercise, you have artifacts (proof that you are in compliance) and documentation that you can reference or pull from for your System Security Plan. Based on the needs of your security partners and the project, you may also need additional documentation or to reference cloud.gov or AWS GovCloud's controls. The following examples are just meant as a starting point. + +Contigency Planning + - [CP-2 (5) Contingency plan](https://csrc.nist.gov/Projects/risk-management/sp800-53-controls/release-search#!/control?version=5.1&number=CP-2) Your troubleshooting doc is a contingency plan for your app! This document can complement existing agency contingency plans. Depending on what your security partners need, you can also make it easy to audit by naming headings like "Contingency plan," "Incident response," "Disaster Recovery," etc. + - [CP-2 (7) Contingency plan: coordinate with external service providers](https://csrc.nist.gov/Projects/risk-management/sp800-53-controls/release-search#!/control?version=5.1&number=CP-2) If you did a data deletion drill in coordination with cloud.gov, you can reference that here. + - [CP-3 Contingency training](https://csrc.nist.gov/Projects/risk-management/sp800-53-controls/release-search#!/control?version=5.1&number=CP-3) Your drill is training on your contingency plan. For artifacts, you can use what you wrote from your recap email and your drill document. + - [CP-4 Contingency plan testing](https://csrc.nist.gov/Projects/risk-management/sp800-53-controls/release-search#!/control?version=5.1&number=CP-4) Your drill tested your contingency plan. For artifacts, you can use what you wrote from your recap email and your drill document. + +Training + - [AT-3(3) Role-based training: practical exercises](https://csrc.nist.gov/Projects/risk-management/sp800-53-controls/release-search#!/control?version=5.1&number=AT-3) Your drill was a practical exercise. For artifacts, you can use what you wrote from your recap email, your drill document and the practice post-incident retrospective write up. + - [AT-3(5) Role-based training: processing personally identifiable information](https://csrc.nist.gov/Projects/risk-management/sp800-53-controls/release-search#!/control?version=5.1&number=AT-3) If you run your drill using the PII scenario, that would speak to this control. For artifacts, you can use what you wrote from your recap email and your drill document. The government training (those courses in OLU, for GSA) count for this as well. + +Incident Response + - [IR-2 Incident response training](https://csrc.nist.gov/Projects/risk-management/sp800-53-controls/release-search#!/control?version=5.1&number=IR-2) Your drill is incident response training for your application. For artifacts, you can use what you wrote from your recap email and your drill document. + - [IR-3 Incident response testing](https://csrc.nist.gov/Projects/risk-management/sp800-53-controls/release-search#!/control?version=5.1&number=IR-3) Your troubleshooting drill included a security incident. You also may find a few bumps along the road as you do your drill, document those issues and any remediations you make. For artifacts, you can use what you wrote from your recap email, which should include that information. + +System Inventory + - [CM-8 System component inventory](https://csrc.nist.gov/Projects/risk-management/sp800-53-controls/release-search#!/control?version=5.1&number=CM-8) Use your network diagram and prep as a way to have an accurate network diagram. Keep the doc in a place that the team has access and that maintainers can edit and update it. Your network diagram and READMEs make good artifacts for this. diff --git a/_guide/_pages/security/output-encoding.md b/_pages/security/output-encoding.md similarity index 100% rename from _guide/_pages/security/output-encoding.md rename to _pages/security/output-encoding.md diff --git a/_guide/_pages/sharepoint.md b/_pages/sharepoint.md similarity index 97% rename from _guide/_pages/sharepoint.md rename to _pages/sharepoint.md index c10aa339..9b9abbd5 100644 --- a/_guide/_pages/sharepoint.md +++ b/_pages/sharepoint.md @@ -135,14 +135,15 @@ connected to other live data sources. The disadvantage is that Power BI is another complicated tool for developers to learn and it requires that the source data be available in a structured format that Power BI can access. -### Power Flow - -Another one of Microsoft’s "Power" tools, Power Flow is not a display tool, -but it is a workflow automation system. If we need notifications or messages -to be sent out when certain things happen on SharePoint or with various -documents, then we can configure a Flow to do those actions. This may not be a -large part of a SharePoint site, but it could be an important capability if -needed. +### Power Automate + +Another one of Microsoft's "Power" tools, Power Automate, is not a display tool, but it is a workflow automation system. If we need +* to move data between systems, +* send notifications or messages when certain things happen on SharePoint or with various documents, +* connect to or create connectors to APIs, +* approval processes, + +then we can configure a Flow to do those actions. This may not be a large part of a SharePoint site, but it could be an important capability if needed. ## SharePoint Development Process diff --git a/_guide/_pages/sharepoint/client_side.png b/_pages/sharepoint/client_side.png similarity index 100% rename from _guide/_pages/sharepoint/client_side.png rename to _pages/sharepoint/client_side.png diff --git a/_guide/_pages/sharepoint/dev_architecture.png b/_pages/sharepoint/dev_architecture.png similarity index 100% rename from _guide/_pages/sharepoint/dev_architecture.png rename to _pages/sharepoint/dev_architecture.png diff --git a/_guide/_pages/sharepoint/dev_workflow.png b/_pages/sharepoint/dev_workflow.png similarity index 100% rename from _guide/_pages/sharepoint/dev_workflow.png rename to _pages/sharepoint/dev_workflow.png diff --git a/_guide/_pages/sharepoint/embedded_excel.png b/_pages/sharepoint/embedded_excel.png similarity index 100% rename from _guide/_pages/sharepoint/embedded_excel.png rename to _pages/sharepoint/embedded_excel.png diff --git a/_guide/_pages/sharepoint/power_app.png b/_pages/sharepoint/power_app.png similarity index 100% rename from _guide/_pages/sharepoint/power_app.png rename to _pages/sharepoint/power_app.png diff --git a/_guide/_pages/sharepoint/power_bi.png b/_pages/sharepoint/power_bi.png similarity index 100% rename from _guide/_pages/sharepoint/power_bi.png rename to _pages/sharepoint/power_bi.png diff --git a/_guide/_pages/sharepoint/sharepoint_list.png b/_pages/sharepoint/sharepoint_list.png similarity index 100% rename from _guide/_pages/sharepoint/sharepoint_list.png rename to _pages/sharepoint/sharepoint_list.png diff --git a/_guide/_pages/sharepoint/text_box.png b/_pages/sharepoint/text_box.png similarity index 100% rename from _guide/_pages/sharepoint/text_box.png rename to _pages/sharepoint/text_box.png diff --git a/_pages/tests/tests.md b/_pages/tests/tests.md new file mode 100644 index 00000000..85a6d5dd --- /dev/null +++ b/_pages/tests/tests.md @@ -0,0 +1,30 @@ +--- +title: Automated Testing +sidenav: tools +permalink: /tests/ +sticky_sidenav: true +--- + +There are many different types of automated testing, which all have +separate roles to play. Ideally, automated testing can be run locally +as well as part of a continuous integration workflow. +## Validating HTML output + +### Ruby {#html-output-ruby} + +[HTMLProofer](https://github.com/gjtorikian/html-proofer) is the most common +tool in use for ruby projects at TTS for validating HTML output. It is used in our +[guides](https://18f.gsa.gov/guides/) to ensure that internal links are not +broken, but it can also be used for a broad range of image, link, and script +tests. + +HTMLProofer can be run on the command line directly, as a +[Rake task](https://github.com/18F/isildurs-bane/blob/699502eeb374bf3414c1336290cb622e9a0f8847/Rakefile) +or as part of a [CI action](https://github.com/18F/handbook/blob/cf5a76af5a1463496cd7eb1a14fdc7a422aa5ae6/.circleci/config.yml#L58-L60). + +**Warning**: +Some government websites are very sensitive to crawlers, and so testing external government links +can cause HTMLProofer to fail with an opaque error like `1 No Error`. If you are testing external +links in a CI/CD pipeline, you may regularly have to manually check errors to ensure that they are +valid. When a link is actually broken, HTMLProofer will display a diagnostic message about where +the bad link originated. \ No newline at end of file diff --git a/_pages/web-architecture.md b/_pages/web-architecture.md new file mode 100644 index 00000000..a0d26a41 --- /dev/null +++ b/_pages/web-architecture.md @@ -0,0 +1,130 @@ +--- +title: Choosing a Web App Architecture +sidenav: tools +sticky_sidenav: true +--- +The goal of this guide is to help you decide how to approach a web application’s architecture, driving towards simplicity. + +Simpler approaches involve: + +- **fewer layers of technology** +- **using stable technology over cutting-edge**, and +- **less computation or no computation when possible** + +## Why push for simplicity + +Government software projects often face tight budgets, are used long-term, and have a broad user base with diverse needs. Because of these factors, simpler is better. + +- **Cost-effectiveness**: Government agencies need to carefully steward public funds. Because budgets for software development in government can be tight, the technology we buy and build should be cost-efficient as well as high-quality. We’ve found that simpler UI technologies are more cost-effective to build and maintain, and easier to understand for members of the public who want to contribute. +- **Maintainability**: Government is long-term, so we want government software to last. We want to be kind to the future maintainers of our software and leave them with the minimum possible complexity to maintain. +- **Accessibility**: As government employees we serve the public, so the websites we build must be highly accessible to the public. The more complexity involved in building UI views, the more work it takes to build an accessible site. + +## How to choose an approach + +How much complexity does your web application need to include? That depends on what kind of features it requires. + +- If you can make it a static site, you should. +- If you can’t, it should probably be a server-rendered app. +- If your use case requires a bit of client-side interactivity, use the above options with a bit of JavaScript. +- If your use case requires complex client-side interactivity, then you may need a single-page application. + +Web applications can and do shift approaches over time. + +Many web apps begin their life cycles with server-side rendering only, and add more client-side functionality over time in response to user behavior. Consider whether your application could initially launch as a server-rendered app, with the potential to add more client-side functionality based on user behavior. + +See below for examples and heuristics to help you decide which architecture could make the most sense for your project as a starting point: + +## If you can make it a static site, you should. + +_When thinking about a static site, you might use words like: [Jekyll](https://jekyllrb.com), [Hugo](https://gohugo.io), [Federalist](https://federalist.18f.gov) {%include components/tag-standard.html %}, static HTML._ + +### Benefits to this approach: + +- Simple to keep running (low maintenance cost) +- Can use Federalist to outsource deployment of the site +- Quick path to ATO, or no ATO at all since Federalist has its own ATO +- Automatic accessibility testing is extremely straightforward +- Searching with search.gov/search engines is easy + +### When this might be the right fit: + +- A site used mostly to publish static content, such as public-facing agency information, articles, or press releases +- An informational handbook or guide +- A blog + +### When you might need something more complex: + +- When your app needs authentication, user roles or permissions +- When your app needs to draw from live data feeds or APIs +- When your app needs to handle sensitive data or PII + +## If you can’t, it should probably be a server-rendered app. + +_When thinking about a server-rendered app, you might use words like: [Django](https://www.djangoproject.com/), [Rails](https://rubyonrails.org/)._ + +### Benefits to this approach: + +- Stable, tried-and-true tooling +- Only one set of development skills needed, as opposed to separate back-end and front-end development skills +- Faster development velocity and lower costs to build and maintain than an equivalent project with separate front-end and back-end apps +- Can use tools like [Cloud.gov](https://cloud.gov) +- Easy to see if it’s working (compared to purely client-side functionality) if status codes returned are 200 +- Changes to data are easy to manage using tools like Admin Interfaces +- Custom implemented searching with SQL-y endpoints +- Adding basic forms with no client-side interactivity are a breeze +- Client doesn’t get out of sync with the server, as it’s served from the response. + +### Drawbacks to this approach: + +- Applications with servers and databases will need their own ATO +- Deployment is more complex and requires more skills to maintain +- Zero downtime deployments are more complex + +## If your use case requires a bit of client-side interactivity, use the above options with a bit of JavaScript. + +_You might use words like: [Stimulus](https://stimulus.hotwire.dev), [jQuery](https://jquery.com), Plain JavaScript._ + +### Benefits to this approach: + +- Accessibility testing is relatively straightforward +- Interactivity that doesn’t require state management, like animations or visual graphics +- Because memory is dumped between pages, potential memory leaks or tricky to diagnose issues are less impactful +- Leverages the browser cache +- Can use more than one JavaScript framework, which may be useful for project transitions +- Leaves room for more flexible decisions for UI down the road + +### Drawbacks to this approach: + +- Forms with complex state are harder to manage +- Build/deployment includes both server-side build patterns and client-side build patterns +- Hard to know where something is rendered +- No clear conventions, no standard way to build them. +- Can quickly turn into a ball of JavaScript with mixed frameworks +- Generally uses two (or more) package managers + +## If your use case requires complex client-side interactivity, then you may need a single-page application (SPA). + +_You might use words like: [React](https://engineering.18f.gov/javascript/frameworks/#react) {%include components/tag-default.html %}, [React Router](https://reactrouter.com), [Redux](https://redux.js.org), [Angular](https://engineering.18f.gov/javascript/frameworks/#angular) {%include components/tag-suggestion.html %}, [Gatsby](https://www.gatsbyjs.com), [Vue.js](https://vuejs.org), [Ember](https://emberjs.com)_ + +### Benefits to this approach: + +- Handling offline support +- Managing client-side state is required and first-class, so handling complex interactions are more straightforward +- Clearer conventions for how code should be written, compared to server-side rendering with a bit of JavaScript + +### Drawbacks to this approach: + +- Requires more specialist dev skills to build +- Can be costlier to build and maintain (both in time and money) than server-rendered or static sites +- Making pages and features accessible requires more developer time and effort +- Testing for accessibility is no longer straightforward +- Proper SEO also requires more developer time and effort +- Deployments: how do you monitor when a new version of a SPA is available and apply the code changes? What if the SPA is a different version than the server? +- An SPA can run for days, weeks, etc; which may highlight memory management problems +- Routing: the browser already handles this, but SPA's override it and it becomes your problem +- Caching can be tricky with many areas to maintain state storage (rather than just the browser’s cache) +- Execution environment is always unknown and changing + +## Conclusion + +Keeping web application architecture as simple as possible can help keep government websites cost-effective, maintainable, and accessible. Understanding your user requirements can help decide what kinds of client-side interactivity are nice-to-haves, must-haves, or not needed at all. diff --git a/_pages/workflow.md b/_pages/workflow.md new file mode 100644 index 00000000..dccf9c1f --- /dev/null +++ b/_pages/workflow.md @@ -0,0 +1,72 @@ +--- +title: Our approach +sidenav: approach +sticky_sidenav: true +--- + +Project teams may vary, but across TTS engineering we aim for consistency +around deployments, git etiquette, and similar workflow conventions. + +## Continuous Integration & Deployment + +### All Projects {%include components/tag-standard.html %} + +- Ensure that your project is running **automated tests** in CI. Successful + test completion should be a requirement for deployment. +- Generally, **CI should perform deployments**. This ensures the deployments + are repeatable and don’t rely on individual development environments. See + our [documentation on continuous deployment]({{site.baseurl}}/continuous-deployment) for + details on how to set this up. +- Deployments should be **zero-downtime**, achievable through tools like + [Cloud Foundry's rolling deployment process](https://docs.cloudfoundry.org/devguide/deploy-apps/rolling-deploy.html). +- In addition to deployments after code change, we generally need to + (automatically) **re-deploy daily** to ensure the running containers haven’t + been tampered with (an ATO compliance requirement). See CircleCI’s + [“schedule” + docs](https://circleci.com/docs/2.0/configuration-reference/#schedule) for + details. + +## Git & GitHub {%include components/tag-standard.html %} + +Git is our version control system of choice and +GitHub is our current repository platform, but how to use these tools can be spelled out +in a bit more detail. Note that we are looking to consolidate this with our existing +documentation on [code review]({{site.baseurl}}/code-review) and [example +workflows]({{site.baseurl}}/example-workflows). + +### Security {%include components/tag-requirement.html %} + +_For best practices on protecting sensitive information, check out the [TTS +Handbook](https://handbook.tts.gsa.gov/sensitive-information/#protecting-tts-systems)._ + +Enable +[**two-factor authentication**](https://help.github.com/articles/about-two-factor-authentication/) for +your GitHub account. This is required for all TTS employees. + +As part of the ATO process, we require any branches which +trigger automated deployment be [**protected**](https://help.github.com/articles/about-protected-branches/) +by passing CI and peer review. + +### Other considerations + +#### {%include components/tag-standard.html %} +* Default to **public** for new repositories. See our + [guidelines](https://github.com/18F/open-source-policy/blob/master/practice.md) + about open source for more detail. +* Enforce reviewer approval of pull requests against the main branch. +* We prefer **branches** over forks to ease internal collaboration. *If your project has many outside contributors, consider forks instead.* +* Keep your repository **clean**; delete merged branches and avoid committing +files specific to your dev environment (e.g. `.DS_Store`). +* Consider [**signing commits** with a GPG + key](https://help.github.com/articles/signing-commits-with-gpg/) + + +#### {%include components/tag-suggestion.html %} +* When in doubt, use feature branches and [**gitflow**](http://nvie.com/posts/a-successful-git-branching-model/) as your branch naming scheme. +* Follow [this + guidance](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) about **good commit messages**. +* Consider using [Allstar](https://github.com/ossf/allstar) to enforce consistent branch protection rules or to require commit signing on all repositories in your organization. For example, see the [Allstar configuration](https://github.com/cloud-gov/.allstar) that the cloud.gov team is using. + +## Code style + +{%include components/tag-standard.html %} Use an opinionated automated code formatter whenever possible. This saves teams from wasting time arguing about code style, and makes it easy to comply. Specific suggestions in [the pages for each language]({{site.baseurl}}/language-selection/). diff --git a/_plugins/override.rb b/_plugins/override.rb deleted file mode 100644 index 159d194e..00000000 --- a/_plugins/override.rb +++ /dev/null @@ -1,133 +0,0 @@ -require "yaml" - -module Jekyll - ## - # Loads custom, guide-specific config and data under GUIDE_DIR. - # Configuration keys are limited to those specified in this class, - # orginating from uswds-jekyll, jekyll-sitemap, and isidurs-bane. - # Data filenames/keys are limited to those in DATA_FILES. - # - class OverrideGenerator < Generator - # Guide-specific directory for configuration, data, and content - GUIDE_DIR = "_guide" - # Guide-specific configuration file - GUIDE_CONFIG = File.join("_guide", "_config.yml") - - # Supported keys in GUIDE_CONFIG: - - # Sets the guide title in the header and anchor, from uswds-jekyll - TITLE_KEY = "title" - # Sets the guide description in the element, from uswds-jekyll - DESC_KEY = "description" - # Sets the URL used in the sitemap.xml, from jekyll-sitemap - URL_KEY = "url" - # Sets the GitHub repository information for the "Edit this page" link, from uswds-jekyll - GITHUB_KEY = "github_info" - # Sets the search.gov handle used with the search function in the header, from uswds-jekyll - SEARCH_KEY = "search_site_handle" - # Sets the organization managing this guide, from isidurs-bane - ORG_KEY = "org" - - # Parent directory for org-specific data - ORGS_DATA_DIR = File.join("_data", "orgs") - - # Guide-specific data - GUIDE_DATA_DIR = File.join("_guide", "_data") - - # Supported uswds-jekyll and isidurs-bane data files - DATA_FILES = ["header.yml", "navigation.yml", "footer.yml", "theme.yml", "anchor.yml"] - - safe true - - ## - # Merges keys in GUIDE_CONFIG with those set in _config.yml. - # Also loads uswds-jekyll and isidurs-bane YAML data files under - # ORGS_DATA_DIR and in GUIDE_DATA_DIR, overriding any keys found - # in _data. Key precedence is GUIDE_DATA_DIR, then the optional - # org-specific sub-directory in ORGS_DATA_DIR, then finally _data. - # - # This method is run after Jekyll has made an inventory of - # the existing content, and before the site is generated, per: - # https://jekyllrb.com/docs/plugins/generators/ - # - def generate(site) - merge_config_file(site) - - merge_org_data(site) - - merge_guide_data(site) - end - - private - - def merge_org_data(site) - yamls = DATA_FILES - yamls.each do |y| - org = site.config[ORG_KEY] - if org - merge_data(site, File.join(ORGS_DATA_DIR, org), y) - end - end - end - - def merge_guide_data(site) - yamls = DATA_FILES - yamls.each do |y| - merge_data(site, GUIDE_DATA_DIR, y) - end - end - - ## - # Federalist does not allow multiple Jekyll config files to be - # specified (i.e., with --config), so this approximates that - # Jekyll feature. - # - def merge_config_file(site) - required = [TITLE_KEY, DESC_KEY, GITHUB_KEY, SEARCH_KEY, URL_KEY] - optional = [ORG_KEY] - - original_url = site.config[URL_KEY] - - customizations = YAML.load_file(GUIDE_CONFIG) - if customizations - required.each do |k| - site.config[k] = customizations[k] - end - - optional.each do |k| - if customizations.key?(k) - site.config[k] = customizations[k] - end - end - - # Per https://jekyllrb.com/docs/variables/, Jekyll will set - # the url at runtime in dev environments -- preserve, if set - if original_url - site.config[URL_KEY] = original_url - end - end - puts " Merged " + GUIDE_CONFIG - end - - def merge_data(site, dir, file) - path = File.join(dir, file) - unless File.exist?(path) - # Not every org/guide will need to override a given data file - return - end - - begin - customizations = YAML.load_file(path) - if customizations - # Per https://jekyllrb.com/docs/datafiles/ - key = File.basename(path, File.extname(path)) - site.data[key].merge!(customizations) - puts " Merged " + path - end - rescue - puts " ERROR " + path - raise - end - end - end -end diff --git a/_sass/_usa_anchor.scss b/_sass/_usa_anchor.scss deleted file mode 100644 index 62700f58..00000000 --- a/_sass/_usa_anchor.scss +++ /dev/null @@ -1,232 +0,0 @@ -// Anchor component - - - - - - - - - - - - - - - -// Using the USWDS Design Tokens -.anchor{ - display: flex; - flex-direction: column; - justify-content: flex-end; - flex: 1; -} - - -.component-anchor{ - background-color: $color-dark; - @include u-text('white'); - - h3{ - @include u-font('sans', 'md'); - } - - .org-short{ - @include u-padding-y(3); - @include u-display('block'); - @include at-media('tablet') { - @include u-display('flex'); - @include u-flex('align-center'); - @include u-flex('justify'); - } - .org-copy{ - @include u-display('flex'); - @include u-flex('align-start'); - @include at-media('tablet'){ - @include u-flex('align-center'); - } - p{ - @include u-margin(0); - @include at-media('tablet'){ - @include u-measure(5); - } - } - .org-img{ - @include u-margin-right(2); - @include u-maxw(7); - @include u-minw(7); - @include at-media('tablet') { - @include u-maxw(6); - @include u-minw(6); - } - } - } - } - - .org-copy{ - @include u-font('sans', 'xs'); - @include u-line-height('sans', 3); - @include u-text('white'); - @include at-media('tablet') { - @include u-font('sans', 'sm'); - } - p{ - a{ - @include u-text('white'); - } - .more{ - @include u-text('underline'); - } - } - - } - - .org-expanded{ - .org-copy{ - @include u-margin-bottom(2); - } - .org-links{ - @include u-margin-bottom(2); - @include u-padding-x(2); - @include u-padding-right(1); - @include u-padding-top('105'); - @include u-padding-bottom(2); - @include u-bg('primary-dark'); - @include u-font('sans', '2xs'); - @include u-text('base-lightest'); - ul{ - @include u-padding-left('205'); - li{ - @include u-margin-bottom('05'); - a{ - @include u-text('no-underline'); - @include u-border-bottom('1px', 'solid', 'white'); - &:hover{ - @include u-text('white'); - @include u-border-bottom('2px', 'solid', 'white'); - } - } - } - } - a{ - @include u-text('base-lightest'); - &:hover{ - @include u-text('white'); - @include u-border-bottom('2px', 'solid', 'white'); - } - } - } - } - - button.btn-learn-more{ - @include u-text('white'); - @include u-border('1px', 'solid', 'white'); - @include u-radius('md'); - background: none; - box-shadow: none; - @include u-width('auto'); - - @include u-margin(0); - @include u-margin-top(1); - @include u-padding-y('05'); - @include u-padding-left('105'); - @include u-padding-right(4); - @include u-font('sans', '2xs'); - @include at-media('tablet') { - @include u-margin-top(0); - @include u-margin-left(2); - @include u-padding-y(1); - @include u-float('right'); - @include u-font('sans', 'xs'); - } - @include at-media('desktop') { - @include u-font('sans', 'sm'); - } - &:hover{ - box-shadow: none; - } - } - .usa-accordion__button[aria-expanded=false]{ - background-image: url('https://github.com/assets/images/angle-arrow-down-white.svg'),-webkit-gradient(linear,left top,left bottom,from(transparent),to(transparent)); - background-size: .85rem; - background-repeat: no-repeat; - background-position: 6.65em center; - } - .usa-accordion__button[aria-expanded=true]{ - background-image: url('https://github.com/assets/images/angle-arrow-up-white.svg'),-webkit-gradient(linear,left top,left bottom,from(transparent),to(transparent)); - background-size: .85rem; - background-repeat: no-repeat; - background-position: 6.65em center; - } -} - -.component-anchor-support{ - @include u-bg('black'); - @include u-text('white'); - .usagov{ - @include u-padding-y(1); - @include u-display('block'); - @include at-media('tablet') { - @include u-display('flex'); - @include u-font('sans', 'sm'); - @include u-flex('align-center'); - @include u-flex('justify-start'); - } - p{ - @include u-margin-y('05'); - @include u-flex('align-center'); - @include u-line-height('sans', 2); - @include u-font('sans', 'xs'); - @include at-media('tablet') { - @include u-font('sans', 'sm'); - } - i{ - @include u-margin-right('105'); - font-size:1.25rem; - @include u-maxw(3); - @include u-minw(3); - @include at-media('tablet') { - @include u-maxw(3); - @include u-minw(3); - } - } - } - .usagov__link{ - @include u-margin(0); - @include u-margin-top(1); - @include u-margin-bottom(2); - @include u-padding-y(1); - @include u-text('white'); - white-space: nowrap; - @include u-font('sans', 'sm'); - @include at-media('tablet') { - @include u-margin(0); - @include u-margin-left('105'); - @include u-font('sans', 'xs'); - } - @include at-media('tablet-lg') { - @include u-font('sans', 'sm'); - } - } - } -} - - -.usa-button-sm{ - @include u-margin-x('05'); - @include u-padding-y('05'); - @include u-padding-x('105'); -} -.arrow-down{ - @include u-margin-left('105'); - @include u-width('105'); -} - -.component-anchor-meta{ - @include u-bg('white'); - @include u-text('black'); - .page-meta{ - @include u-padding-y(1); - @include u-display('block'); - @include at-media('tablet') { - @include u-display('flex'); - @include u-font('sans', 'sm'); - @include u-flex('align-center'); - @include u-flex('justify-end'); - } - p{ - @include u-margin-y('05'); - @include u-flex('align-center'); - @include u-line-height('sans', 2); - @include u-font('sans', 'xs'); - @include at-media('tablet') { - @include u-font('sans', 'sm'); - } - } - } -} diff --git a/_sass/_usa_identifier.scss b/_sass/_usa_identifier.scss new file mode 100644 index 00000000..c66d3b80 --- /dev/null +++ b/_sass/_usa_identifier.scss @@ -0,0 +1,39 @@ +// Identifier component - - - - - - - - - - - - - - - +// Using the USWDS Design Tokens + +// fix footer to the bottom on short pages +@include at-media("desktop") { + body { + display: flex; + flex-direction: column; + min-height: 100vh; + } +} + +.usa-identifier { + margin-top: auto; +} + +.component-identifier-meta{ + @include u-bg('white'); + @include u-text('black'); + .page-meta{ + @include u-padding-y(1); + @include u-display('block'); + @include at-media('tablet') { + @include u-display('flex'); + @include u-font('sans', 'sm'); + @include u-flex('align-center'); + @include u-flex('justify-end'); + } + p{ + @include u-margin-y('05'); + @include u-flex('align-center'); + @include u-line-height('sans', 2); + @include u-font('sans', 'xs'); + @include at-media('tablet') { + @include u-font('sans', 'sm'); + } + } + } +} diff --git a/_sass/_uswds-theme-custom-styles.scss b/_sass/_uswds-theme-custom-styles.scss index ef773470..07891cc7 100644 --- a/_sass/_uswds-theme-custom-styles.scss +++ b/_sass/_uswds-theme-custom-styles.scss @@ -186,14 +186,4 @@ a[href^="https://gsa-tts.slack.com/"]::before { //// Footer (usa-anchor styles) - -// Fixing footer anchor to bottom -@include at-media("desktop") { - body { - display: flex; - flex-direction: column; - min-height: 100vh; - } -} - -@import 'https://github.com/_usa_anchor'; +@import 'https://github.com/_usa_identifier'; diff --git a/assets/images/18f-logo-blue.svg b/assets/images/18f-logo-blue.svg deleted file mode 100755 index c2725f3f..00000000 --- a/assets/images/18f-logo-blue.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - 18F-Logo-2016-Blue - Created with Sketch. - - - - - - - - - \ No newline at end of file diff --git a/assets/images/coe-logomark.svg b/assets/images/coe-logomark.svg deleted file mode 100644 index 5bfe8417..00000000 --- a/assets/images/coe-logomark.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - diff --git a/assets/images/drill-small-wikimedia.png b/assets/images/drill-small-wikimedia.png new file mode 100644 index 00000000..bb21c7c4 Binary files /dev/null and b/assets/images/drill-small-wikimedia.png differ diff --git a/assets/images/pif.png b/assets/images/pif.png deleted file mode 100644 index e21c0c16..00000000 Binary files a/assets/images/pif.png and /dev/null differ diff --git a/assets/images/rerun-workflow-circleci-screenshot.png b/assets/images/rerun-workflow-circleci-screenshot.png new file mode 100644 index 00000000..f5472a42 Binary files /dev/null and b/assets/images/rerun-workflow-circleci-screenshot.png differ diff --git a/assets/images/screenshot-fake-epg-hacked.png b/assets/images/screenshot-fake-epg-hacked.png new file mode 100644 index 00000000..4c557474 Binary files /dev/null and b/assets/images/screenshot-fake-epg-hacked.png differ diff --git a/doc/bpdr/0001-record-best-practices-decisions.md b/doc/bpdr/0001-record-best-practices-decisions.md new file mode 100644 index 00000000..e157d230 --- /dev/null +++ b/doc/bpdr/0001-record-best-practices-decisions.md @@ -0,0 +1,19 @@ +1. Record best practices decisions +Date: 2022-03-10 + +Status +Accepted + +Context +As we make best practices decisions, it would be good to have a record +of those decisions so that people can understand the historical context +and review/revisit whether the circumstances of those decisions are still +appropriate. + +Decision +We will use Best Practices Decision Records (BPDR), modified from Architecture Decision +Records (ADR) [as described by Michael Nygard](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions). + +Consequences +Best practices decisions are available in a consistent format to help explain the +reasons and motivations behind creating a best practice. \ No newline at end of file diff --git a/doc/bpdr/0002-on-call-recs.md b/doc/bpdr/0002-on-call-recs.md new file mode 100644 index 00000000..39bb563e --- /dev/null +++ b/doc/bpdr/0002-on-call-recs.md @@ -0,0 +1,24 @@ +1. On-call recommendations +Date: 2022-03-10 + +Status +Accepted + +Context +18F recently built an emergent website that needed on-call support from non-team members. +Because of the urgency of the situation, the on-call needs were left to the last minute. + +Meanwhile, 18F is moving towards being more product-focused, and as such, we may need +to support products in the long- or short-term going forward. + +Decision +[On-call recommendations](https://engineering.18f.gov/on-call/) were created by Davida Marion, +under consultation with Christa Hartsock and Logan McDonald. Recommendations were +[reviewed by](https://github.com/18F/development-guide/pull/298): +Jessica Dussault, Laura Gerhardt, Alex Soble, Michael Sullivan, Neil Martinsen-Burrell, +Ryan Ahern, Sarah Withee, and Sven Aas. + +Consequences +Engineers have a reviewed set of recommendations to take into account while working on builds +that seem like they may have on-call needs. These recommendations can be inserted into the +staffing phase, the development phase, and the support phase. \ No newline at end of file diff --git a/doc/bpdr/0003-set-criteria-for-static-site-framework.md b/doc/bpdr/0003-set-criteria-for-static-site-framework.md new file mode 100644 index 00000000..70c13543 --- /dev/null +++ b/doc/bpdr/0003-set-criteria-for-static-site-framework.md @@ -0,0 +1,68 @@ +# 3. Set Criteria for Recommended Static Site Generator + +## Status +Accepted + +## Context +TTS needs to build a lot of server-rendered websites, both for its own purposes and for other government agencies. + +Jekyll has been the popular go-to framework for this work, for a few reasons: +- Many 18F employees were Rubyists +- For a while, it had strong community and institutional support + - Github uses it as the engine for Github Pages +- Federalist (now Cloud.gov Pages) supports it and USWDS built multiple themes for it, allowing teams to stand up a new government website very quickly +- Markdown pages were relatively easier to edit by a wider variety of TTS employees than other frameworks + +In mid-2021 some core maintainers said Jekyll was [in hiatus](https://www.theregister.com/2021/09/14/future_of_jekyll_project_engine/) and recommended other frameworks to switch to. This hasn't been stated on the official website, and the [Jekyll Github repo](https://github.com/jekyll/jekyll) remains active, so Jekyll's future seems unclear. + +In addition, a number of TTS employees are unsatisfied with Jekyll because: +- build times have become slower relative to other frameworks +- It’s difficult to support asset rendering (including building USWDS, a common component of our sites) in a way that supports far-futures cache headers +- Building locally in development is difficult to impossible without admin rights, hindering handoff to folks with less computer privileges + +For these reasons, we want teams to avoid standing up new Jekyll sites, but we don't yet have consensus on what the alternative should be. + +While we don't know what the single alternative to Jekyll should be, we agree that TTS should recommend one alternative over multiple, since a single alternative will be easier for TTS staff to support. + +In order to get consensus on the alternative, we should first agree on a criteria for what we need and want in a static site generator. + +## Decision + +Any static site generator used by TTS needs to: +- be written in a language that many TTS'ers can support +- have sufficient open-source community support and longevity +- be supported by Cloud.gov Pages +- be supported by USWDS +- allow containerization through Docker +- be able to be used for both prototyping and production +- have build times that don't impede development +- not make a11y hard +- have multilingual support +- enable people without specialized engineering skills to edit static content + +It would be nice to have: +- built-in support for common compiles-to-web languages, like SASS, ESNext, and TypeScript +- the ability to reuse/share layouts or templates across sites + +Current candidates (in no particular order): +- [11ty](https://www.11ty.dev/) +- [Hugo](https://gohugo.io/) +- [Next](https://nextjs.org/) +- [Gatsby](https://www.gatsbyjs.com/) +- [Bridgetown](https://www.bridgetownrb.com/) +- Build our own +- [Middleman](https://middlemanapp.com/) + +## Consequences + +### Risks of staying with Jekyll +- Degredation of framework and dependencies as community support wanes +- If Jekyll's period of support officially ends, we will be forced to migrate at that point, or risk running deprecated software + +## Risks of moving from Jekyll +- We will still need to maintain our many Jekyll apps, for a time +- We will need to decide whether these apps should be deprecated or moved to a new platform +- Moving to a new platform will take a lot of work and support + +## Next Steps +The Guild will make a checklist based on these criteria, share it out with teams using these alternatives, and decide what to do next based on the feedback we get. diff --git a/favicon.ico b/favicon.ico new file mode 100755 index 00000000..c81a0226 Binary files /dev/null and b/favicon.ico differ diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..d21f0c4f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,936 @@ +{ + "name": "development-guide", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "axe-core": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-3.5.5.tgz", + "integrity": "sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "bfj": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-4.2.4.tgz", + "integrity": "sha1-hfeyNoPCr9wVhgOEotHD+sgO0zo=", + "dev": true, + "requires": { + "check-types": "^7.3.0", + "hoopy": "^0.1.2", + "tryer": "^1.0.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "check-types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-7.4.0.tgz", + "integrity": "sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg==", + "dev": true + }, + "cheerio": { + "version": "1.0.0-rc.6", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.6.tgz", + "integrity": "sha512-hjx1XE1M/D5pAtMgvWwE21QClmAEeGHOIDfycgmndisdNgI6PE1cGRQkMGBcsbUbmEQyWu5PJLUcAOjtQS8DWw==", + "dev": true, + "requires": { + "cheerio-select": "^1.3.0", + "dom-serializer": "^1.3.1", + "domhandler": "^4.1.0", + "htmlparser2": "^6.1.0", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1" + } + }, + "cheerio-select": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.4.0.tgz", + "integrity": "sha512-sobR3Yqz27L553Qa7cK6rtJlMDbiKPdNywtR95Sj/YgfpLfy0u6CGJuaBKe5YE/vTc23SCRKxWSdlon/w6I/Ew==", + "dev": true, + "requires": { + "css-select": "^4.1.2", + "css-what": "^5.0.0", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0", + "domutils": "^2.6.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "css-select": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.2.tgz", + "integrity": "sha512-nu5ye2Hg/4ISq4XqdLY2bEatAcLIdt3OYGFc9Tm9n7VSlFBcfRv0gBNksHRgSdUDQGtN3XrZ94ztW+NfzkFSUw==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^5.0.0", + "domhandler": "^4.2.0", + "domutils": "^2.6.0", + "nth-check": "^2.0.0" + } + }, + "css-what": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", + "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", + "dev": true + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "dom-serializer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.1.tgz", + "integrity": "sha512-Pv2ZluG5ife96udGgEDovOOOA5UELkltfJpnIExPrAk1LTvecolUGn6lIaoLh86d83GiB86CjzciMd9BuRB71Q==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true + }, + "domhandler": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz", + "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.6.0.tgz", + "integrity": "sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "extract-zip": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", + "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", + "dev": true, + "requires": { + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "file-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", + "integrity": "sha512-g872QGsHexznxkIAdK8UiZRe7SkE6kvylShU4Nsj8NvfvZag7S0QuQ4IgvPDkk75HxgjIVDwycFTDAgIiO4nDA==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", + "dev": true + }, + "html_codesniffer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/html_codesniffer/-/html_codesniffer-2.4.1.tgz", + "integrity": "sha512-7g4Z8+7agJFi7XJGu2r0onIqA7ig9b26vFEvUE6DgtFJlJzy1ELYEKzzd5Xwam4xjHiHQ/w8yHO7KTGNcXnwzg==", + "dev": true + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", + "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node.extend": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-2.0.2.tgz", + "integrity": "sha512-pDT4Dchl94/+kkgdwyS2PauDFjZG0Hk0IcHIB+LkW27HLDtdoeMxHTxZh39DYbPP8UflWXWj9JcdDozF+YDOpQ==", + "dev": true, + "requires": { + "has": "^1.0.3", + "is": "^3.2.1" + } + }, + "nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } + }, + "pa11y": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/pa11y/-/pa11y-5.3.1.tgz", + "integrity": "sha512-hRxe9mYUqwODrlIXiTKUrlJX8zgrJZG84s0IrJnvvI8reO6n4RtiF20juTaGukjuHtH8p3tgFh+i2gPcRZSyUg==", + "dev": true, + "requires": { + "commander": "~3.0.2", + "node.extend": "~2.0.2", + "p-timeout": "~2.0.1", + "pa11y-reporter-cli": "~1.0.1", + "pa11y-reporter-csv": "~1.0.0", + "pa11y-reporter-json": "~1.0.0", + "pa11y-runner-axe": "~1.0.1", + "pa11y-runner-htmlcs": "~1.2.1", + "puppeteer": "~1.19.0", + "semver": "~5.7.0" + }, + "dependencies": { + "commander": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", + "dev": true + }, + "puppeteer": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.19.0.tgz", + "integrity": "sha512-2S6E6ygpoqcECaagDbBopoSOPDv0pAZvTbnBgUY+6hq0/XDFDOLEMNlHF/SKJlzcaZ9ckiKjKDuueWI3FN/WXw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "extract-zip": "^1.6.6", + "https-proxy-agent": "^2.2.1", + "mime": "^2.0.3", + "progress": "^2.0.1", + "proxy-from-env": "^1.0.0", + "rimraf": "^2.6.1", + "ws": "^6.1.0" + } + } + } + }, + "pa11y-ci": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/pa11y-ci/-/pa11y-ci-2.4.0.tgz", + "integrity": "sha512-0TOR9CfOTJNO7TpmYfPRxbNZWs6tF/iCk/R+j40kmDlEInLT+my3MHdYhDwC3OjRczaQiRgR3y7y7QqAGENJpw==", + "dev": true, + "requires": { + "async": "~2.6.3", + "chalk": "~1.1.3", + "cheerio": "~1.0.0-rc.3", + "commander": "~2.20.3", + "globby": "~6.1.0", + "lodash": "~4.17.20", + "node-fetch": "~2.6.0", + "pa11y": "~5.3.0", + "protocolify": "~3.0.0", + "puppeteer": "~1.20.0", + "wordwrap": "~1.0.0" + } + }, + "pa11y-reporter-cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pa11y-reporter-cli/-/pa11y-reporter-cli-1.0.1.tgz", + "integrity": "sha512-k+XPl5pBU2R1J6iagGv/GpN/dP7z2cX9WXqO0ALpBwHlHN3ZSukcHCOhuLMmkOZNvufwsvobaF5mnaZxT70YyA==", + "dev": true, + "requires": { + "chalk": "^2.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "pa11y-reporter-csv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pa11y-reporter-csv/-/pa11y-reporter-csv-1.0.0.tgz", + "integrity": "sha512-S2gFgbAvONBzAVsVbF8zsYabszrzj7SKhQxrEbw19zF0OFI8wCWn8dFywujYYkg674rmyjweSxSdD+kHTcx4qA==", + "dev": true + }, + "pa11y-reporter-json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pa11y-reporter-json/-/pa11y-reporter-json-1.0.0.tgz", + "integrity": "sha512-EdLrzh1hyZ8DudCSSrcakgtsHDiSsYNsWLSoEAo1JnFTIK8hYpD7vL+xgd0u+LXDxz9wLLFnckdubpklaRpl/w==", + "dev": true, + "requires": { + "bfj": "^4.2.3" + } + }, + "pa11y-runner-axe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pa11y-runner-axe/-/pa11y-runner-axe-1.0.2.tgz", + "integrity": "sha512-HMw5kQZz16vS5Bhe067esgeuULNzFYP4ixOFAHxOurwGDptlyc2OqH6zfUuK4szB9tbgb5F23v3qz9hCbkGRpw==", + "dev": true, + "requires": { + "axe-core": "^3.5.1" + } + }, + "pa11y-runner-htmlcs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pa11y-runner-htmlcs/-/pa11y-runner-htmlcs-1.2.1.tgz", + "integrity": "sha512-flatSp6moEbqzny18b2IEoDXEWj6xJbJrszdBjUAPQBCN11QRW+SZ0U4uFnxNTLPpXs30N/a9IlH4vYiRr2nPg==", + "dev": true, + "requires": { + "html_codesniffer": "~2.4.1" + } + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dev": true, + "requires": { + "parse5": "^6.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "prepend-http": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-3.0.1.tgz", + "integrity": "sha512-BLxfZh+m6UiAiCPZFJ4+vYoL7NrRs5XgCTRrjseATAggXhdZKKxn+JUNmuVYWY23bDHgaEHodxw8mnmtVEDtHw==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "protocolify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/protocolify/-/protocolify-3.0.0.tgz", + "integrity": "sha512-PuvDJOkKJMVQx8jSNf8E5g0bJw/UTKm30mTjFHg4N30c8sefgA5Qr/f8INKqYBKfvP/MUSJrj+z1Smjbq4/3rQ==", + "dev": true, + "requires": { + "file-url": "^3.0.0", + "prepend-http": "^3.0.0" + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "puppeteer": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.20.0.tgz", + "integrity": "sha512-bt48RDBy2eIwZPrkgbcwHtb51mj2nKvHOPMaSH2IsWiv7lOG9k9zhaRzpDZafrk05ajMc3cu+lSQYYOfH2DkVQ==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "extract-zip": "^1.6.6", + "https-proxy-agent": "^2.2.1", + "mime": "^2.0.3", + "progress": "^2.0.1", + "proxy-from-env": "^1.0.0", + "rimraf": "^2.6.1", + "ws": "^6.1.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..b0bfce67 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "development-guide", + "version": "1.0.0", + "description": "This repo will contain the guidelines and best practices for the engineering chapter at 18F. The site is a living document.", + "main": "index.js", + "private": true, + "author": "18F", + "license": "CC0-1.0", + "scripts": { + "start-detached": "bundle exec jekyll serve --detach", + "pa11y-ci:home": "pa11y-ci http://localhost:4000", + "pa11y-ci:sitemap": "pa11y-ci --sitemap https://engineering.18f.gov/sitemap.xml --sitemap-find https://engineering.18f.gov --sitemap-replace http://localhost:4000 --sitemap-exclude \"/*.pdf\"" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/18F/development-guide.git" + }, + "bugs": { + "url": "https://github.com/18F/development-guide/issues" + }, + "devDependencies": { + "pa11y-ci": "^2.4.0" + } +}