Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add test to verify create fuels template integrity #2364

Merged
Merged
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
fe57087
chore: added basic integration test
petertonysmith94 May 21, 2024
dca1f09
chore: extract useful functions from test
petertonysmith94 May 21, 2024
82aa214
chore: moved copy logic out of bootstrapProject
petertonysmith94 May 21, 2024
c002294
chore: extracted generateArgs function
petertonysmith94 May 21, 2024
1545d7e
chore: separate argv from args (in generate)
petertonysmith94 May 21, 2024
55dc06e
chore: added `@fuel-ts/errors` to `create-fuels`
petertonysmith94 May 21, 2024
4bed711
Merge branch 'master' of https://github.com/FuelLabs/fuels-ts into ps…
petertonysmith94 May 21, 2024
1c6bba4
chore: lint
petertonysmith94 May 21, 2024
2bcb8b1
feat: added integration test
petertonysmith94 May 21, 2024
bcf6979
chore: filter out the forc build files
petertonysmith94 May 21, 2024
bb250c1
Removed resetMock
petertonysmith94 May 21, 2024
f6e760b
chore: lint
petertonysmith94 May 21, 2024
e435a6a
Remove the timeout
petertonysmith94 May 21, 2024
31751e7
ci: hooked up job to perform test
petertonysmith94 May 21, 2024
83a1af6
chore: added timeout
petertonysmith94 May 21, 2024
616f061
chore: added `next-env.d.ts` into template bootstrap
petertonysmith94 May 22, 2024
0e768d0
Rebuild
petertonysmith94 May 22, 2024
cffe61a
debug: added debugging for CI related failure
petertonysmith94 May 22, 2024
323b88e
chore: added env to action step
petertonysmith94 May 22, 2024
87f31de
chore: added `process.env` to vitest env loading
petertonysmith94 May 22, 2024
ac5f243
debug: test env is defined
petertonysmith94 May 22, 2024
679ffbb
ci: added output for `published_version`
petertonysmith94 May 22, 2024
65adb0b
chore: fixed `fuelsVersion` format to match CI
petertonysmith94 May 22, 2024
fe79043
Revert "chore: fixed `fuelsVersion` format to match CI"
petertonysmith94 May 22, 2024
09dfecf
Revert "debug: added debugging for CI related failure"
petertonysmith94 May 22, 2024
3f4ae01
chore: finalized integration test
petertonysmith94 May 22, 2024
55df629
Revert "chore: added `process.env` to vitest env loading"
petertonysmith94 May 22, 2024
03b8ed3
chore: refactored publish to NPM into action
petertonysmith94 May 22, 2024
5be3354
chore: changeset
petertonysmith94 May 22, 2024
67e6ad2
chore: lint
petertonysmith94 May 22, 2024
31d304c
ci: added missing shell
petertonysmith94 May 22, 2024
21a7238
chore: added integration tests to validation step
petertonysmith94 May 22, 2024
ccfbdad
ci: added integration test to pipeline
petertonysmith94 May 22, 2024
d1f803d
ci: added missing `steps.`
petertonysmith94 May 22, 2024
f9eee48
ci: removed draft condition for testing
petertonysmith94 May 22, 2024
b191865
fix: tests
petertonysmith94 May 22, 2024
11fdcab
chore: lint
petertonysmith94 May 22, 2024
8b96e6b
ci: added outputs published_version to action
petertonysmith94 May 22, 2024
1337770
ci: added echo published version
petertonysmith94 May 22, 2024
0d60357
ci: add output value
petertonysmith94 May 22, 2024
2560713
ci: disable publish PR
petertonysmith94 May 22, 2024
95b1fe6
ci: only run integration tests on non-draft
petertonysmith94 May 22, 2024
27db035
ci: fixed GITHUB_TOKEN
petertonysmith94 May 22, 2024
2389496
ci: removed redundant outputs
petertonysmith94 May 22, 2024
8f8942e
Merge branch 'master' into ps/chore/add-automated-test-suite-for-crea…
petertonysmith94 May 22, 2024
ee00afb
Merge branch 'master' into ps/chore/add-automated-test-suite-for-crea…
petertonysmith94 May 23, 2024
40cecca
chore: using secrets over passing through variables
petertonysmith94 May 23, 2024
060f50f
chore: moved to `e2e` test
petertonysmith94 May 23, 2024
ed1f8e4
Revert "chore: using secrets over passing through variables"
petertonysmith94 May 23, 2024
65d59a9
chore: skip e2e locally with log
petertonysmith94 May 23, 2024
a085676
chore: fixed name
petertonysmith94 May 23, 2024
710ea46
Merge branch 'master' into ps/chore/add-automated-test-suite-for-crea…
Dhaiwat10 May 23, 2024
7d4c007
Merge branch 'master' into ps/chore/add-automated-test-suite-for-crea…
petertonysmith94 May 24, 2024
556360c
Merge branch 'master' into ps/chore/add-automated-test-suite-for-crea…
petertonysmith94 May 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/chilly-shirts-bathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-fuels": patch
---

