From 833a0cbcf21fdbe73dcc11ed4bbd4f075b7807c2 Mon Sep 17 00:00:00 2001 From: Jay2113 Date: Mon, 14 Apr 2025 11:43:43 -0400 Subject: [PATCH 1/2] fix(aws-amplify-alpha): clarify GitHub repository configuration to address #25658 --- packages/@aws-cdk/aws-amplify-alpha/README.md | 22 +++---- .../@aws-cdk/aws-amplify-alpha/lib/app.ts | 29 +++++++--- .../lib/source-code-providers.ts | 21 ++++++- .../aws-amplify-alpha/test/app.test.ts | 57 ++++++++++++++++++- 4 files changed, 106 insertions(+), 23 deletions(-) diff --git a/packages/@aws-cdk/aws-amplify-alpha/README.md b/packages/@aws-cdk/aws-amplify-alpha/README.md index fb062ae9a56f6..d9d646157311e 100644 --- a/packages/@aws-cdk/aws-amplify-alpha/README.md +++ b/packages/@aws-cdk/aws-amplify-alpha/README.md @@ -26,9 +26,9 @@ import * as codebuild from 'aws-cdk-lib/aws-codebuild'; const amplifyApp = new amplify.App(this, 'MyApp', { sourceCodeProvider: new amplify.GitHubSourceCodeProvider({ - owner: '', - repository: '', - oauthToken: SecretValue.secretsManager('my-github-token'), + owner: '', + repository: '', + accessToken: SecretValue.secretsManager('my-github-token'), }), buildSpec: codebuild.BuildSpec.fromObjectToYaml({ // Alternatively add a `amplify.yml` to the repo @@ -61,8 +61,8 @@ To connect your `App` to GitLab, use the `GitLabSourceCodeProvider`: ```ts const amplifyApp = new amplify.App(this, 'MyApp', { sourceCodeProvider: new amplify.GitLabSourceCodeProvider({ - owner: '', - repository: '', + owner: '', + repository: '', oauthToken: SecretValue.secretsManager('my-gitlab-token'), }), }); @@ -158,9 +158,9 @@ Use `BasicAuth.fromCredentials` when referencing an existing secret: ```ts const amplifyApp = new amplify.App(this, 'MyApp', { sourceCodeProvider: new amplify.GitHubSourceCodeProvider({ - owner: '', - repository: '', - oauthToken: SecretValue.secretsManager('my-github-token'), + owner: '', + repository: '', // Just the repository name, NOT the full URL + accessToken: SecretValue.secretsManager('my-github-token'), }), basicAuth: amplify.BasicAuth.fromCredentials('username', SecretValue.secretsManager('my-github-token')), }); @@ -196,9 +196,9 @@ of branches: ```ts const amplifyApp = new amplify.App(this, 'MyApp', { sourceCodeProvider: new amplify.GitHubSourceCodeProvider({ - owner: '', - repository: '', - oauthToken: SecretValue.secretsManager('my-github-token'), + owner: '', + repository: '', // Just the repository name, NOT the full URL + accessToken: SecretValue.secretsManager('my-github-token'), }), autoBranchCreation: { // Automatically connect branches that match a pattern set patterns: ['feature/*', 'test/*'], diff --git a/packages/@aws-cdk/aws-amplify-alpha/lib/app.ts b/packages/@aws-cdk/aws-amplify-alpha/lib/app.ts index 7c3854394c94c..81628f4ab7bab 100644 --- a/packages/@aws-cdk/aws-amplify-alpha/lib/app.ts +++ b/packages/@aws-cdk/aws-amplify-alpha/lib/app.ts @@ -26,9 +26,11 @@ export interface IApp extends IResource { */ export interface SourceCodeProviderConfig { /** - * The repository for the application. Must use the `HTTPS` protocol. + * The full HTTPS URL for the repository for the application. * - * For example, `https://github.com/aws/aws-cdk`. + * For GitHub: `https://github.com/owner/repository` + * For GitLab: `https://gitlab.com/owner/repository` + * For CodeCommit: The HTTPS clone URL */ readonly repository: string; @@ -36,19 +38,30 @@ export interface SourceCodeProviderConfig { * OAuth token for 3rd party source control system for an Amplify App, used * to create webhook and read-only deploy key. OAuth token is not stored. * - * Either `accessToken` or `oauthToken` must be specified if `repository` - * is specified. + * For GitHub repositories, use `accessToken` instead. OAuth tokens for GitHub repositories + * are supported for backward compatibility but we strongly recommend using `accessToken` + * with the Amplify GitHub App. + * + * For other repository providers like Bitbucket or CodeCommit, use `oauthToken`. + * + * Either `accessToken` (GitHub) or `oauthToken` (other providers) must be specified + * when connecting to a source code repository. * * @default - do not use a token + * @deprecated For GitHub repositories, use accessToken instead */ readonly oauthToken?: SecretValue; /** - * Personal Access token for 3rd party source control system for an Amplify - * App, used to create webhook and read-only deploy key. Token is not stored. + * Personal Access token for GitHub repository for an Amplify + * App, used to authorize access to a GitHub repository using the Amplify GitHub App. + * Token is not stored. + * + * This is the recommended way to authorize access to GitHub repositories. + * For non-GitHub repositories (GitLab, Bitbucket, CodeCommit), use `oauthToken`. * - * Either `accessToken` or `oauthToken` must be specified if `repository` - * is sepcified. + * Either `accessToken` (GitHub) or `oauthToken` (other providers) must be specified + * when connecting to a source code repository. * * @default - do not use a token */ diff --git a/packages/@aws-cdk/aws-amplify-alpha/lib/source-code-providers.ts b/packages/@aws-cdk/aws-amplify-alpha/lib/source-code-providers.ts index 640417c52404a..9eb8ed7008bd1 100644 --- a/packages/@aws-cdk/aws-amplify-alpha/lib/source-code-providers.ts +++ b/packages/@aws-cdk/aws-amplify-alpha/lib/source-code-providers.ts @@ -17,9 +17,23 @@ export interface GitHubSourceCodeProviderProps { readonly repository: string; /** - * A personal access token with the `repo` scope + * Personal Access token for GitHub repository using the Amplify GitHub App. + * Required for new GitHub repositories. + * + * @default - no access token */ - readonly oauthToken: SecretValue; + readonly accessToken?: SecretValue; + + /** + * OAuth token for GitHub repository. + * @deprecated Use accessToken instead. OAuth tokens for GitHub repositories are supported + * for backwards compatibility but we strongly recommend using accessToken with the Amplify GitHub App. + * Existing Amplify apps deployed from a GitHub repository using OAuth continue to work with CI/CD. + * However, we strongly recommend that you migrate these apps to use the GitHub App + * https://docs.aws.amazon.com/amplify/latest/userguide/setting-up-GitHub-access.html#migrating-to-github-app-auth + * @default - no OAuth token + */ + readonly oauthToken?: SecretValue; } /** @@ -31,6 +45,7 @@ export class GitHubSourceCodeProvider implements ISourceCodeProvider { public bind(_app: App): SourceCodeProviderConfig { return { repository: `https://github.com/${this.props.owner}/${this.props.repository}`, + accessToken: this.props.accessToken, oauthToken: this.props.oauthToken, }; } @@ -51,7 +66,7 @@ export interface GitLabSourceCodeProviderProps { readonly repository: string; /** - * A personal access token with the `repo` scope + * OAuth token for GitLab repository with the `repo` scope */ readonly oauthToken: SecretValue; } diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/app.test.ts b/packages/@aws-cdk/aws-amplify-alpha/test/app.test.ts index 1e097547c8215..ae18e5c87babf 100644 --- a/packages/@aws-cdk/aws-amplify-alpha/test/app.test.ts +++ b/packages/@aws-cdk/aws-amplify-alpha/test/app.test.ts @@ -9,7 +9,62 @@ beforeEach(() => { stack = new Stack(); }); -test('create an app connected to a GitHub repository', () => { +test('create an app connected to a GitHub repository with access token', () => { + // WHEN + new amplify.App(stack, 'App', { + sourceCodeProvider: new amplify.GitHubSourceCodeProvider({ + owner: 'aws', + repository: 'aws-cdk', + oauthToken: SecretValue.unsafePlainText('secret'), + }), + buildSpec: codebuild.BuildSpec.fromObjectToYaml({ + version: '1.0', + frontend: { + phases: { + build: { + commands: [ + 'npm run build', + ], + }, + }, + }, + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Amplify::App', { + Name: 'App', + BuildSpec: 'version: \"1.0\"\nfrontend:\n phases:\n build:\n commands:\n - npm run build\n', + IAMServiceRole: { + 'Fn::GetAtt': [ + 'AppRole1AF9B530', + 'Arn', + ], + }, + OauthToken: 'secret', + Repository: 'https://github.com/aws/aws-cdk', + BasicAuthConfig: { + EnableBasicAuth: false, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'amplify.amazonaws.com', + }, + }, + ], + Version: '2012-10-17', + }, + }); +}); + +test('create an app connected to a GitHub repository with oauth token', () => { // WHEN new amplify.App(stack, 'App', { sourceCodeProvider: new amplify.GitHubSourceCodeProvider({ From 0b9e11bfe1e4964da6c21e26d26ed72c03b7a322 Mon Sep 17 00:00:00 2001 From: Jay2113 Date: Mon, 14 Apr 2025 21:11:39 -0400 Subject: [PATCH 2/2] update repo comment --- packages/@aws-cdk/aws-amplify-alpha/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/@aws-cdk/aws-amplify-alpha/README.md b/packages/@aws-cdk/aws-amplify-alpha/README.md index d9d646157311e..e166c2de4ed24 100644 --- a/packages/@aws-cdk/aws-amplify-alpha/README.md +++ b/packages/@aws-cdk/aws-amplify-alpha/README.md @@ -27,7 +27,7 @@ import * as codebuild from 'aws-cdk-lib/aws-codebuild'; const amplifyApp = new amplify.App(this, 'MyApp', { sourceCodeProvider: new amplify.GitHubSourceCodeProvider({ owner: '', - repository: '', + repository: '', // Just the repository name, NOT the full repository URL accessToken: SecretValue.secretsManager('my-github-token'), }), buildSpec: codebuild.BuildSpec.fromObjectToYaml({ @@ -62,7 +62,7 @@ To connect your `App` to GitLab, use the `GitLabSourceCodeProvider`: const amplifyApp = new amplify.App(this, 'MyApp', { sourceCodeProvider: new amplify.GitLabSourceCodeProvider({ owner: '', - repository: '', + repository: '', // Just the repository name, NOT the full repository URL oauthToken: SecretValue.secretsManager('my-gitlab-token'), }), }); @@ -159,7 +159,7 @@ Use `BasicAuth.fromCredentials` when referencing an existing secret: const amplifyApp = new amplify.App(this, 'MyApp', { sourceCodeProvider: new amplify.GitHubSourceCodeProvider({ owner: '', - repository: '', // Just the repository name, NOT the full URL + repository: '', // Just the repository name, NOT the full repository URL accessToken: SecretValue.secretsManager('my-github-token'), }), basicAuth: amplify.BasicAuth.fromCredentials('username', SecretValue.secretsManager('my-github-token')), @@ -171,8 +171,8 @@ Use `BasicAuth.fromGeneratedPassword` to generate a password in Secrets Manager: ```ts const amplifyApp = new amplify.App(this, 'MyApp', { sourceCodeProvider: new amplify.GitHubSourceCodeProvider({ - owner: '', - repository: '', + owner: '', + repository: '', // Just the repository name, NOT the full repository URL oauthToken: SecretValue.secretsManager('my-github-token'), }), basicAuth: amplify.BasicAuth.fromGeneratedPassword('username'), @@ -197,7 +197,7 @@ of branches: const amplifyApp = new amplify.App(this, 'MyApp', { sourceCodeProvider: new amplify.GitHubSourceCodeProvider({ owner: '', - repository: '', // Just the repository name, NOT the full URL + repository: '', // Just the repository name, NOT the full repository URL accessToken: SecretValue.secretsManager('my-github-token'), }), autoBranchCreation: { // Automatically connect branches that match a pattern set @@ -214,8 +214,8 @@ Use the `customResponseHeaders` prop to configure custom response headers for an ```ts const amplifyApp = new amplify.App(this, 'App', { sourceCodeProvider: new amplify.GitHubSourceCodeProvider({ - owner: '', - repository: '', + owner: '', + repository: '', // Just the repository name, NOT the full repository URL oauthToken: SecretValue.secretsManager('my-github-token'), }), customResponseHeaders: [