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

Release #802

Merged
merged 10 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
18 changes: 10 additions & 8 deletions .codebuild/e2e_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,24 +145,25 @@ batch:
depend-on:
- publish_to_local_registry
- identifier: >-
l_build_app_ts_uninitialized_project_codegen_js_uninitialized_project_modelgen_android_uninitialized_project_modelgen_flutter
l_build_app_ts_push_codegen_admin_modelgen_uninitialized_project_codegen_js_uninitialized_project_modelgen_android
buildspec: .codebuild/run_e2e_tests.yml
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
TEST_SUITE: >-
src/__tests__/build-app-ts.test.ts|src/__tests__/uninitialized-project-codegen-js.test.ts|src/__tests__/uninitialized-project-modelgen-android.test.ts|src/__tests__/uninitialized-project-modelgen-flutter.test.ts
src/__tests__/build-app-ts.test.ts|src/__tests__/push-codegen-admin-modelgen.test.ts|src/__tests__/uninitialized-project-codegen-js.test.ts|src/__tests__/uninitialized-project-modelgen-android.test.ts
CLI_REGION: ap-southeast-1
DISABLE_ESLINT_PLUGIN: true
depend-on:
- publish_to_local_registry
- identifier: l_uninitialized_project_modelgen_ios_uninitialized_project_modelgen_js
- identifier: >-
l_uninitialized_project_modelgen_flutter_uninitialized_project_modelgen_ios_uninitialized_project_modelgen_js
buildspec: .codebuild/run_e2e_tests.yml
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
TEST_SUITE: >-
src/__tests__/uninitialized-project-modelgen-ios.test.ts|src/__tests__/uninitialized-project-modelgen-js.test.ts
src/__tests__/uninitialized-project-modelgen-flutter.test.ts|src/__tests__/uninitialized-project-modelgen-ios.test.ts|src/__tests__/uninitialized-project-modelgen-js.test.ts
CLI_REGION: ap-southeast-2
depend-on:
- publish_to_local_registry
Expand Down Expand Up @@ -251,29 +252,30 @@ batch:
- publish_to_local_registry
- build_windows
- identifier: >-
w_build_app_ts_uninitialized_project_codegen_js_uninitialized_project_modelgen_android_uninitialized_project_modelgen_flutter
w_build_app_ts_push_codegen_admin_modelgen_uninitialized_project_codegen_js_uninitialized_project_modelgen_android
buildspec: .codebuild/run_e2e_tests_windows.yml
env:
compute-type: BUILD_GENERAL1_LARGE
image: $WINDOWS_IMAGE_2019
type: WINDOWS_SERVER_2019_CONTAINER
variables:
TEST_SUITE: >-
src/__tests__/build-app-ts.test.ts|src/__tests__/uninitialized-project-codegen-js.test.ts|src/__tests__/uninitialized-project-modelgen-android.test.ts|src/__tests__/uninitialized-project-modelgen-flutter.test.ts
src/__tests__/build-app-ts.test.ts|src/__tests__/push-codegen-admin-modelgen.test.ts|src/__tests__/uninitialized-project-codegen-js.test.ts|src/__tests__/uninitialized-project-modelgen-android.test.ts
CLI_REGION: us-east-1
DISABLE_ESLINT_PLUGIN: true
depend-on:
- publish_to_local_registry
- build_windows
- identifier: w_uninitialized_project_modelgen_ios_uninitialized_project_modelgen_js
- identifier: >-
w_uninitialized_project_modelgen_flutter_uninitialized_project_modelgen_ios_uninitialized_project_modelgen_js
buildspec: .codebuild/run_e2e_tests_windows.yml
env:
compute-type: BUILD_GENERAL1_LARGE
image: $WINDOWS_IMAGE_2019
type: WINDOWS_SERVER_2019_CONTAINER
variables:
TEST_SUITE: >-
src/__tests__/uninitialized-project-modelgen-ios.test.ts|src/__tests__/uninitialized-project-modelgen-js.test.ts
src/__tests__/uninitialized-project-modelgen-flutter.test.ts|src/__tests__/uninitialized-project-modelgen-ios.test.ts|src/__tests__/uninitialized-project-modelgen-js.test.ts
CLI_REGION: us-east-1
depend-on:
- publish_to_local_registry
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/closed-issue-message.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Closed Issue Message
on:
issues:
types: [closed]
jobs:
auto_comment:
runs-on: ubuntu-latest
steps:
- uses: aws-actions/closed-issue-message@v1
with:
# These inputs are both required
repo-token: '${{ secrets.GITHUB_TOKEN }}'
message: |
This issue is now closed. Comments on closed issues are hard for our team to see.
If you need more assistance, please open a new issue that references this one.
2 changes: 1 addition & 1 deletion dependency_licenses.txt
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ Apache License

