Skip to content

Commit

Permalink
Merge branch 'main' into dt-realtime-defer-stream
Browse files Browse the repository at this point in the history
  • Loading branch information
dthyresson authored Oct 23, 2023
2 parents 8bb557b + 433d8ef commit 129abbc
Show file tree
Hide file tree
Showing 82 changed files with 2,627 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ async function main() {
// starting point.
if (
changedFile.startsWith('tasks/smoke-tests/rsc/') ||
changedFile.startsWith('tasks/smoke-tests/rsa/') ||
changedFile.startsWith('tasks/smoke-tests/basePlaywright.config.ts') ||
changedFile.startsWith('.github/actions/set-up-rsc-project/') ||
changedFile.startsWith('github/actions/rsc_related_changes/') ||
Expand Down
28 changes: 28 additions & 0 deletions .github/actions/set-up-rsc-from-fixture/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# GitHub action to copy a template RSA project to use for testing

This action copies a RW project with Streaming SSR and RSC support already set
up. It's used for RSA smoke tests.

It copies the `__fixtures__/test-project-rsa` project, runs `yarn install` and
`project:copy`. Finally it builds the rw app.

## Testing/running locally

Go into the github actions folder
`cd .github/actions`

Then run the following command to execute the action
`node set-up-rsc-from-fixture/setUpRscFixtureLocally.mjs`

## Design

The main logic of the action is in the `setUpRscFixture.mjs` file. To be able
to run that code both on GitHub and locally it uses dependency injection. The
injection is done by `setupRscFixtureLocally.mjs` for when you want to run
the action on your own machine and by `setupRscFixtureGitHib.mjs` when it's
triggered by GitHub CI.

When doing further changes to the code here it's very important to keep the
DI scripts as light on logic as possible. Ideally all logic is kept to
`setUpRscFixture.mjs` so that the same logic is used both locally and on
GitHub.
10 changes: 10 additions & 0 deletions .github/actions/set-up-rsc-from-fixture/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: Set up RSC test project from fixture
description: Sets up an RSC project for smoke-tests

runs:
using: node20
main: 'setUpRscFromFixtureGitHub.mjs'

outputs:
test-project-path:
description: Path to the test project
11 changes: 11 additions & 0 deletions .github/actions/set-up-rsc-from-fixture/jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"noEmit": true,
"esModuleInterop": true,
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"skipLibCheck": false,
"jsx": "react-jsx"
},
}
6 changes: 6 additions & 0 deletions .github/actions/set-up-rsc-from-fixture/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "set-up-rsc-fixture",
"version": "0.0.0",
"private": true,
"type": "module"
}
130 changes: 130 additions & 0 deletions .github/actions/set-up-rsc-from-fixture/setUpRscFromFixture.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/* eslint-env node */
// @ts-check

import fs from 'node:fs'
import path from 'node:path'

import { REDWOOD_FRAMEWORK_PATH, projectCopy, projectDeps } from '../actionsLib.mjs'

/**
* @typedef {import('@actions/exec').ExecOptions} ExecOptions
*/

/**
* @callback ExecInProject
* @param {string} commandLine command to execute (can include additional args). Must be correctly escaped.
* @param {Omit<ExecOptions, "cwd">=} options exec options. See ExecOptions
* @returns {Promise<unknown>} exit code
*/

/**
* @param {string} rsaProjectPath
* @param {Object} core
* @param {(key: string, value: string) => void} core.setOutput
* @param {ExecInProject} execInProject
* @returns {Promise<void>}
*/
export async function main(
rsaProjectPath,
core,
execInProject
) {
core.setOutput('rsa-project-path', rsaProjectPath)

console.log('rwPath', REDWOOD_FRAMEWORK_PATH)
console.log('rsaProjectPath', rsaProjectPath)

await setUpRsaTestProject(
rsaProjectPath,
execInProject,
)
}