chore: add test to verify `create fuels` template integrity
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
FUEL_NETWORK_URL=
TEST_WALLET_PVT_KEY=
PUBLISHED_NPM_VERSION=
41 changes: 41 additions & 0 deletions .github/actions/pr-release/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: "Publish PR to NPM"
inputs:
npm-token:
description: "NPM token for authenticating to NPM registry"
required: true

github-token:
description: "GitHub token for authenticating to GitHub"
required: true
danielbate marked this conversation as resolved.
Show resolved Hide resolved

pr-number:
description: "PR number"
default: ${{ github.event.pull_request.number }}

outputs:
published_version:
description: "Published version of the PR"
value: ${{ steps.release.outputs.published_version }}

runs:
using: "composite"
steps:
- name: Ensure NPM access
shell: bash
run: npm whoami
env:
NODE_AUTH_TOKEN: ${{ inputs.npm-token }}

- name: Release to @pr-${{ inputs.pr-number }} tag on npm
id: release
shell: bash
run: |
pnpm changeset:next
git add .changeset/fuel-labs-ci.md
pnpm changeset version --snapshot pr-${{ inputs.pr-number }}
changetsets=$(pnpm changeset publish --tag pr-${{ inputs.pr-number }})
published_version=$(echo "$changetsets" | grep -oP '@\K([0-9]+\.){2}[0-9]+-pr-${{ inputs.pr-number }}-\d+' | head -1)
echo "published_version=$published_version" >> $GITHUB_OUTPUT
env:
NODE_AUTH_TOKEN: ${{ inputs.npm-token }}
GITHUB_TOKEN: ${{ inputs.github-token }}
25 changes: 7 additions & 18 deletions .github/workflows/pr-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,20 @@ jobs:
- name: CI Setup
uses: ./.github/actions/ci-setup

- name: Ensure NPM access
run: npm whoami
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Build
run: pnpm build

- name: Release to @pr-${{ github.event.pull_request.number }} tag on npm
- name: Publish to NPM
id: release
run: |
pnpm changeset:next
git add .changeset/fuel-labs-ci.md
pnpm changeset version --snapshot pr-${{ env.PR_NUMBER }}
changetsets=$(pnpm changeset publish --tag pr-${{ env.PR_NUMBER }})
published_version=$(echo "$changetsets" | grep -oP '@\K([0-9]+\.){2}[0-9]+-pr-${{ env.PR_NUMBER }}-\d+' | head -1)
echo "published_version=$published_version" >> $GITHUB_OUTPUT
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
uses: ./.github/actions/pr-release
with:
npm-token: ${{ secrets.NPM_TOKEN }}
github-token: ${{ secrets.GITHUB_TOKEN }}
pr-number: ${{ github.event.pull_request.number }}

- uses: mshick/add-pr-comment@v2
with:
message: |
This PR is published in NPM with version **${{ steps.release.outputs.published_version }}**
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
13 changes: 12 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,19 @@ jobs:
with:
fetch-depth: 0

- name: CI Setup
- name: Test Setup
uses: ./.github/actions/test-setup

- name: Publish PR to NPM
id: release
uses: ./.github/actions/pr-release
with:
npm-token: ${{ secrets.NPM_TOKEN }}
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Echo Published Version
run: echo ${{ steps.release.outputs.published_version }}

- name: Pretest
run: pnpm pretest

