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

test: add non-interactive init/pull in git-cloned project #11365

Merged
merged 7 commits into from
Nov 11, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
1 change: 1 addition & 0 deletions .eslint-dictionary.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
"uint",
"unauth",
"unlink",
"unstaged",
"updateamplify",
"urls",
"userpool",
Expand Down
1 change: 1 addition & 0 deletions packages/amplify-e2e-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"execa": "^5.1.1",
"fs-extra": "^8.1.0",
"graphql-transformer-core": "^7.6.6",
"ini": "^1.3.5",
"jest-environment-node": "^26.6.2",
"lodash": "^4.17.21",
"node-fetch": "^2.6.7",
Expand Down
46 changes: 8 additions & 38 deletions packages/amplify-e2e-core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/* eslint-disable prefer-arrow/prefer-arrow-functions */
/* eslint-disable func-style */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable jsdoc/require-jsdoc */
/* eslint-disable import/no-cycle */
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file is minimal lint fixes after moving the isCI function to a different file

import * as os from 'os';
import * as path from 'path';
import * as fs from 'fs-extra';
Expand All @@ -12,12 +17,12 @@ export * from './configure';
export * from './init';
export * from './utils';
export * from './categories';
export * from './utils/sdk-calls';
export * from './export';
export { addFeatureFlag } from './utils/feature-flags';
export * from './cli-version-controller';

declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace NodeJS {
interface Global {
getRandomId: () => string;
Expand All @@ -27,9 +32,6 @@ declare global {

const amplifyTestsDir = 'amplify-e2e-tests';

/**
*
*/
export function getCLIPath(testingWithLatestCodebase = false) {
if (!testingWithLatestCodebase) {
if (process.env.AMPLIFY_PATH && fs.existsSync(process.env.AMPLIFY_PATH)) {
Expand All @@ -43,16 +45,10 @@ export function getCLIPath(testingWithLatestCodebase = false) {
return amplifyScriptPath;
}

/**
*
*/
export function isTestingWithLatestCodebase(scriptRunnerPath) {
return scriptRunnerPath === process.execPath;
}

/**
*
*/
export function getScriptRunnerPath(testingWithLatestCodebase = false) {
if (!testingWithLatestCodebase) {
return process.platform === 'win32' ? 'node.exe' : 'exec';
Expand All @@ -62,9 +58,6 @@ export function getScriptRunnerPath(testingWithLatestCodebase = false) {
return process.execPath;
}

/**
*
*/
export function getNpxPath() {
let npxPath = 'npx';
if (process.platform === 'win32') {
Expand All @@ -73,9 +66,6 @@ export function getNpxPath() {
return npxPath;
}

/**
*
*/
export function getNpmPath() {
let npmPath = 'npm';
if (process.platform === 'win32') {
Expand All @@ -84,33 +74,17 @@ export function getNpmPath() {
return npmPath;
}

/**
*
*/
export function isCI(): boolean {
return !!(process.env.CI && process.env.CIRCLECI);
}

/**
*
*/
export function injectSessionToken(profileName: string) {
const credentialsContents = ini.parse(fs.readFileSync(pathManager.getAWSCredentialsFilePath()).toString());
credentialsContents[profileName] = credentialsContents[profileName] || {};
credentialsContents[profileName].aws_session_token = process.env.AWS_SESSION_TOKEN;
fs.writeFileSync(pathManager.getAWSCredentialsFilePath(), ini.stringify(credentialsContents));
}

/**
*
*/
export function npmInstall(cwd: string) {
spawnSync('npm', ['install'], { cwd });
}

/**
*
*/
export async function installAmplifyCLI(version = 'latest') {
spawnSync('npm', ['install', '-g', `@aws-amplify/cli@${version}`], {
cwd: process.cwd(),
Expand All @@ -122,11 +96,9 @@ export async function installAmplifyCLI(version = 'latest') {
: path.join(os.homedir(), '.npm-global', 'bin', 'amplify');
}

/**
*
*/
export async function createNewProjectDir(
projectName: string,
// eslint-disable-next-line spellcheck/spell-checker
prefix = path.join(fs.realpathSync(os.tmpdir()), amplifyTestsDir),
): Promise<string> {
const currentHash = execSync('git rev-parse --short HEAD', { cwd: __dirname }).toString().trim();
Expand All @@ -141,10 +113,8 @@ export async function createNewProjectDir(
return projectDir;
}

/**
*
*/
export const createTempDir = () => {
// eslint-disable-next-line spellcheck/spell-checker
const osTempDir = fs.realpathSync(os.tmpdir());
const tempProjectDir = path.join(osTempDir, amplifyTestsDir, uuid());

Expand Down
13 changes: 13 additions & 0 deletions packages/amplify-e2e-core/src/init/headless-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Shape of awscloudformation object within `--profile` payload for init/pull
*/
Comment on lines +1 to +3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have a similar type in prod code base?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't have an exact corollary but we have some types here that define the credential config (plus other values that it can have)

export type AwsProviderConfig = {
configLevel: string,
useProfile: boolean,
profileName: string,
}

/**
* Shape of `--categories` payload for init/pull
*/
export type CategoriesConfig = Record<string, unknown>;
2 changes: 2 additions & 0 deletions packages/amplify-e2e-core/src/init/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/* eslint-disable import/no-cycle */
export * from './amplifyPull';
export * from './amplifyPush';
export * from './deleteProject';
export * from './initProjectHelper';
export * from './pull-headless';
export * from './adminUI';
export * from './overrideStack';
export * from './non-interactive-init';
56 changes: 56 additions & 0 deletions packages/amplify-e2e-core/src/init/non-interactive-init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import execa from 'execa';
// eslint-disable-next-line import/no-cycle
import { getCLIPath, TEST_PROFILE_NAME } from '..';
import { CategoriesConfig, AwsProviderConfig } from './headless-types';

/**
* Executes a non-interactive init to attach a local project to an existing cloud environment
*/
export const nonInteractiveInitAttach = async (
projRoot: string,
amplifyInitConfig: AmplifyInitConfig,
categoriesConfig?: CategoriesConfig,
awsProviderConfig = getAwsProviderConfig(),
): Promise<void> => {
const args = [
'init',
'--yes',
'--amplify',
JSON.stringify(amplifyInitConfig),
'--providers',
JSON.stringify({
awscloudformation: awsProviderConfig,
}),
];
if (categoriesConfig) {
args.push('--categories', JSON.stringify(categoriesConfig));
}
await execa(getCLIPath(), args, { cwd: projRoot });
};

/**
* Returns an AmplifyConfig object with a default editor
*/
export const getAmplifyInitConfig = (projectName: string, envName: string): AmplifyInitConfig => ({
projectName,
envName,
defaultEditor: 'code',
});

/**
* Returns a default AwsProviderConfig
*/
export const getAwsProviderConfig = (): AwsProviderConfig => ({
configLevel: 'project',
useProfile: true,
profileName: TEST_PROFILE_NAME,
});

/**
* Shape of `--amplify` payload for init/pull
*/
export type AmplifyInitConfig = {
projectName: string,
envName: string,
defaultEditor: string,
};
58 changes: 22 additions & 36 deletions packages/amplify-e2e-core/src/init/overrideStack.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,36 @@
/* eslint-disable jsdoc/require-jsdoc */
// eslint-disable-next-line import/no-cycle
import { nspawn as spawn, getCLIPath } from '..';

export function amplifyOverrideRoot(cwd: string, settings: { testingWithLatestCodebase?: boolean }) {
return new Promise((resolve, reject) => {
const args = ['override', 'project'];
export const amplifyOverrideRoot = (cwd: string, settings: { testingWithLatestCodebase?: boolean }): Promise<void> => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file is just lint fixes

const args = ['override', 'project'];

spawn(getCLIPath(settings.testingWithLatestCodebase), args, { cwd, stripColors: true })
.wait('Do you want to edit override.ts file now?')
.sendNo()
.sendEof()
.run((err: Error) => {
if (!err) {
resolve({});
} else {
reject(err);
}
});
});
}
return spawn(getCLIPath(settings.testingWithLatestCodebase), args, { cwd, stripColors: true })
.wait('Do you want to edit override.ts file now?')
.sendNo()
.sendEof()
.runAsync();
};

export function amplifyOverrideAuth(cwd: string, settings: {}) {
return new Promise((resolve, reject) => {
const args = ['override', 'auth'];
export const amplifyOverrideAuth = (cwd: string): Promise<void> => {
const args = ['override', 'auth'];

spawn(getCLIPath(), args, { cwd, stripColors: true })
.wait('Do you want to edit override.ts file now?')
.sendNo()
.sendEof()
.run((err: Error) => {
if (!err) {
resolve({});
} else {
reject(err);
}
});
});
}
return spawn(getCLIPath(), args, { cwd, stripColors: true })
.wait('Do you want to edit override.ts file now?')
.sendNo()
.sendEof()
.runAsync();
};

export function amplifyOverrideApi(cwd: string, settings: any) {
export const amplifyOverrideApi = (cwd: string): Promise<void> => {
const args = ['override', 'api'];
const chain = spawn(getCLIPath(), args, { cwd, stripColors: true });
chain.wait('Do you want to edit override.ts file now?').sendNo().sendEof();
return chain.runAsync();
}
};

export function buildOverrides(cwd: string, settings: any) {
export const buildOverrides = (cwd: string): Promise<void> => {
const args = ['build'];
const chain = spawn(getCLIPath(), args, { cwd, stripColors: true });
return chain.runAsync();
}
};
Loading