diff --git a/.github/scripts/mega-app-copy-files.sh b/.github/scripts/mega-app-copy-files.sh new file mode 100755 index 00000000000..6c2935a9c79 --- /dev/null +++ b/.github/scripts/mega-app-copy-files.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +echo "cd build-system-tests" +cd build-system-tests +if [ "$BUILD_TOOL" == 'cra' ]; then + echo "cp templates/template-aws-exports.js mega-apps/${MEGA_APP_NAME}/src/aws-exports.js" + cp templates/template-aws-exports.js mega-apps/${MEGA_APP_NAME}/src/aws-exports.js + if [ "$LANGUAGE" == 'js' ]; then + echo "cp templates/components/react/cra/App.js mega-apps/${MEGA_APP_NAME}/src/App.js" + cp templates/components/react/cra/App.js mega-apps/${MEGA_APP_NAME}/src/App.js + else + echo "cp templates/components/react/cra/App.js mega-apps/${MEGA_APP_NAME}/src/App.tsx" + cp templates/components/react/cra/App.js mega-apps/${MEGA_APP_NAME}/src/App.tsx + if [ "$FRAMEWORK_VERSION" == '16' ]; then + # We have to customize the index.tsx file for React 16 because the render API changed since React 18. + # See more: https://legacy.reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html + echo "cp templates/components/react/cra/index-react-${FRAMEWORK_VERSION}.js mega-apps/${MEGA_APP_NAME}/src/index.tsx" + cp templates/components/react/cra/index-react-${FRAMEWORK_VERSION}.js mega-apps/${MEGA_APP_NAME}/src/index.tsx + fi + fi +fi + +if [ "$BUILD_TOOL" == 'next' ]; then + echo "mkdir mega-apps/${MEGA_APP_NAME}/data" + mkdir mega-apps/${MEGA_APP_NAME}/data + echo "cp templates/template-aws-exports.js mega-apps/${MEGA_APP_NAME}/data/aws-exports.js" + cp templates/template-aws-exports.js mega-apps/${MEGA_APP_NAME}/data/aws-exports.js + echo "cp templates/components/react/next/App.js mega-apps/${MEGA_APP_NAME}/pages/index.tsx" + cp templates/components/react/next/App.js mega-apps/${MEGA_APP_NAME}/pages/index.tsx + if [ "$BUILD_TOOL_VERSION" == '11' ]; then + # We have to customize the package.json and tsconfig.json for Next.js 11, + # because create-next-app only creates the app with the latest version + echo "cp templates/components/react/next/template-package-${BUILD_TOOL_VERSION}.json mega-apps/${MEGA_APP_NAME}/package.json" + cp templates/components/react/next/template-package-${BUILD_TOOL_VERSION}.json mega-apps/${MEGA_APP_NAME}/package.json + echo "cp templates/components/react/next/template-tsconfig-${BUILD_TOOL_VERSION}.json mega-apps/${MEGA_APP_NAME}/tsconfig.json" + cp templates/components/react/next/template-tsconfig-${BUILD_TOOL_VERSION}.json mega-apps/${MEGA_APP_NAME}/tsconfig.json + fi +fi + +if [ "$BUILD_TOOL" == 'vite' ]; then + echo "cp templates/template-aws-exports.js mega-apps/${MEGA_APP_NAME}/src/aws-exports.js" + cp templates/template-aws-exports.js mega-apps/${MEGA_APP_NAME}/src/aws-exports.js + echo "cp templates/components/react/cra/App.js mega-apps/${MEGA_APP_NAME}/src/App.tsx" + cp templates/components/react/cra/App.js mega-apps/${MEGA_APP_NAME}/src/App.tsx + echo "cp templates/components/react/vite/index.html mega-apps/${MEGA_APP_NAME}/index.html" + cp templates/components/react/vite/index.html mega-apps/${MEGA_APP_NAME}/index.html + echo "cp templates/components/react/vite/template-tsconfig.json mega-apps/${MEGA_APP_NAME}/tsconfig.json" + cp templates/components/react/vite/template-tsconfig.json mega-apps/${MEGA_APP_NAME}/tsconfig.json + echo "cp templates/components/react/vite/vite.config.ts mega-apps/${MEGA_APP_NAME}/vite.config.ts" + cp templates/components/react/vite/vite.config.ts mega-apps/${MEGA_APP_NAME}/vite.config.ts +fi diff --git a/.github/scripts/mega-app-create-app.sh b/.github/scripts/mega-app-create-app.sh new file mode 100755 index 00000000000..12bc9b9108c --- /dev/null +++ b/.github/scripts/mega-app-create-app.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +echo "cd build-system-tests" +cd build-system-tests +echo "mkdir -p mega-apps/" +mkdir -p mega-apps/ +echo "cd mega-apps" +cd mega-apps + +if [[ "$BUILD_TOOL" == 'cra' && "$LANGUAGE" == 'js' ]]; then + echo "npx create-react-app ${MEGA_APP_NAME}" + npx create-react-app ${MEGA_APP_NAME} +fi + +if [[ "$BUILD_TOOL" == 'cra' && "$LANGUAGE" == 'ts' ]]; then + echo "npx create-react-app ${MEGA_APP_NAME} --template typescript" + npx create-react-app ${MEGA_APP_NAME} --template typescript +fi + +if [ "$BUILD_TOOL" == 'next' ]; then + echo "npx create-next-app ${MEGA_APP_NAME} --ts --no-src-dir --no-experimental-app --no-eslint" + npx create-next-app ${MEGA_APP_NAME} --ts --no-src-dir --no-experimental-app --no-eslint +fi + +if [ "$BUILD_TOOL" == 'vite' ]; then + echo "npm create vite@${BUILD_TOOL_VERSION} $MEGA_APP_NAME -- --template react-ts" + npm create vite@${BUILD_TOOL_VERSION} $MEGA_APP_NAME -- --template react-ts +fi diff --git a/.github/scripts/mega-app-install-build.sh b/.github/scripts/mega-app-install-build.sh new file mode 100755 index 00000000000..88346dccbc2 --- /dev/null +++ b/.github/scripts/mega-app-install-build.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +echo "cd build-system-tests/mega-apps/${MEGA_APP_NAME}" +cd build-system-tests/mega-apps/${MEGA_APP_NAME} +if [ "$PKG_MANAGER" == 'yarn' ]; then + echo "yarn version" + yarn -v + echo "yarn set version $PKG_MANAGER_VERSION" + yarn set version $PKG_MANAGER_VERSION + echo "yarn version" + yarn -v + if [[ "$BUILD_TOOL" == 'cra' && "$LANGUAGE" == 'ts' ]]; then + echo "yarn add $DEP_TYPES" + yarn add $DEP_TYPES + fi + echo "yarn add $DEPENDENCIES" + yarn add $DEPENDENCIES + echo "yarn build" + yarn build +else + if [[ "$BUILD_TOOL" == 'cra' && "$LANGUAGE" == 'ts' ]]; then + # If not testing the latest React, we need to download its types. + # CRA is the only framework that we test React 16. + echo "npm install $DEP_TYPES" + npm install $DEP_TYPES + fi + if [[ "$BUILD_TOOL" == 'next' && "$BUILD_TOOL_VERSION" == '11' ]]; then + # We have to remove the initial downloaded node_modules for Next.js 11, + # because create-next-app only creates the app with the latest version + echo "rm -rf node_modules" + rm -rf node_modules + fi + echo "npm install $DEPENDENCIES" + npm install $DEPENDENCIES + echo "npm run build" + npm run build +fi diff --git a/.github/workflows/build-system-test.yml b/.github/workflows/build-system-test.yml new file mode 100644 index 00000000000..d1df8a2856c --- /dev/null +++ b/.github/workflows/build-system-test.yml @@ -0,0 +1,145 @@ +# Description: this workflow runs build mega-apps that have all the connected components. + +name: Build System Test Canary + +on: + schedule: + - cron: '*/15 * * * *' # Run every 15 minutes + push: + branches: [main] # Run when merge to main + +jobs: + build: + runs-on: ubuntu-latest + environment: ci + strategy: + fail-fast: false + matrix: + framework: [react] + framework-version: [latest] + build-tool: [cra, next, vite] + build-tool-version: [latest] + pkg-manager: [npm] + language: [ts] + node-version: [18] + include: + - framework: react + framework-version: latest + build-tool: cra + build-tool-version: latest + pkg-manager: npm + language: ts + node-version: 16 + - framework: react + framework-version: 16 + build-tool: cra + build-tool-version: latest + pkg-manager: npm + language: ts + node-version: 18 + - framework: react + framework-version: latest + build-tool: cra + build-tool-version: latest + pkg-manager: npm + language: js + node-version: 18 + - framework: react + framework-version: latest + build-tool: cra + build-tool-version: latest + pkg-manager: yarn + pkg-manager-version: 1 + language: ts + node-version: 18 + - framework: react + framework-version: 17 + build-tool: next + build-tool-version: 11 + pkg-manager: npm + language: ts + node-version: 16 + - framework: react + framework-version: latest + build-tool: vite + build-tool-version: 2 + pkg-manager: npm + language: ts + node-version: 18 + + env: + MEGA_APP_NAME: ${{ matrix.framework }}-${{ matrix.framework-version }}-${{ matrix.build-tool }}-${{ matrix.build-tool-version }}-node-${{ matrix.node-version }}-${{ matrix.language }} + DEPENDENCIES: react@${{ matrix.framework-version }} react-dom@${{ matrix.framework-version }} @aws-amplify/ui-react aws-amplify @aws-amplify/ui-react-storage + DEP_TYPES: '@types/react@${{ matrix.framework-version }} @types/react-dom@${{ matrix.framework-version }}' + + steps: + - name: Checkout Amplify UI + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 https://github.com/actions/checkout/commit/24cb9080177205b6e8c946b17badbe402adc938f + with: + persist-credentials: false + - name: Setup Node.js ${{ matrix.node-version }} with ${{ matrix.pkg-manager }} + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 https://github.com/actions/setup-node/commit/64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c + with: + node-version: ${{ matrix.node-version }} + cache: ${{ matrix.pkg-manager }} + env: + SEGMENT_DOWNLOAD_TIMEOUT_MINS: 2 + - name: Create MegaApp ${{ env.MEGA_APP_NAME }} + run: ./.github/scripts/mega-app-create-app.sh + shell: bash + env: + BUILD_TOOL: ${{ matrix.build-tool }} + LANGUAGE: ${{ matrix.language }} + MEGA_APP_NAME: ${{ env.MEGA_APP_NAME }} + BUILD_TOOL_VERSION: ${{ matrix.build-tool-version }} + - name: Copy aws_export and App.js + run: ./.github/scripts/mega-app-copy-files.sh + shell: bash + env: + BUILD_TOOL: ${{ matrix.build-tool }} + LANGUAGE: ${{ matrix.language }} + MEGA_APP_NAME: ${{ env.MEGA_APP_NAME }} + BUILD_TOOL_VERSION: ${{ matrix.build-tool-version }} + FRAMEWORK_VERSION: ${{ matrix.framework-version }} + - name: Install Packages and Build + run: ./.github/scripts/mega-app-install-build.sh + shell: bash + env: + BUILD_TOOL: ${{ matrix.build-tool }} + BUILD_TOOL_VERSION: ${{ matrix.build-tool-version }} + LANGUAGE: ${{ matrix.language }} + MEGA_APP_NAME: ${{ env.MEGA_APP_NAME }} + PKG_MANAGER: ${{ matrix.pkg-manager }} + PKG_MANAGER_VERSION: ${{ matrix.pkg-manager-version }} + DEPENDENCIES: ${{ env.DEPENDENCIES }} + DEP_TYPES: ${{ env.DEP_TYPES }} + + log-failure-metric: + # Send a failure data point to metric BuildSystemTestFailure in github-workflows@ us-east-2 + runs-on: ubuntu-latest + environment: ci + needs: build + if: ${{ failure() }} + steps: + - name: Log failure data point to metric BuildSystemTestFailure + uses: aws-amplify/amplify-ui/.github/actions/log-metric@main + with: + metric-name: BuildSystemTestFailure + value: 1 + role-to-assume: ${{ secrets.METRIC_LOGGER_ROLE_ARN }} + aws-region: us-east-2 + + log-success-metric: + # Send a success data point to metric BuildSystemTestFailure in github-workflows@ us-east-2 + runs-on: ubuntu-latest + environment: ci + needs: build + if: ${{ success() }} + steps: + - name: Log success data point to metric BuildSystemTestFailure + uses: aws-amplify/amplify-ui/.github/actions/log-metric@main + with: + metric-name: BuildSystemTestFailure + value: 0 + role-to-assume: ${{ secrets.METRIC_LOGGER_ROLE_ARN }} + aws-region: us-east-2 diff --git a/.vscode/settings.json b/.vscode/settings.json index aee31c24ce0..6e7cacd124a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,5 +8,8 @@ "typescript.tsdk": "node_modules/typescript/lib", "[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[shellscript]": { + "editor.defaultFormatter": "foxundermoon.shell-format" } } diff --git a/build-system-tests/.gitignore b/build-system-tests/.gitignore new file mode 100644 index 00000000000..94b5eb6cedb --- /dev/null +++ b/build-system-tests/.gitignore @@ -0,0 +1 @@ +mega-apps diff --git a/build-system-tests/templates/components/react/cra/App.js b/build-system-tests/templates/components/react/cra/App.js new file mode 100644 index 00000000000..df8ef034422 --- /dev/null +++ b/build-system-tests/templates/components/react/cra/App.js @@ -0,0 +1,51 @@ +import React, { useEffect } from 'react'; +import { Amplify, Notifications } from 'aws-amplify'; +import { + AccountSettings, + Authenticator, + FileUploader, + MapView, + Text, + InAppMessagingProvider, + InAppMessageDisplay, +} from '@aws-amplify/ui-react'; +import { StorageManager } from '@aws-amplify/ui-react-storage'; +import '@aws-amplify/ui-react/styles.css'; +import awsconfig from './aws-exports'; +Amplify.configure(awsconfig); + +const { InAppMessaging } = Notifications; + +export default function Home() { + useEffect(() => { + // sync remote in-app messages + InAppMessaging.syncMessages(); + }, []); + + return ( + <> + + + In-App Messaging Example + + + + {({ signOut, user = { username: '' } }) => ( +
+