-----

The following software may be included in this product: @aws-amplify/graphql-schema-test-library, @aws-amplify/graphql-transformer-interfaces, graphql-mapping-template, graphql-transformer-common, graphql-transformer-core. A copy of the source code may be downloaded from https://github.com/aws-amplify/amplify-category-api.git (@aws-amplify/graphql-schema-test-library), https://github.com/aws-amplify/amplify-category-api.git (@aws-amplify/graphql-transformer-interfaces), https://github.com/aws-amplify/amplify-category-api.git (graphql-mapping-template), https://github.com/aws-amplify/amplify-category-api.git (graphql-transformer-common), https://github.com/aws-amplify/amplify-category-api.git (graphql-transformer-core). This software contains the following license and notice below:
The following software may be included in this product: @aws-amplify/graphql-directives, @aws-amplify/graphql-schema-test-library, @aws-amplify/graphql-transformer-interfaces, graphql-mapping-template, graphql-transformer-common, graphql-transformer-core. A copy of the source code may be downloaded from https://github.com/aws-amplify/amplify-category-api.git (@aws-amplify/graphql-directives), https://github.com/aws-amplify/amplify-category-api.git (@aws-amplify/graphql-schema-test-library), https://github.com/aws-amplify/amplify-category-api.git (@aws-amplify/graphql-transformer-interfaces), https://github.com/aws-amplify/amplify-category-api.git (graphql-mapping-template), https://github.com/aws-amplify/amplify-category-api.git (graphql-transformer-common), https://github.com/aws-amplify/amplify-category-api.git (graphql-transformer-core). This software contains the following license and notice below:

Apache License
Version 2.0, January 2004
Expand Down
14 changes: 14 additions & 0 deletions packages/amplify-codegen-e2e-core/src/utils/sdk-calls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
AmplifyBackend,
} from 'aws-sdk';
import _ from 'lodash';
import { getProjectMeta } from './projectMeta';

export const getDDBTable = async (tableName: string, region: string) => {
const service = new DynamoDB({ region });
Expand Down Expand Up @@ -42,6 +43,19 @@ export const bucketNotExists = async (bucket: string) => {
}
};

export const getDeploymentBucketObject = async (projectRoot: string, objectKey: string) => {
const meta = getProjectMeta(projectRoot);
const deploymentBucket = meta.providers.awscloudformation.DeploymentBucketName;
const s3 = new S3();
const result = await s3
.getObject({
Bucket: deploymentBucket,
Key: objectKey,
})
.promise();
return result.Body.toLocaleString();
};