/**
* @param {string} rsaProjectPath
* @param {ExecInProject} execInProject
* @returns {Promise<void>}
*/
async function setUpRsaTestProject(rsaProjectPath, execInProject) {
const fixturePath = path.join(
REDWOOD_FRAMEWORK_PATH,
'__fixtures__',
'test-project-rsa'
)
const rwBinPath = path.join(
REDWOOD_FRAMEWORK_PATH,
'packages/cli/dist/index.js'
)
const rwfwBinPath = path.join(
REDWOOD_FRAMEWORK_PATH,
'packages/cli/dist/rwfw.js'
)

console.log(`Creating project at ${rsaProjectPath}`)
console.log()
fs.cpSync(fixturePath, rsaProjectPath, { recursive: true })

console.log(`Adding framework dependencies to ${rsaProjectPath}`)
await projectDeps(rsaProjectPath)
console.log()

console.log(`Installing node_modules in ${rsaProjectPath}`)
await execInProject('yarn install')

console.log(`Building project in ${rsaProjectPath}`)
await execInProject(`node ${rwBinPath} build -v`)
console.log()

console.log(`Copying over framework files to ${rsaProjectPath}`)
await execInProject(`node ${rwfwBinPath} project:copy`, {
env: { RWFW_PATH: REDWOOD_FRAMEWORK_PATH },
})
console.log()

// await cache.saveCache([rsaProjectPath], dependenciesKey)
// console.log(`Cache saved with key: ${dependenciesKey}`)
}

// async function setUpRsaFromFixture(
// rsaProjectPath,
// exec,
// execInProject,
// ) {
// const rwBinPath = path.join(
// REDWOOD_FRAMEWORK_PATH,
// 'packages/cli/dist/index.js'
// )
// const rwfwBinPath = path.join(
// REDWOOD_FRAMEWORK_PATH,
// 'packages/cli/dist/rwfw.js'
// )

// console.log(`Creating project at ${rsaProjectPath}`)
// console.log()
// await exec('npx', [
// '-y',
// 'create-redwood-app@canary',
// '-y',
// '--no-git',
// rscProjectPath,
// ])

// console.log(`Setting up Streaming/SSR in ${rscProjectPath}`)
// const cmdSetupStreamingSSR = `node ${rwBinPath} experimental setup-streaming-ssr -f`
// await execInProject(cmdSetupStreamingSSR)
// console.log()

// console.log(`Setting up RSC in ${rscProjectPath}`)
// await execInProject(`node ${rwBinPath} experimental setup-rsc`)
// console.log()

// console.log(`Building project in ${rscProjectPath}`)
// await execInProject(`node ${rwBinPath} build -v`)
// console.log()

// console.log(`Building project in ${rscProjectPath}`)
// await execInProject(`node ${rwfwBinPath} project:copy`, {
// env: { RWFW_PATH: REDWOOD_FRAMEWORK_PATH },
// })
// console.log()
// }
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* eslint-env node */
// @ts-check

import path from 'node:path'

import core from '@actions/core'

import { createExecWithEnvInCwd } from '../actionsLib.mjs'

import { main } from './setUpRscFromFixture.mjs'

const rsaProjectPath = path.join(path.dirname(process.cwd()), 'rsa-project')

const execInProject = createExecWithEnvInCwd(rsaProjectPath)

main(rsaProjectPath, core, execInProject)
103 changes: 103 additions & 0 deletions .github/actions/set-up-rsc-from-fixture/setUpRscFromFixtureLocally.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/* eslint-env node */
// @ts-check

import os from 'node:os'
import path from 'node:path'

import execa from 'execa'

import { main } from './setUpRscFromFixture.mjs'

class ExecaError extends Error {
stdout
stderr
exitCode

constructor({ stdout, stderr, exitCode }) {
super(`execa failed with exit code ${exitCode}`)
this.stdout = stdout
this.stderr = stderr
this.exitCode = exitCode
}
}

/**
* @template [EncodingType=string]
* @typedef {import('execa').Options<EncodingType>} ExecaOptions<T>
*/

/**
* @typedef {{
* env?: Record<string, string>
* }} ExecOptions
*/

/**
* @param {string} commandLine command to execute (can include additional args). Must be correctly escaped.
* @param {string[]=} args arguments for tool. Escaping is handled by the lib.
* @param {ExecOptions=} options exec options. See ExecOptions
*/
async function exec(commandLine, args, options) {
return execa(commandLine, args, options)
.then(({ stdout, stderr, exitCode }) => {
if (exitCode !== 0) {
throw new ExecaError({ stdout, stderr, exitCode })
}
})
.catch((error) => {
if (error instanceof ExecaError) {
// Rethrow ExecaError
throw error
} else {
const { stdout, stderr, exitCode } = error
console.log('error', error)
throw new ExecaError({ stdout, stderr, exitCode })
}
})
}