Hello {user.username}

+ +
+ )} +
+ {}} /> + {}} /> + + + + ); +} diff --git a/build-system-tests/templates/components/react/cra/index-react-16.js b/build-system-tests/templates/components/react/cra/index-react-16.js new file mode 100644 index 00000000000..c1f31c5f49d --- /dev/null +++ b/build-system-tests/templates/components/react/cra/index-react-16.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; + +ReactDOM.render( + + + , + document.getElementById('root') +); diff --git a/build-system-tests/templates/components/react/cra/index-react-18.js b/build-system-tests/templates/components/react/cra/index-react-18.js new file mode 100644 index 00000000000..593edf12164 --- /dev/null +++ b/build-system-tests/templates/components/react/cra/index-react-18.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; + +const root = ReactDOM.createRoot(document.getElementById('root')); +root.render( + + + +); diff --git a/build-system-tests/templates/components/react/cra/index-react-18.tsx b/build-system-tests/templates/components/react/cra/index-react-18.tsx new file mode 100644 index 00000000000..32a75194c0c --- /dev/null +++ b/build-system-tests/templates/components/react/cra/index-react-18.tsx @@ -0,0 +1,13 @@ +// @ts-nocheck +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; + +const root = ReactDOM.createRoot( + document.getElementById('root') as HTMLElement +); +root.render( + + + +); diff --git a/build-system-tests/templates/components/react/next/App.js b/build-system-tests/templates/components/react/next/App.js new file mode 100644 index 00000000000..272fa5d04ae --- /dev/null +++ b/build-system-tests/templates/components/react/next/App.js @@ -0,0 +1,51 @@ +import React, { useEffect } from 'react'; +import { Amplify, Notifications } from 'aws-amplify'; +import { + AccountSettings, + Authenticator, + FileUploader, + MapView, + Text, + InAppMessagingProvider, + InAppMessageDisplay, +} from '@aws-amplify/ui-react'; +import { StorageManager } from '@aws-amplify/ui-react-storage'; +import '@aws-amplify/ui-react/styles.css'; +import awsconfig from '@/data/aws-exports'; +Amplify.configure(awsconfig); + +const { InAppMessaging } = Notifications; + +export default function Home() { + useEffect(() => { + // sync remote in-app messages + InAppMessaging.syncMessages(); + }, []); + + return ( + <> + + + In-App Messaging Example + + + + {({ signOut, user = { username: '' } }) => ( +
+

