Move events into subject folder (#35262)
This commit is contained in:
51
.github/workflows/test.yml
vendored
51
.github/workflows/test.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: Node.js Tests
|
name: Test
|
||||||
|
|
||||||
# **What it does**: Runs our tests.
|
# **What it does**: Runs our tests.
|
||||||
# **Why we have it**: We want our tests to pass before merging code.
|
# **Why we have it**: We want our tests to pass before merging code.
|
||||||
@@ -41,22 +41,22 @@ jobs:
|
|||||||
// we're on the private docs-internal repo because only that
|
// we're on the private docs-internal repo because only that
|
||||||
// one has ability to clone the remote (private) translations
|
// one has ability to clone the remote (private) translations
|
||||||
// repos.
|
// repos.
|
||||||
const all = [
|
return [
|
||||||
'content',
|
{ name: 'content', path: 'tests/content', },
|
||||||
'graphql',
|
{ name: 'graphql', path: 'tests/graphql', },
|
||||||
'meta',
|
{ name: 'meta', path: 'tests/meta', },
|
||||||
'rendering',
|
{ name: 'rendering', path: 'tests/rendering', },
|
||||||
'routing',
|
{ name: 'routing', path: 'tests/routing', },
|
||||||
'unit',
|
{ name: 'unit', path: 'tests/unit', },
|
||||||
'linting',
|
{ name: 'linting', path: 'tests/linting', },
|
||||||
'rendering-fixtures',
|
{ name: 'rendering-fixtures', path: 'tests/rendering-fixtures', },
|
||||||
];
|
{ name: 'events', path: 'src/events/tests', },
|
||||||
if (context.payload.repository.full_name === 'github/docs-internal') {
|
context.payload.repository.full_name === 'github/docs-internal' &&
|
||||||
all.push('translations');
|
{ name: 'translations', path: 'tests/translations', },
|
||||||
}
|
].filter(Boolean)
|
||||||
return all;
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
name: ${{ matrix.name }}
|
||||||
needs: figureOutMatrix
|
needs: figureOutMatrix
|
||||||
# Run on ubuntu-20.04-xl if the private repo or ubuntu-latest if the public repo
|
# Run on ubuntu-20.04-xl if the private repo or ubuntu-latest if the public repo
|
||||||
# See pull # 17442 in the private repo for context
|
# See pull # 17442 in the private repo for context
|
||||||
@@ -65,7 +65,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
test-group: ${{ fromJSON(needs.figureOutMatrix.outputs.matrix) }}
|
include: ${{ fromJSON(needs.figureOutMatrix.outputs.matrix) }}
|
||||||
steps:
|
steps:
|
||||||
# Each of these ifs needs to be repeated at each step to make sure the required check still runs
|
# Each of these ifs needs to be repeated at each step to make sure the required check still runs
|
||||||
# Even if if doesn't do anything
|
# Even if if doesn't do anything
|
||||||
@@ -73,7 +73,7 @@ jobs:
|
|||||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
||||||
|
|
||||||
- uses: ./.github/actions/setup-elasticsearch
|
- uses: ./.github/actions/setup-elasticsearch
|
||||||
if: ${{ matrix.test-group == 'content' || matrix.test-group == 'translations' }}
|
if: ${{ matrix.name == 'content' || matrix.name == 'translations' }}
|
||||||
|
|
||||||
- uses: ./.github/actions/node-npm-setup
|
- uses: ./.github/actions/node-npm-setup
|
||||||
|
|
||||||
@@ -83,12 +83,12 @@ jobs:
|
|||||||
token: ${{ secrets.DOCUBOT_REPO_PAT }}
|
token: ${{ secrets.DOCUBOT_REPO_PAT }}
|
||||||
|
|
||||||
- name: Check the test fixture data (if applicable)
|
- name: Check the test fixture data (if applicable)
|
||||||
if: ${{ matrix.test-group == 'rendering-fixtures' }}
|
if: ${{ matrix.name == 'rendering-fixtures' }}
|
||||||
run: ./script/copy-fixture-data.js --check
|
run: ./script/copy-fixture-data.js --check
|
||||||
|
|
||||||
# This keeps our fixture content/data in check
|
# This keeps our fixture content/data in check
|
||||||
- name: Check the test fixture content (if applicable)
|
- name: Check the test fixture content (if applicable)
|
||||||
if: ${{ matrix.test-group == 'rendering-fixtures' }}
|
if: ${{ matrix.name == 'rendering-fixtures' }}
|
||||||
env:
|
env:
|
||||||
ROOT: tests/fixtures
|
ROOT: tests/fixtures
|
||||||
run: |
|
run: |
|
||||||
@@ -101,12 +101,13 @@ jobs:
|
|||||||
tests/fixtures/data
|
tests/fixtures/data
|
||||||
|
|
||||||
- name: Clone all translations
|
- name: Clone all translations
|
||||||
if: ${{ matrix.test-group == 'translations' }}
|
if: ${{ matrix.name == 'translations' }}
|
||||||
uses: ./.github/actions/clone-translations
|
uses: ./.github/actions/clone-translations
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.DOCUBOT_REPO_PAT }}
|
token: ${{ secrets.DOCUBOT_REPO_PAT }}
|
||||||
|
|
||||||
- name: Gather files changed
|
- name: Gather files changed
|
||||||
|
if: ${{ matrix.name == 'linting' }}
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
PR: ${{ github.event.pull_request.number }}
|
PR: ${{ github.event.pull_request.number }}
|
||||||
@@ -149,9 +150,9 @@ jobs:
|
|||||||
run: npm run build
|
run: npm run build
|
||||||
|
|
||||||
- name: Index fixtures into the local Elasticsearch
|
- name: Index fixtures into the local Elasticsearch
|
||||||
# For the sake of saving time, only run this step if the test-group
|
# For the sake of saving time, only run this step if the group
|
||||||
# is one that will run tests against an Elasticsearch on localhost.
|
# is one that will run tests against an Elasticsearch on localhost.
|
||||||
if: ${{ matrix.test-group == 'content' || matrix.test-group == 'translations' }}
|
if: ${{ matrix.name == 'content' || matrix.name == 'translations' }}
|
||||||
run: npm run index-test-fixtures
|
run: npm run index-test-fixtures
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
@@ -161,6 +162,6 @@ jobs:
|
|||||||
# By default, when `process.env.NODE_ENV === 'test'` it forces the
|
# By default, when `process.env.NODE_ENV === 'test'` it forces the
|
||||||
# tests run only in English. The exception is the
|
# tests run only in English. The exception is the
|
||||||
# `tests/translations/` suite which needs all languages to be set up.
|
# `tests/translations/` suite which needs all languages to be set up.
|
||||||
ENABLED_LANGUAGES: ${{ matrix.test-group == 'translations' && 'all' || '' }}
|
ENABLED_LANGUAGES: ${{ matrix.name == 'translations' && 'all' || '' }}
|
||||||
ROOT: ${{ matrix.test-group == 'rendering-fixtures' && 'tests/fixtures' || ''}}
|
ROOT: ${{ matrix.name == 'rendering-fixtures' && 'tests/fixtures' || ''}}
|
||||||
run: npm test -- tests/${{ matrix.test-group }}/
|
run: npm test -- ${{ matrix.path }}/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import Cookies from 'js-cookie'
|
import Cookies from 'js-cookie'
|
||||||
import { UnderlineNav } from '@primer/react'
|
import { UnderlineNav } from '@primer/react'
|
||||||
import { sendEvent, EventType } from 'components/lib/events'
|
import { sendEvent, EventType } from 'src/events/browser'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
|
||||||
type Option = {
|
type Option = {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useRouter } from 'next/router'
|
|||||||
import { ThumbsdownIcon, ThumbsupIcon } from '@primer/octicons-react'
|
import { ThumbsdownIcon, ThumbsupIcon } from '@primer/octicons-react'
|
||||||
import { useTranslation } from 'components/hooks/useTranslation'
|
import { useTranslation } from 'components/hooks/useTranslation'
|
||||||
import { Link } from 'components/Link'
|
import { Link } from 'components/Link'
|
||||||
import { sendEvent, EventType } from 'components/lib/events'
|
import { sendEvent, EventType } from 'src/events/browser'
|
||||||
|
|
||||||
import styles from './Survey.module.scss'
|
import styles from './Survey.module.scss'
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { useTranslation } from 'components/hooks/useTranslation'
|
|||||||
import { useNumberFormatter } from 'components/hooks/useNumberFormatter'
|
import { useNumberFormatter } from 'components/hooks/useNumberFormatter'
|
||||||
import { Link } from 'components/Link'
|
import { Link } from 'components/Link'
|
||||||
import { useQuery } from 'components/hooks/useQuery'
|
import { useQuery } from 'components/hooks/useQuery'
|
||||||
import { sendEvent, EventType } from 'components/lib/events'
|
import { sendEvent, EventType } from 'src/events/browser'
|
||||||
|
|
||||||
import styles from './SearchResults.module.scss'
|
import styles from './SearchResults.module.scss'
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { useRouter } from 'next/router'
|
|||||||
import Head from 'next/head'
|
import Head from 'next/head'
|
||||||
import { Heading } from '@primer/react'
|
import { Heading } from '@primer/react'
|
||||||
|
|
||||||
import { sendEvent, EventType } from 'components/lib/events'
|
import { sendEvent, EventType } from 'src/events/browser'
|
||||||
import { useTranslation } from 'components/hooks/useTranslation'
|
import { useTranslation } from 'components/hooks/useTranslation'
|
||||||
import { DEFAULT_VERSION, useVersion } from 'components/hooks/useVersion'
|
import { DEFAULT_VERSION, useVersion } from 'components/hooks/useVersion'
|
||||||
import { useNumberFormatter } from 'components/hooks/useNumberFormatter'
|
import { useNumberFormatter } from 'components/hooks/useNumberFormatter'
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { ActionList } from '@primer/react'
|
|||||||
|
|
||||||
import { Link } from 'components/Link'
|
import { Link } from 'components/Link'
|
||||||
import { ProductTreeNode } from 'components/context/MainContext'
|
import { ProductTreeNode } from 'components/context/MainContext'
|
||||||
import { EventType, sendEvent } from 'components/lib/events'
|
import { EventType, sendEvent } from 'src/events/browser'
|
||||||
import styles from './SidebarProduct.module.scss'
|
import styles from './SidebarProduct.module.scss'
|
||||||
|
|
||||||
type SectionProps = {
|
type SectionProps = {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { ActionList } from '@primer/react'
|
|||||||
|
|
||||||
import { Link } from 'components/Link'
|
import { Link } from 'components/Link'
|
||||||
import { ProductTreeNode } from 'components/context/MainContext'
|
import { ProductTreeNode } from 'components/context/MainContext'
|
||||||
import { EventType, sendEvent } from 'components/lib/events'
|
import { EventType, sendEvent } from 'src/events/browser'
|
||||||
import { useAutomatedPageContext } from 'components/context/AutomatedPageContext'
|
import { useAutomatedPageContext } from 'components/context/AutomatedPageContext'
|
||||||
import type { MiniTocItem } from 'components/context/ArticleContext'
|
import type { MiniTocItem } from 'components/context/ArticleContext'
|
||||||
import styles from './SidebarProduct.module.scss'
|
import styles from './SidebarProduct.module.scss'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import express from 'express'
|
import express from 'express'
|
||||||
import { createProxyMiddleware } from 'http-proxy-middleware'
|
import { createProxyMiddleware } from 'http-proxy-middleware'
|
||||||
|
|
||||||
import events from './events.js'
|
import events from '../../src/events/middleware.js'
|
||||||
import search from './search.js'
|
import search from './search.js'
|
||||||
import webhooks from './webhooks.js'
|
import webhooks from './webhooks.js'
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import Hydro from '../lib/hydro.js'
|
import Hydro from '../src/events/hydro.js'
|
||||||
|
|
||||||
export default function reqUtils(req, res, next) {
|
export default function reqUtils(req, res, next) {
|
||||||
req.hydro = new Hydro()
|
req.hydro = new Hydro()
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
"stylesheets",
|
"stylesheets",
|
||||||
"tests",
|
"tests",
|
||||||
"content",
|
"content",
|
||||||
|
"translations",
|
||||||
"data/reusables",
|
"data/reusables",
|
||||||
"data/variables",
|
"data/variables",
|
||||||
"data/glossaries",
|
"data/glossaries",
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { ThemeProvider, SSRProvider } from '@primer/react'
|
|||||||
|
|
||||||
import '../stylesheets/index.scss'
|
import '../stylesheets/index.scss'
|
||||||
|
|
||||||
import { initializeEvents } from 'components/lib/events'
|
import { initializeEvents } from 'src/events/browser'
|
||||||
import { initializeExperiments } from 'components/lib/experiment'
|
import { initializeExperiments } from 'src/events/experiment'
|
||||||
import {
|
import {
|
||||||
LanguagesContext,
|
LanguagesContext,
|
||||||
LanguagesContextT,
|
LanguagesContextT,
|
||||||
|
|||||||
@@ -7,14 +7,15 @@ Output looks like:
|
|||||||
src/
|
src/
|
||||||
xsubject/
|
xsubject/
|
||||||
README.md
|
README.md
|
||||||
components/
|
docs/
|
||||||
gitkeep
|
gitkeep
|
||||||
lib/
|
lib/
|
||||||
tests/
|
middleware/
|
||||||
scripts/
|
|
||||||
stylesheets/
|
|
||||||
pages/
|
pages/
|
||||||
docs/
|
components/
|
||||||
|
stylesheets/
|
||||||
|
scripts/
|
||||||
|
tests/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import fs from 'fs/promises'
|
import fs from 'fs/promises'
|
||||||
@@ -33,7 +34,16 @@ if (!name) {
|
|||||||
|
|
||||||
const src = 'src/'
|
const src = 'src/'
|
||||||
|
|
||||||
const subfolders = ['components', 'lib', 'tests', 'scripts', 'stylesheets', 'pages', 'docs']
|
const subfolders = [
|
||||||
|
'docs',
|
||||||
|
'lib',
|
||||||
|
'middleware',
|
||||||
|
'pages',
|
||||||
|
'components',
|
||||||
|
'stylesheets',
|
||||||
|
'scripts',
|
||||||
|
'tests',
|
||||||
|
]
|
||||||
|
|
||||||
const files = [
|
const files = [
|
||||||
[
|
[
|
||||||
|
|||||||
21
src/events/README.md
Normal file
21
src/events/README.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Events
|
||||||
|
|
||||||
|
We record events from the browser into our data pipeline to aggregate anonymous data about how folks are using the Docs.
|
||||||
|
|
||||||
|
## Why events
|
||||||
|
|
||||||
|
Data helps us to understand where our Docs are successful, and where we need to improve.
|
||||||
|
|
||||||
|
## How to view events
|
||||||
|
|
||||||
|
1. We send a `POST /events` request from the browser.
|
||||||
|
2. Any data sent we check against our JSON schema.
|
||||||
|
3. After passing the schema check, we send the data along the path to the warehouse.
|
||||||
|
|
||||||
|
## How to work on event
|
||||||
|
|
||||||
|
When adding or changing properties, make sure to update the schema in both the JS file as well as the schema for the warehouse.
|
||||||
|
|
||||||
|
## How to get help for events
|
||||||
|
|
||||||
|
For hubbers, see the internal docs in the internal engineering repository.
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import Cookies from 'js-cookie'
|
import Cookies from 'js-cookie'
|
||||||
import { parseUserAgent } from './user-agent'
|
import { parseUserAgent } from '../../components/lib/user-agent'
|
||||||
|
|
||||||
const COOKIE_NAME = '_docs-events'
|
const COOKIE_NAME = '_docs-events'
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import murmur from 'imurmurhash'
|
import murmur from 'imurmurhash'
|
||||||
import { getUserEventsId, sendEvent, EventType } from './events'
|
import { getUserEventsId, sendEvent, EventType } from './browser'
|
||||||
|
|
||||||
let initialized = false
|
let initialized = false
|
||||||
|
|
||||||
@@ -3,8 +3,8 @@ import { Agent } from 'https'
|
|||||||
|
|
||||||
import got from 'got'
|
import got from 'got'
|
||||||
|
|
||||||
import statsd from '../lib/statsd.js'
|
import statsd from '../../lib/statsd.js'
|
||||||
import FailBot from '../lib/failbot.js'
|
import FailBot from '../../lib/failbot.js'
|
||||||
|
|
||||||
const TIME_OUT_TEXT = 'ms has passed since batch creation'
|
const TIME_OUT_TEXT = 'ms has passed since batch creation'
|
||||||
|
|
||||||
@@ -2,9 +2,9 @@ import express from 'express'
|
|||||||
import { omit } from 'lodash-es'
|
import { omit } from 'lodash-es'
|
||||||
import Ajv from 'ajv'
|
import Ajv from 'ajv'
|
||||||
import addFormats from 'ajv-formats'
|
import addFormats from 'ajv-formats'
|
||||||
import { eventSchema, hydroNames } from '../../lib/schema-event.js'
|
import { eventSchema, hydroNames } from './schema.js'
|
||||||
import catchMiddlewareError from '../catch-middleware-error.js'
|
import catchMiddlewareError from '../../middleware/catch-middleware-error.js'
|
||||||
import { noCacheControl } from '../cache-control.js'
|
import { noCacheControl } from '../../middleware/cache-control.js'
|
||||||
|
|
||||||
const router = express.Router()
|
const router = express.Router()
|
||||||
const ajv = new Ajv()
|
const ajv = new Ajv()
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
import { languageKeys } from './languages.js'
|
import { languageKeys } from '../../lib/languages.js'
|
||||||
import { allVersionKeys } from './all-versions.js'
|
import { allVersionKeys } from '../../lib/all-versions.js'
|
||||||
import { productIds } from './all-products.js'
|
import { productIds } from '../../lib/all-products.js'
|
||||||
import { allTools } from './all-tools.js'
|
import { allTools } from '../../lib/all-tools.js'
|
||||||
|
|
||||||
const context = {
|
const context = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { expect, jest } from '@jest/globals'
|
import { expect, jest } from '@jest/globals'
|
||||||
import { post } from '../helpers/e2etest.js'
|
import { post } from '../../../tests/helpers/e2etest.js'
|
||||||
|
|
||||||
describe('POST /events', () => {
|
describe('POST /events', () => {
|
||||||
jest.setTimeout(60 * 1000)
|
jest.setTimeout(60 * 1000)
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { afterEach } from '@jest/globals'
|
import { afterEach } from '@jest/globals'
|
||||||
import nock from 'nock'
|
import nock from 'nock'
|
||||||
import Hydro from '../../lib/hydro.js'
|
import Hydro from '../hydro.js'
|
||||||
|
|
||||||
describe('hydro', () => {
|
describe('hydro', () => {
|
||||||
let hydro, params
|
let hydro, params
|
||||||
Reference in New Issue
Block a user