/**
* @param {string} cwd
* @param {Record<string, string>=} env
* @returns {ExecaOptions<string>}
*/
function getExecaOptions(cwd, env = {}) {
return {
shell: true,
stdio: 'inherit',
cleanup: true,
cwd,
env,
}
}

const rsaProjectPath = path.join(
os.tmpdir(),
'redwood-rsa-project',
// ":" is problematic with paths
new Date().toISOString().split(':').join('-')
)

// Mock for @actions/core
const core = {
setOutput: () => {},
}

/**
* Exec a command.
* Output will be streamed to the live console.
* Returns promise with return code
*
* @param {string} commandLine command to execute (can include additional args). Must be correctly escaped.
* @param {ExecOptions=} options exec options. See ExecOptions
* @returns {Promise<unknown>} exit code
*/
function execInProject(commandLine, options) {
return exec(
commandLine,
undefined,
getExecaOptions(rsaProjectPath, options?.env)
)
}

main(rsaProjectPath, core, execInProject)
2 changes: 1 addition & 1 deletion .github/actions/set-up-rsc-project/setUpRscProject.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ async function setUpRscProject(
await execInProject(`node ${rwBinPath} build -v`)
console.log()

console.log(`Building project in ${rscProjectPath}`)
console.log(`Copying over framework files to ${rscProjectPath}`)
await execInProject(`node ${rwfwBinPath} project:copy`, {
env: { RWFW_PATH: REDWOOD_FRAMEWORK_PATH },
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ function getExecaOptions(cwd, env = {}) {

const rscProjectPath = path.join(
os.tmpdir(),
'rsc-project',
'redwood-rsc-project',
// ":" is problematic with paths
new Date().toISOString().split(':').join('-')
)
Expand Down
14 changes: 14 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,20 @@ jobs:
REDWOOD_TEST_PROJECT_PATH: ${{ steps.set-up-rsc-project.outputs.rsc-project-path }}
REDWOOD_DISABLE_TELEMETRY: 1

- name: 🌲 Set up RSC from fixture
id: set-up-rsc-from-fixture
uses: ./.github/actions/set-up-rsc-from-fixture
env:
REDWOOD_DISABLE_TELEMETRY: 1
YARN_ENABLE_IMMUTABLE_INSTALLS: false

- name: 🐘 Run RSA smoke tests
working-directory: tasks/smoke-tests/rsa
run: npx playwright test
env:
REDWOOD_TEST_PROJECT_PATH: ${{ steps.set-up-rsc-from-fixture.outputs.rsa-project-path }}
REDWOOD_DISABLE_TELEMETRY: 1

rsc-smoke-tests-mock:
needs: rsc-related-changes
if: needs.rsc-related-changes.outputs.rsc-related-changes != 'true'
Expand Down
10 changes: 10 additions & 0 deletions __fixtures__/test-project-rsa/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# editorconfig.org
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
19 changes: 19 additions & 0 deletions __fixtures__/test-project-rsa/.env.defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# These environment variables will be used by default if you do not create any
# yourself in .env. This file should be safe to check into your version control
# system. Any custom values should go in .env and .env should *not* be checked
# into version control.

# schema.prisma defaults
DATABASE_URL=file:./dev.db

# location of the test database for api service scenarios (defaults to ./.redwood/test.db if not set)
# TEST_DATABASE_URL=file:./.redwood/test.db

# disables Prisma CLI update notifier
PRISMA_HIDE_UPDATE_MESSAGE=true

# Option to override the current environment's default api-side log level
# See: https://redwoodjs.com/docs/logger for level options, defaults to "trace" otherwise.
# Most applications want "debug" or "info" during dev, "trace" when you have issues and "warn" in production.
# Ordered by how verbose they are: trace | debug | info | warn | error | silent
# LOG_LEVEL=debug
4 changes: 4 additions & 0 deletions __fixtures__/test-project-rsa/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# DATABASE_URL=file:./dev.db
# TEST_DATABASE_URL=file:./.redwood/test.db
# PRISMA_HIDE_UPDATE_MESSAGE=true
# LOG_LEVEL=trace
Loading

0 comments on commit 129abbc

Please sign in to comment.