export const deleteS3Bucket = async (bucket: string, providedS3Client: S3 | undefined = undefined) => {
const s3 = providedS3Client ? providedS3Client : new S3();
let continuationToken: Required<Pick<S3.ListObjectVersionsOutput, 'KeyMarker' | 'VersionIdMarker'>> = undefined;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
input AMPLIFY { globalAuthRule: AuthRule = { allow: public } } # FOR TESTING ONLY!

type Todo @model {
id: ID!
name: String!
description: String
phone: Phone
}
type Phone {
number: String
}
enum BillingSource {
CLIENT
PROJECT
}
input CustomInput {
customField1: String!
customField2: BillingSource
customField3: NestedInput!
}
input NestedInput {
content: String! = "hello"
}
interface ICustom {
firstName: String!
lastName: String
birthdays: [INestedCustom!]!
}
interface INestedCustom {
birthDay: AWSDate!
}
# The member types of a Union type must all be Object base types.
union CustomUnion = Todo | Phone

type Query {
getAllTodo(msg: String, input: CustomInput): String @function(name: "echofunction-${env}")
echo(msg: String!): String
echo2(todoId: ID!): Todo
echo3: [Todo!]!
echo4(number: String): Phone
echo5: [CustomUnion!]!
echo6(customInput: CustomInput): String!
echo7: [ICustom]!
echo8(msg: [Float], msg2: [Int!], enumType: BillingSource, enumList: [BillingSource], inputType: [CustomInput]): [String]
echo9(msg: [Float]!, msg2: [Int!]!, enumType: BillingSource!, enumList: [BillingSource!]!, inputType: [CustomInput!]!): [String!]!

}
type Mutation {
mutate(msg: [String!]!): Todo
}
type Subscription {
onMutate(msg: String): [Todo!]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { DEFAULT_JS_CONFIG, createNewProjectDir } from "@aws-amplify/amplify-codegen-e2e-core";
import { deleteAmplifyProject, testPushAdminModelgen, testPushCodegen } from "../codegen-tests-base";

const schema = 'admin-modelgen.graphql';

describe('Amplify push with codegen tests - admin modelgen', () => {
let projectRoot: string;
beforeEach(async () => {
projectRoot = await createNewProjectDir('pushCodegenAdminModelgen');
});

afterEach(async () => {
await deleteAmplifyProject(projectRoot);
});

it(`should not throw error for executing the admin modelgen step required by studio CMS usage post push given the schema with input, union and interface types`, async () => {
await testPushAdminModelgen(DEFAULT_JS_CONFIG, projectRoot, schema);
});
});
57 changes: 48 additions & 9 deletions packages/amplify-codegen-e2e-tests/src/cleanup-e2e-resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type AmplifyAppInfo = {

type S3BucketInfo = {
name: string;
region: string;
jobId?: string;
cbInfo?: CodeBuild.Build;
};
Expand Down Expand Up @@ -118,7 +119,16 @@ const getOrphanS3TestBuckets = async (account: AWSAccountInfo): Promise<S3Bucket
const s3Client = new aws.S3(getAWSConfig(account));
const listBucketResponse = await s3Client.listBuckets().promise();
const staleBuckets = listBucketResponse.Buckets.filter(testBucketStalenessFilter);
return staleBuckets.map(it => ({ name: it.Name }));
const bucketInfos = await Promise.all(
staleBuckets.map(async (staleBucket): Promise<S3BucketInfo> => {
const region = await getBucketRegion(account, staleBucket.Name);
return {
name: staleBucket.Name,
region,
};
}),
);
return bucketInfos;
};

/**
Expand Down Expand Up @@ -276,27 +286,52 @@ const getJobCodeBuildDetails = async (jobIds: string[]): Promise<CodeBuild.Build
}
};

const getBucketRegion = async (account: AWSAccountInfo, bucketName: string): Promise<string> => {
const awsConfig = getAWSConfig(account);
const s3Client = new aws.S3(awsConfig);
const location = await s3Client.getBucketLocation({ Bucket: bucketName }).promise();
const region = location.LocationConstraint ?? 'us-east-1';
return region;
};

const getS3Buckets = async (account: AWSAccountInfo): Promise<S3BucketInfo[]> => {
const s3Client = new aws.S3(getAWSConfig(account));
const awsConfig = getAWSConfig(account);
const s3Client = new aws.S3(awsConfig);
const buckets = await s3Client.listBuckets().promise();
const result: S3BucketInfo[] = [];
for (const bucket of buckets.Buckets) {
let region: string | undefined;
try {
const bucketDetails = await s3Client.getBucketTagging({ Bucket: bucket.Name }).promise();
region = await getBucketRegion(account, bucket.Name);
// Operations on buckets created in opt-in regions appear to require region-specific clients
const regionalizedClient = new aws.S3({
region,
...(awsConfig as object),
});
const bucketDetails = await regionalizedClient.getBucketTagging({ Bucket: bucket.Name }).promise();
const jobId = getJobId(bucketDetails.TagSet);
if (jobId) {
result.push({
name: bucket.Name,
region,
jobId
});
}
} catch (e) {
if (e.code !== 'NoSuchTagSet' && e.code !== 'NoSuchBucket') {
// TODO: Why do we process the bucket even with these particular errors?
if (e.code === 'NoSuchTagSet' || e.code === 'NoSuchBucket') {
result.push({
name: bucket.Name,
region: region ?? 'us-east-1',
});
} else if (e.code === 'InvalidToken') {
// We see some buckets in some accounts that were somehow created in an opt-in region different from the one to which the account is
// actually opted in. We don't quite know how this happened, but for now, we'll make a note of the inconsistency and continue
// processing the rest of the buckets.
console.error(`Skipping processing ${account.accountId}, bucket ${bucket.Name}`, e);
} else {
throw e;
}
result.push({
name: bucket.Name,
});
}
}
return result;
Expand Down Expand Up @@ -516,8 +551,12 @@ const deleteBucket = async (account: AWSAccountInfo, accountIndex: number, bucke
const { name } = bucket;
try {
console.log(`${generateAccountInfo(account, accountIndex)} Deleting S3 Bucket ${name}`);
const s3 = new aws.S3(getAWSConfig(account));
await deleteS3Bucket(name, s3);
const awsConfig = getAWSConfig(account);
const regionalizedS3Client = new aws.S3({
region: bucket.region,
...(awsConfig as object),
});
await deleteS3Bucket(name, regionalizedS3Client);
} catch (e) {
console.log(`${generateAccountInfo(account, accountIndex)} Deleting bucket ${name} failed with error ${e.message}`);
if (e.code === 'ExpiredTokenException') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import {
amplifyPushWithCodegenAdd,
AmplifyFrontendConfig,
amplifyPushWithCodegenUpdate,
updateAPIWithResolutionStrategyWithModels
updateAPIWithResolutionStrategyWithModels,
getProjectMeta,
getDeploymentBucketObject,
amplifyPush
} from "@aws-amplify/amplify-codegen-e2e-core";
import { existsSync } from "fs";
import path from 'path';
Expand Down Expand Up @@ -38,3 +41,38 @@ export async function testPushCodegen(config: AmplifyFrontendConfig, projectRoot
expect(existsSync(userSourceCodePath)).toBe(true);
expect(isNotEmptyDir(path.join(projectRoot, config.modelgenDir))).toBe(true);
}

export async function testPushAdminModelgen(config: AmplifyFrontendConfig, projectRoot: string, schema: string) {
// init project and add API category
await initProjectWithProfile(projectRoot, { ...config, disableAmplifyAppCreation: false, });
const {
DeploymentBucketName: bucketName,
Region: region,
AmplifyAppId: appId,
} = getProjectMeta(projectRoot).providers.awscloudformation;

expect(bucketName).toBeDefined()
expect(region).toBeDefined();
expect(appId).toBeDefined();

const projectName = createRandomName();
await addApiWithoutSchema(projectRoot, { apiName: projectName });
await updateApiSchema(projectRoot, projectName, schema);
// add codegen succeeds
await amplifyPush(projectRoot);

/**
* Source code from
* https://github.com/aws-amplify/amplify-cli/blob/1da5de70c57b15a76f02c92364af4889d1585229/packages/amplify-provider-awscloudformation/src/admin-modelgen.ts#L85-L93
*/
const s3ApiModelsPrefix = `models/${projectName}/`;
const cmsArtifactLocalToS3Keys = [
`${s3ApiModelsPrefix}schema.graphql`,
`${s3ApiModelsPrefix}schema.js`,
`${s3ApiModelsPrefix}modelIntrospection.json`,
];
// expect CMS assets to be present in S3
cmsArtifactLocalToS3Keys.forEach(async (key) => {
await expect(getDeploymentBucketObject(projectRoot, key)).resolves.not.toThrow();
});
}
1 change: 1 addition & 0 deletions packages/amplify-codegen/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"extract-api": "ts-node ../../scripts/extract-api.ts"
},
"dependencies": {
"@aws-amplify/graphql-directives": "^1.0.1",
"@aws-amplify/graphql-docs-generator": "4.2.1",
"@aws-amplify/graphql-generator": "0.2.4",
"@aws-amplify/graphql-types-generator": "3.4.6",
Expand Down
2 changes: 2 additions & 0 deletions packages/amplify-codegen/src/commands/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ async function add(context, apiId = null, region = 'us-east-1') {
apiId,
...(withoutInit ? { frontend } : {}),
...(withoutInit && frontend === 'javascript' ? { framework } : {}),
// The default Amplify JS lib version is set for 6 for angular codegen
...(answer.target === 'angular' ? { amplifyJsLibraryVersion: 6 } : {}),
},
};

Expand Down
4 changes: 2 additions & 2 deletions packages/amplify-codegen/src/commands/models.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ const fs = require('fs-extra');
const globby = require('globby');
const { FeatureFlags, pathManager } = require('@aws-amplify/amplify-cli-core');
const { generateModels: generateModelsHelper } = require('@aws-amplify/graphql-generator');
const { DefaultDirectives } = require('@aws-amplify/graphql-directives');
const { validateAmplifyFlutterMinSupportedVersion } = require('../utils/validateAmplifyFlutterMinSupportedVersion');
const defaultDirectiveDefinitions = require('../utils/defaultDirectiveDefinitions');
const getProjectRoot = require('../utils/getProjectRoot');
const { getModelSchemaPathParam, hasModelSchemaPathParam } = require('../utils/getModelSchemaPathParam');
const { isDataStoreEnabled } = require('graphql-transformer-core');
Expand Down Expand Up @@ -131,7 +131,7 @@ const getDirectives = async (context, apiResourcePath) => {
resourceDir: apiResourcePath,
});
} catch {
return defaultDirectiveDefinitions;
return DefaultDirectives.map(directive => directive.definition).join('\n');
}
};

Expand Down
Loading
Loading