-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ci): isolate smoke tests, introduce caching
- Loading branch information
Showing
31 changed files
with
1,286 additions
and
1,311 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/* eslint-env node */ | ||
// @ts-check | ||
|
||
import { fileURLToPath } from 'node:url' | ||
|
||
import { getExecOutput } from '@actions/exec' | ||
import { hashFiles } from '@actions/glob' | ||
|
||
/** | ||
* @typedef {import('@actions/exec').ExecOptions} ExecOptions | ||
*/ | ||
|
||
export const REDWOOD_FRAMEWORK_PATH = fileURLToPath(new URL('../../', import.meta.url)) | ||
|
||
/** | ||
* @param {string} command | ||
* @param {ExecOptions} options | ||
*/ | ||
function execWithEnv(command, { env = {}, ...rest } = {}) { | ||
return getExecOutput( | ||
command, | ||
undefined, | ||
{ | ||
// @ts-expect-error TS doesn't like spreading process.env here but it's fine | ||
env: { | ||
...process.env, | ||
...env | ||
}, | ||
...rest | ||
} | ||
) | ||
} | ||
|
||
/** | ||
* @param {string} cwd | ||
*/ | ||
export function createExecWithEnvInCwd(cwd) { | ||
/** | ||
* @param {string} command | ||
* @param {Omit<ExecOptions, 'cwd'>} options | ||
*/ | ||
return function (command, options = {}) { | ||
return execWithEnv(command, { cwd, ...options }) | ||
} | ||
} | ||
|
||
export const execInFramework = createExecWithEnvInCwd(REDWOOD_FRAMEWORK_PATH) | ||
|
||
/** | ||
* @param {string} redwoodProjectCwd | ||
*/ | ||
export function projectDeps(redwoodProjectCwd) { | ||
return execInFramework('yarn project:deps', { env: { RWJS_CWD: redwoodProjectCwd } }) | ||
} | ||
|
||
/** | ||
* @param {string} redwoodProjectCwd | ||
*/ | ||
export function projectCopy(redwoodProjectCwd) { | ||
return execInFramework('yarn project:copy', { env: { RWJS_CWD: redwoodProjectCwd } }) | ||
} | ||
|
||
/** | ||
* @param {string} prefix | ||
*/ | ||
export async function createCacheKeys(prefix) { | ||
const baseKey = [ | ||
prefix, | ||
process.env.RUNNER_OS, | ||
].join('-') | ||
|
||
const dependenciesKey = [ | ||
baseKey, | ||
'dependencies', | ||
await hashFiles(['yarn.lock', '.yarnrc.yml'].join('\n')), | ||
].join('-') | ||
|
||
const distKey = [ | ||
dependenciesKey, | ||
'dist', | ||
await hashFiles([ | ||
'package.json', | ||
'babel.config.js', | ||
'tsconfig.json', | ||
'tsconfig.compilerOption.json', | ||
'nx.json', | ||
'lerna.json', | ||
'packages', | ||
].join('\n')) | ||
].join('-') | ||
|
||
return { | ||
baseKey, | ||
dependenciesKey, | ||
distKey | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
name: Set up test project | ||
description: Set up the test project fixture | ||
|
||
runs: | ||
# `node18` isn't supported yet | ||
using: node16 | ||
main: 'setUpTestProject.mjs' |
106 changes: 106 additions & 0 deletions
106
.github/actions/set-up-test-project/setUpTestProject.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* eslint-env node */ | ||
// @ts-check | ||
|
||
import path from 'node:path' | ||
|
||
import cache from '@actions/cache' | ||
import core from '@actions/core' | ||
|
||
import fs from 'fs-extra' | ||
|
||
import { | ||
createCacheKeys, | ||
createExecWithEnvInCwd, | ||
projectCopy, | ||
projectDeps, | ||
REDWOOD_FRAMEWORK_PATH, | ||
} from '../actionsLib.mjs' | ||
|
||
const TEST_PROJECT_PATH = core.getInput('test-project-path') | ||
|
||
const { | ||
dependenciesKey, | ||
distKey | ||
} = await createCacheKeys('test-project') | ||
|
||
/** | ||
* @returns {Promise<void>} | ||
*/ | ||
async function main() { | ||
const distCacheKey = await cache.restoreCache([TEST_PROJECT_PATH], distKey) | ||
|
||
if (distCacheKey) { | ||
console.log(`Cache restored from key: ${distKey}`) | ||
return | ||
} | ||
|
||
const dependenciesCacheKey = await cache.restoreCache([TEST_PROJECT_PATH], dependenciesKey) | ||
|
||
if (dependenciesCacheKey) { | ||
console.log(`Cache restored from key: ${dependenciesKey}`) | ||
await sharedTasks() | ||
} else { | ||
console.log(`Cache not found for input keys: ${distKey}, ${dependenciesKey}`) | ||
await setUpTestProject() | ||
} | ||
|
||
await cache.saveCache([TEST_PROJECT_PATH], distKey) | ||
console.log(`Cache saved with key: ${distKey}`) | ||
} | ||
|
||
/** | ||
* @returns {Promise<void>} | ||
*/ | ||
async function setUpTestProject() { | ||
const TEST_PROJECT_FIXTURE_PATH = path.join( | ||
REDWOOD_FRAMEWORK_PATH, | ||
'__fixtures__', | ||
'test-project' | ||
) | ||
|
||
console.log(`Creating project at ${TEST_PROJECT_PATH}`) | ||
console.log() | ||
await fs.copy(TEST_PROJECT_FIXTURE_PATH, TEST_PROJECT_PATH) | ||
|
||
console.log(`Adding framework dependencies to ${TEST_PROJECT_PATH}`) | ||
await projectDeps(TEST_PROJECT_PATH) | ||
console.log() | ||
|
||
console.log(`Installing node_modules in ${TEST_PROJECT_PATH}`) | ||
await execInProject('yarn install') | ||
console.log() | ||
|
||
await cache.saveCache([TEST_PROJECT_PATH], dependenciesKey) | ||
console.log(`Cache saved with key: ${dependenciesKey}`) | ||
|
||
await sharedTasks() | ||
} | ||
|
||
const execInProject = createExecWithEnvInCwd(TEST_PROJECT_PATH) | ||
|
||
/** | ||
* @returns {Promise<void>} | ||
*/ | ||
async function sharedTasks() { | ||
console.log('Copying framework packages to project') | ||
await projectCopy(TEST_PROJECT_PATH) | ||
console.log() | ||
|
||
console.log('Generating dbAuth secret') | ||
const { stdout } = await execInProject( | ||
'yarn rw g secret --raw', | ||
{ silent: true } | ||
) | ||
fs.appendFileSync( | ||
path.join(TEST_PROJECT_PATH, '.env'), | ||
`SESSION_SECRET='${stdout}'` | ||
) | ||
console.log() | ||
|
||
console.log('Running prisma migrate reset') | ||
await execInProject( | ||
'yarn rw prisma migrate reset --force', | ||
) | ||
} | ||
|
||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
name: Set up yarn cache | ||
description: Set up yarn cache | ||
|
||
runs: | ||
using: composite | ||
|
||
steps: | ||
# We try to cache and restore yarn's cache directory and install state to speed up the yarn install step. | ||
# Caching yarn's cache directory avoids its fetch step. | ||
- name: 📁 Get yarn cache directory | ||
id: get-yarn-cache-directory | ||
run: echo "CACHE_DIRECTORY=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT | ||
shell: bash | ||
|
||
# If the primary key doesn't match, the cache will probably be stale or incomplete, | ||
# but still worth restoring for the yarn install step. | ||
- name: ♻️ Restore yarn cache | ||
uses: actions/cache@v3 | ||
with: | ||
path: ${{ steps.get-yarn-cache-directory.outputs.CACHE_DIRECTORY }} | ||
key: yarn-cache-${{ runner.os }}-${{ hashFiles('yarn.lock', '.yarnrc.yml') }} | ||
restore-keys: yarn-cache-${{ runner.os }} | ||
|
||
# We avoid restore-keys for these steps because it's important to just start from scratch if something changes. | ||
# But most commits don't change `yarn.lock` or `.yarnrc.yml` ,so they'll be cached and restored most of the time. | ||
- name: ♻️ Restore yarn install state | ||
uses: actions/cache@v3 | ||
with: | ||
path: .yarn/install-state.gz | ||
key: yarn-install-state-${{ runner.os }}-${{ hashFiles('yarn.lock', '.yarnrc.yml') }} | ||
|
||
- name: ♻️ Restore node_modules | ||
uses: actions/cache@v3 | ||
with: | ||
path: '**/node_modules' | ||
key: yarn-node-modules-${{ runner.os }}-${{ hashFiles('yarn.lock', '.yarnrc.yml') }} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.