Expand All @@ -71,6 +81,7 @@ jobs:
TEST_WALLET_PVT_KEY: ${{ secrets.TEST_WALLET_PVT_KEY }}
TEST_WALLET_ADDRESS: ${{ secrets.TEST_WALLET_ADDRESS }}
FUEL_TESTNET_NETWORK_URL: ${{ secrets.FUEL_TESTNET_NETWORK_URL }}
PUBLISHED_NPM_VERSION: ${{ steps.release.outputs.published_version }}

test:
if: github.base_ref == 'master' || github.ref_name == 'master'
Expand Down
1 change: 1 addition & 0 deletions packages/create-fuels/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"prompts": "^2.4.2"
},
"devDependencies": {
"@fuel-ts/errors": "workspace:*",
"@fuel-ts/versions": "workspace:*",
"@types/prompts": "^2.4.8",
"glob": "^10.2.6"
Expand Down
70 changes: 12 additions & 58 deletions packages/create-fuels/test/cli.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { mkdirSync } from 'fs';
import { glob } from 'glob';

import type { ProgramsToInclude } from '../src/cli';
import { runScaffoldCli, setupProgram } from '../src/cli';

import type { ProjectPaths } from './utils/bootstrapProject';
import { bootstrapProject, cleanupFilesystem, resetFilesystem } from './utils/bootstrapProject';
import {
bootstrapProject,
cleanupFilesystem,
copyTemplate,
resetFilesystem,
} from './utils/bootstrapProject';
import { generateArgv } from './utils/generateArgs';
import { mockLogger } from './utils/mockLogger';

const getAllFiles = async (pathToDir: string) => {
const files = await glob(`${pathToDir}/**/*`, {
ignore: ['**/node_modules/**', '**/.next/**', '**/sway-api/**'],
});
const filesWithoutPrefix = files.map((file) => file.replace(pathToDir, ''));
return filesWithoutPrefix;
};
import { filterOriginalTemplateFiles, getAllFiles } from './utils/templateFiles';

const possibleProgramsToInclude: ProgramsToInclude[] = [
{ contract: true, predicate: false, script: false },
Expand All @@ -26,51 +24,6 @@ const possibleProgramsToInclude: ProgramsToInclude[] = [
{ contract: true, predicate: true, script: true },
];

const defaultFlags = ['--pnpm'];

const generateArgs = (programsToInclude: ProgramsToInclude, projectName?: string) => {
const args = ['', ''];
if (projectName) {
args.push(projectName);
}
if (programsToInclude.contract) {
args.push('-c');
}
if (programsToInclude.predicate) {
args.push('-p');
}
if (programsToInclude.script) {
args.push('-s');
}
args.push(...defaultFlags);
return args;
};

const filterOriginalTemplateFiles = (files: string[], programsToInclude: ProgramsToInclude) => {
let newFiles = [...files];

newFiles = newFiles.filter((file) => {
if (file.includes('CHANGELOG')) {
return false;
}
if (!programsToInclude.contract && file.includes('contract')) {
return false;
}
if (!programsToInclude.predicate && file.includes('predicate')) {
return false;
}
if (!programsToInclude.script && file.includes('script')) {
return false;
}
if (['/gitignore', '/env'].includes(file)) {
return false;
}
return true;
});

return newFiles;
};

/**
* @group node
*/
Expand All @@ -80,6 +33,7 @@ describe('CLI', () => {

beforeEach(() => {
paths = bootstrapProject(__filename);
copyTemplate(paths.sourceTemplate, paths.template);
});

afterEach(() => {
Expand All @@ -95,7 +49,7 @@ describe('CLI', () => {
test.each(possibleProgramsToInclude)(
'create-fuels extracts the template to the specified directory',
async (programsToInclude) => {
const args = generateArgs(programsToInclude, paths.root);
const args = generateArgv(programsToInclude, paths.root);

await runScaffoldCli({
program: setupProgram(),
Expand All @@ -113,7 +67,7 @@ describe('CLI', () => {
);

test('create-fuels reports an error if the project directory already exists', async () => {
const args = generateArgs(
const args = generateArgv(
{
contract: true,
predicate: true,
Expand All @@ -140,7 +94,7 @@ describe('CLI', () => {
});

test('create-fuels reports an error if no programs are chosen to be included', async () => {
const args = generateArgs(
const args = generateArgv(
{
contract: false,
predicate: false,
Expand Down
65 changes: 65 additions & 0 deletions packages/create-fuels/test/e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { safeExec } from '@fuel-ts/errors/test-utils';
import { execSync } from 'child_process';

import type { ProjectPaths } from './utils/bootstrapProject';
import { bootstrapProject, resetFilesystem } from './utils/bootstrapProject';
import { generateArgs } from './utils/generateArgs';
import {
filterForcBuildFiles,
filterOriginalTemplateFiles,
getAllFiles,
} from './utils/templateFiles';

const { log } = console;

const PUBLISHED_NPM_VERSION = process.env.PUBLISHED_NPM_VERSION;
const programsToInclude = { contract: true, predicate: true, script: true };
const availablePackages = ['pnpm'];

/**
* @group e2e
*/
describe('`create fuels` package integrity', () => {
let paths: ProjectPaths;
let shouldSkip = false;

beforeAll(() => {
if (!PUBLISHED_NPM_VERSION) {
log('Skipping live `create fuels` test');
nedsalk marked this conversation as resolved.
Show resolved Hide resolved
shouldSkip = true;
}
});

beforeEach(() => {
paths = bootstrapProject(__filename);
});

afterEach(() => {
resetFilesystem(paths.root);
});

it.each(availablePackages)(
'should perform `%s create fuels`',
async (packageManager) => {
if (shouldSkip) {
return;
}

const args = generateArgs(programsToInclude, paths.root, packageManager).join(' ');
const expectedTemplateFiles = await getAllFiles(paths.sourceTemplate).then((files) =>
filterOriginalTemplateFiles(files, programsToInclude).filter(filterForcBuildFiles)
);

const { error: createFuelsError } = await safeExec(() =>
execSync(`${packageManager} create fuels@${PUBLISHED_NPM_VERSION} ${args}`, {
stdio: 'inherit',
})
);

const actualTemplateFiles = await getAllFiles(paths.root);
expect(createFuelsError).toBeUndefined();
expect(actualTemplateFiles.sort()).toEqual(expectedTemplateFiles.sort());
},
{ timeout: 30000 }
);
});
11 changes: 8 additions & 3 deletions packages/create-fuels/test/utils/bootstrapProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { basename, join } from 'path';
export type ProjectPaths = {
root: string;
template: string;
sourceTemplate: string;
};

/**
Expand All @@ -21,9 +22,6 @@ export const bootstrapProject = (
// Template paths
const templateDir = join(templatesDir, templateName);
const localTemplateDir = join(testTemplateDir, templateName);
if (!existsSync(localTemplateDir)) {
cpSync(templateDir, localTemplateDir, { recursive: true });
}

// Unique name
const testFilename = basename(testFilepath.replace(/\./g, '-'));
Expand All @@ -35,9 +33,16 @@ export const bootstrapProject = (
return {
root,
template: localTemplateDir,
sourceTemplate: templateDir,
};
};

export const copyTemplate = (srcDir: string, destDir: string) => {
if (!existsSync(destDir)) {
cpSync(srcDir, destDir, { recursive: true });
}
};

export const resetFilesystem = (dirPath: string) => {
if (existsSync(dirPath)) {
rmSync(dirPath, { recursive: true });
Expand Down
28 changes: 28 additions & 0 deletions packages/create-fuels/test/utils/generateArgs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { ProgramsToInclude } from '../../src/cli';

export const generateArgs = (
programsToInclude: ProgramsToInclude,
projectName?: string,
packageManager: string = 'pnpm'
): string[] => {
const args = [];
if (projectName) {
args.push(projectName);
}
if (programsToInclude.contract) {
args.push('-c');
}
if (programsToInclude.predicate) {
args.push('-p');
}
if (programsToInclude.script) {
args.push('-s');
}
args.push(`--${packageManager}`);
return args;
};

export const generateArgv = (
programsToInclude: ProgramsToInclude,
projectName?: string
): string[] => ['', '', ...generateArgs(programsToInclude, projectName)];
Loading
Loading