Hello {user.username}

+ +
+ )} +
+ {}} /> + {}} /> + + + + ); +} diff --git a/build-system-tests/templates/components/react/next/template-package-11.json b/build-system-tests/templates/components/react/next/template-package-11.json new file mode 100644 index 00000000000..ce9df3adc11 --- /dev/null +++ b/build-system-tests/templates/components/react/next/template-package-11.json @@ -0,0 +1,20 @@ +{ + "name": "react-17-next-11-ts", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@types/node": "^15.12.4", + "@types/react": "17.0.47", + "@types/react-dom": "17", + "next": "^11.1.3", + "react": "17", + "react-dom": "17", + "typescript": "5.0.3" + } +} diff --git a/build-system-tests/templates/components/react/next/template-tsconfig-11.json b/build-system-tests/templates/components/react/next/template-tsconfig-11.json new file mode 100644 index 00000000000..6dbcf30832a --- /dev/null +++ b/build-system-tests/templates/components/react/next/template-tsconfig-11.json @@ -0,0 +1,35 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": false, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "baseUrl": "./", + "paths": { + "@/*": [ + "./*" + ] + } + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/build-system-tests/templates/components/react/vite/index.html b/build-system-tests/templates/components/react/vite/index.html new file mode 100644 index 00000000000..36ca904f975 --- /dev/null +++ b/build-system-tests/templates/components/react/vite/index.html @@ -0,0 +1,23 @@ + + + + + + + + Vite + React + TS + + + +
+ + + + + diff --git a/build-system-tests/templates/components/react/vite/template-tsconfig.json b/build-system-tests/templates/components/react/vite/template-tsconfig.json new file mode 100644 index 00000000000..426108b55c0 --- /dev/null +++ b/build-system-tests/templates/components/react/vite/template-tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "lib": [ + "DOM", + "DOM.Iterable", + "ESNext" + ], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": [ + "src" + ], + "references": [ + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/build-system-tests/templates/components/react/vite/vite.config.ts b/build-system-tests/templates/components/react/vite/vite.config.ts new file mode 100644 index 00000000000..4f78ad9d0a8 --- /dev/null +++ b/build-system-tests/templates/components/react/vite/vite.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from 'vite'; +// @ts-ignore +import react from '@vitejs/plugin-react'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + resolve: { + alias: [ + { + find: './runtimeConfig', + replacement: './runtimeConfig.browser', + }, + ], + }, +}); diff --git a/build-system-tests/templates/template-aws-exports.js b/build-system-tests/templates/template-aws-exports.js new file mode 100644 index 00000000000..da9a8be835e --- /dev/null +++ b/build-system-tests/templates/template-aws-exports.js @@ -0,0 +1,3 @@ +const awsmobile = {}; + +export default awsmobile;