From d81c6ed09b45766d966fa33c3297ec1c28d5ca03 Mon Sep 17 00:00:00 2001 From: Terraform Date: Tue, 29 Jul 2025 17:03:02 -0700 Subject: [PATCH 1/8] Add production release CICD --- .github/workflows/aws_prod_release.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/aws_prod_release.yml b/.github/workflows/aws_prod_release.yml index 4b375da..43caaf6 100644 --- a/.github/workflows/aws_prod_release.yml +++ b/.github/workflows/aws_prod_release.yml @@ -66,8 +66,6 @@ jobs: - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v2 - with: - mask-password: 'false' - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 From 72e6f154cec99be3e2e735d189e4a2aa72b2ab64 Mon Sep 17 00:00:00 2001 From: Terraform Date: Tue, 29 Jul 2025 17:03:08 -0700 Subject: [PATCH 2/8] Add production release CICD --- .github/workflows/aws_dev_release.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/aws_dev_release.yml b/.github/workflows/aws_dev_release.yml index 9674563..46ddb74 100644 --- a/.github/workflows/aws_dev_release.yml +++ b/.github/workflows/aws_dev_release.yml @@ -62,8 +62,6 @@ jobs: - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v2 - with: - mask-password: 'false' - name: Image Metadata id: metadata From 213f378718bf27b362e6810a828f51f6b34b4b78 Mon Sep 17 00:00:00 2001 From: Terraform Date: Sat, 30 Aug 2025 23:06:59 -0700 Subject: [PATCH 3/8] Fix release workflow to trigger production deployment --- .github/workflows/aws_auto_release.yml | 152 +++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 .github/workflows/aws_auto_release.yml diff --git a/.github/workflows/aws_auto_release.yml b/.github/workflows/aws_auto_release.yml new file mode 100644 index 0000000..7fabd78 --- /dev/null +++ b/.github/workflows/aws_auto_release.yml @@ -0,0 +1,152 @@ +name: Auto Release on Main Merge +on: + pull_request: + types: [closed] + branches: + - main + +concurrency: + group: ${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: write + pull-requests: read + +jobs: + auto_release: + runs-on: ubuntu-latest + if: github.event.pull_request.merged == true + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: main + token: ${{ secrets.PAT }} + + - name: Check for release labels and determine version bumps + id: check + run: | + labels='${{ toJson(github.event.pull_request.labels.*.name) }}' + echo "PR Labels: $labels" + + has_release_label=false + has_major=false + has_minor=false + has_patch=false + + # Check if release label exists + if echo "$labels" | grep -q "release"; then + has_release_label=true + + # Check for each type of version bump + if echo "$labels" | grep -q "major"; then + has_major=true + fi + if echo "$labels" | grep -q "minor"; then + has_minor=true + fi + if echo "$labels" | grep -q "patch"; then + has_patch=true + fi + + # If no specific version type is specified, default to patch + if [[ "$has_major" == "false" && "$has_minor" == "false" && "$has_patch" == "false" ]]; then + has_patch=true + fi + fi + + echo "should_release=$has_release_label" >> $GITHUB_OUTPUT + echo "has_major=$has_major" >> $GITHUB_OUTPUT + echo "has_minor=$has_minor" >> $GITHUB_OUTPUT + echo "has_patch=$has_patch" >> $GITHUB_OUTPUT + echo "Should release: $has_release_label" + echo "Has major: $has_major, minor: $has_minor, patch: $has_patch" + + - name: Setup Node.js + if: steps.check.outputs.should_release == 'true' + uses: actions/setup-node@v4 + with: + node-version: 20.10 + + - name: Calculate new version with cumulative bumps + if: steps.check.outputs.should_release == 'true' + id: version + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + + # Get the latest tag from git + latest_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") + echo "Latest git tag: $latest_tag" + + # Remove 'v' prefix if present + current_version=${latest_tag#v} + echo "Current version: $current_version" + + # Parse current version + IFS='.' read -r major minor patch <<< "$current_version" + echo "Parsed version - Major: $major, Minor: $minor, Patch: $patch" + + # Apply cumulative version bumps + if [[ "${{ steps.check.outputs.has_major }}" == "true" ]]; then + major=$((major + 1)) + minor=0 # Reset minor when major is bumped + patch=0 # Reset patch when major is bumped + echo "Applied major bump: $major.0.0" + fi + + if [[ "${{ steps.check.outputs.has_minor }}" == "true" ]]; then + minor=$((minor + 1)) + if [[ "${{ steps.check.outputs.has_major }}" != "true" ]]; then + patch=0 # Reset patch when minor is bumped (only if major wasn't bumped) + fi + echo "Applied minor bump: $major.$minor.$patch" + fi + + if [[ "${{ steps.check.outputs.has_patch }}" == "true" ]]; then + patch=$((patch + 1)) + echo "Applied patch bump: $major.$minor.$patch" + fi + + new_version="$major.$minor.$patch" + echo "Final calculated version: $new_version" + + # Create package.json if it doesn't exist + if [[ ! -f "package.json" ]]; then + echo '{"version": "0.0.0"}' > package.json + fi + + # Update package.json with new version + npm version $new_version --no-git-tag-version --allow-same-version + + echo "NEW_VERSION=v$new_version" >> $GITHUB_ENV + echo "New version will be: v$new_version" + + - name: Create Release + if: steps.check.outputs.should_release == 'true' + uses: softprops/action-gh-release@v2 + with: + token: ${{ secrets.PAT }} # Use PAT to trigger other workflows + tag_name: ${{ env.NEW_VERSION }} + name: "Release ${{ env.NEW_VERSION }}" + generate_release_notes: true + make_latest: true + body: | + ## 🚀 Release ${{ env.NEW_VERSION }} + + **Version Bumps Applied:** + - Major: ${{ steps.check.outputs.has_major }} + - Minor: ${{ steps.check.outputs.has_minor }} + - Patch: ${{ steps.check.outputs.has_patch }} + + **Triggered by:** PR #${{ github.event.pull_request.number }} - ${{ github.event.pull_request.title }} + **Merged by:** @${{ github.event.pull_request.merged_by.login }} + + ### Changes in this PR + ${{ github.event.pull_request.body }} + + --- + *This release was automatically created by the Auto Release workflow* + From 026c0f44ce5b946c9eaabdba12a05035a162bab6 Mon Sep 17 00:00:00 2001 From: Terraform Date: Sun, 31 Aug 2025 18:06:46 -0700 Subject: [PATCH 4/8] Fix release workflow to trigger production deployment --- .github/workflows/aws_auto_release.yml | 95 ++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 4 deletions(-) diff --git a/.github/workflows/aws_auto_release.yml b/.github/workflows/aws_auto_release.yml index 7fabd78..d00ba20 100644 --- a/.github/workflows/aws_auto_release.yml +++ b/.github/workflows/aws_auto_release.yml @@ -23,9 +23,96 @@ jobs: with: fetch-depth: 0 ref: main - token: ${{ secrets.PAT }} + token: ${{ secrets.PAT }} + + - name: Check if user is authorized + id: auth_check + run: | + merged_by="${{ github.event.pull_request.merged_by.login }}" + echo "PR was merged by: $merged_by" + + # Get authorized users from CODEOWNERS file + authorized_users=() + + # Read CODEOWNERS file if it exists + if [[ -f ".github/CODEOWNERS" ]]; then + echo "📋 Reading CODEOWNERS file..." + # Extract usernames from CODEOWNERS (remove @ prefix) + codeowners=$(grep -v '^#' .github/CODEOWNERS | grep -o '@[a-zA-Z0-9_-]*' | sed 's/@//' | sort -u) + for user in $codeowners; do + authorized_users+=("$user") + echo " - CODEOWNER: $user" + done + else + echo "⚠️ No CODEOWNERS file found" + fi + + # Get repository collaborators with admin/maintain permissions using GitHub API + echo "🔍 Checking repository permissions..." + + # Check if user has admin or maintain permissions + user_permission=$(curl -s -H "Authorization: token ${{ secrets.PAT }}" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/${{ github.repository }}/collaborators/$merged_by/permission" | \ + jq -r '.permission // "none"') + + echo "User $merged_by has permission level: $user_permission" + + # Check if user is authorized + is_authorized=false + + # Check if user is in CODEOWNERS + for user in "${authorized_users[@]}"; do + if [[ "$user" == "$merged_by" ]]; then + is_authorized=true + echo "✅ User $merged_by is authorized via CODEOWNERS" + break + fi + done + + # Check if user has admin or maintain permissions + if [[ "$user_permission" == "admin" || "$user_permission" == "maintain" ]]; then + is_authorized=true + echo "✅ User $merged_by is authorized via repository permissions ($user_permission)" + fi + + # Check if user is organization owner (for metaversecloud-com org) + org_response=$(curl -s -H "Authorization: token ${{ secrets.PAT }}" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/orgs/metaversecloud-com/members/$merged_by" \ + -w "%{http_code}") + + # Extract HTTP status code from the response + http_code=${org_response: -3} + + if [[ "$http_code" == "200" ]]; then + # Check if user is an owner + owner_status=$(curl -s -H "Authorization: token ${{ secrets.PAT }}" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/orgs/metaversecloud-com/memberships/$merged_by" | \ + jq -r '.role // "none"') + + if [[ "$owner_status" == "admin" ]]; then + is_authorized=true + echo "✅ User $merged_by is authorized as organization owner" + fi + fi + + echo "is_authorized=$is_authorized" >> $GITHUB_OUTPUT + + if [[ "$is_authorized" == "false" ]]; then + echo "❌ User $merged_by is not authorized to trigger releases" + echo "💡 Authorized users include:" + echo " - CODEOWNERS: ${authorized_users[*]}" + echo " - Repository admins and maintainers" + echo " - Organization owners" + exit 0 + else + echo "🎉 User $merged_by is authorized to trigger releases" + fi - name: Check for release labels and determine version bumps + if: steps.auth_check.outputs.is_authorized == 'true' id: check run: | labels='${{ toJson(github.event.pull_request.labels.*.name) }}' @@ -65,13 +152,13 @@ jobs: echo "Has major: $has_major, minor: $has_minor, patch: $has_patch" - name: Setup Node.js - if: steps.check.outputs.should_release == 'true' + if: steps.auth_check.outputs.is_authorized == 'true' && steps.check.outputs.should_release == 'true' uses: actions/setup-node@v4 with: node-version: 20.10 - name: Calculate new version with cumulative bumps - if: steps.check.outputs.should_release == 'true' + if: steps.auth_check.outputs.is_authorized == 'true' && steps.check.outputs.should_release == 'true' id: version run: | git config --global user.email "github-actions[bot]@users.noreply.github.com" @@ -125,7 +212,7 @@ jobs: echo "New version will be: v$new_version" - name: Create Release - if: steps.check.outputs.should_release == 'true' + if: steps.auth_check.outputs.is_authorized == 'true' && steps.check.outputs.should_release == 'true' uses: softprops/action-gh-release@v2 with: token: ${{ secrets.PAT }} # Use PAT to trigger other workflows From 9c72d79fbd07d43fcaa56d86d2b567dcef0339fe Mon Sep 17 00:00:00 2001 From: Terraform Date: Fri, 5 Sep 2025 10:52:00 -0700 Subject: [PATCH 5/8] Add production release CICD --- .github/workflows/aws_prod_release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/aws_prod_release.yml b/.github/workflows/aws_prod_release.yml index 43caaf6..3550e1a 100644 --- a/.github/workflows/aws_prod_release.yml +++ b/.github/workflows/aws_prod_release.yml @@ -50,7 +50,7 @@ jobs: cache: 'npm' - run: git config --global user.email devops@topia.io - run: git config --global user.name Devops - - run: npm version --workspaces --include-workspace-root true ${{ github.event.release.tag_name }} + - run: npm version --no-git-tag-version --workspaces --include-workspace-root true ${{ github.event.release.tag_name }} - run: npm i - run: CI=false npm run build From d2655e4ba97fd73e53764f20635e8f53d9290754 Mon Sep 17 00:00:00 2001 From: Terraform Date: Tue, 3 Feb 2026 20:51:17 +0000 Subject: [PATCH 6/8] Fix release workflow to trigger production deployment --- .github/workflows/aws_auto_release.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/aws_auto_release.yml b/.github/workflows/aws_auto_release.yml index d00ba20..c265155 100644 --- a/.github/workflows/aws_auto_release.yml +++ b/.github/workflows/aws_auto_release.yml @@ -36,7 +36,7 @@ jobs: # Read CODEOWNERS file if it exists if [[ -f ".github/CODEOWNERS" ]]; then - echo "📋 Reading CODEOWNERS file..." + echo "[INFO] Reading CODEOWNERS file..." # Extract usernames from CODEOWNERS (remove @ prefix) codeowners=$(grep -v '^#' .github/CODEOWNERS | grep -o '@[a-zA-Z0-9_-]*' | sed 's/@//' | sort -u) for user in $codeowners; do @@ -44,11 +44,11 @@ jobs: echo " - CODEOWNER: $user" done else - echo "⚠️ No CODEOWNERS file found" + echo "[WARN] No CODEOWNERS file found" fi # Get repository collaborators with admin/maintain permissions using GitHub API - echo "🔍 Checking repository permissions..." + echo "[CHECK] Checking repository permissions..." # Check if user has admin or maintain permissions user_permission=$(curl -s -H "Authorization: token ${{ secrets.PAT }}" \ @@ -65,7 +65,7 @@ jobs: for user in "${authorized_users[@]}"; do if [[ "$user" == "$merged_by" ]]; then is_authorized=true - echo "✅ User $merged_by is authorized via CODEOWNERS" + echo "[OK] User $merged_by is authorized via CODEOWNERS" break fi done @@ -73,7 +73,7 @@ jobs: # Check if user has admin or maintain permissions if [[ "$user_permission" == "admin" || "$user_permission" == "maintain" ]]; then is_authorized=true - echo "✅ User $merged_by is authorized via repository permissions ($user_permission)" + echo "[OK] User $merged_by is authorized via repository permissions ($user_permission)" fi # Check if user is organization owner (for metaversecloud-com org) @@ -94,21 +94,21 @@ jobs: if [[ "$owner_status" == "admin" ]]; then is_authorized=true - echo "✅ User $merged_by is authorized as organization owner" + echo "[OK] User $merged_by is authorized as organization owner" fi fi echo "is_authorized=$is_authorized" >> $GITHUB_OUTPUT if [[ "$is_authorized" == "false" ]]; then - echo "❌ User $merged_by is not authorized to trigger releases" - echo "💡 Authorized users include:" + echo "[ERROR] User $merged_by is not authorized to trigger releases" + echo "[TIP] Authorized users include:" echo " - CODEOWNERS: ${authorized_users[*]}" echo " - Repository admins and maintainers" echo " - Organization owners" exit 0 else - echo "🎉 User $merged_by is authorized to trigger releases" + echo "[SUCCESS] User $merged_by is authorized to trigger releases" fi - name: Check for release labels and determine version bumps @@ -221,7 +221,7 @@ jobs: generate_release_notes: true make_latest: true body: | - ## 🚀 Release ${{ env.NEW_VERSION }} + ## ? Release ${{ env.NEW_VERSION }} **Version Bumps Applied:** - Major: ${{ steps.check.outputs.has_major }} From 4219bc8cb4c3951f36139e29ff671e755b15b509 Mon Sep 17 00:00:00 2001 From: Lina Date: Mon, 9 Feb 2026 13:39:04 -0800 Subject: [PATCH 7/8] update README.md --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index bf2b561..ec47f6c 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,20 @@ Breakout is a fun speed networking experience. +## Built With + +### Client + +![React](https://img.shields.io/badge/react-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB) +![Vite](https://img.shields.io/badge/vite-%23646CFF.svg?style=for-the-badge&logo=vite&logoColor=white) +![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white) +![Tailwind CSS](https://img.shields.io/badge/tailwindcss-%2338B2AC.svg?style=for-the-badge&logo=tailwind-css&logoColor=white) + +### Server + +![Node.js](https://img.shields.io/badge/node.js-%2343853D.svg?style=for-the-badge&logo=node.js&logoColor=white) +![Express](https://img.shields.io/badge/express-%23000000.svg?style=for-the-badge&logo=express&logoColor=white) + ## Key Features - Be assigned into groups which will switch in timed intervals From 393cf5424872bda370824ee53b688c67842e3c2a Mon Sep 17 00:00:00 2001 From: Lina Date: Tue, 10 Feb 2026 19:03:08 -0800 Subject: [PATCH 8/8] Update .env-example and README --- .env-example | 9 ++++----- README.md | 31 ++++++++++++++++++------------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/.env-example b/.env-example index 3413ba1..6e3c1cb 100644 --- a/.env-example +++ b/.env-example @@ -1,8 +1,7 @@ -API_KEY=xxxxxxx PORT=3000 -INSTANCE_DOMAIN=api.topia.io -INTERACTIVE_KEY=xxxxxxx -INTERACTIVE_SECRET=xxxxxxx INSTANCE_PROTOCOL=https NODE_ENV=development -APP_URL=http://localhost:3000 \ No newline at end of file +APP_URL=https://your-app.ngrok-free.app/ +INSTANCE_DOMAIN=api.topia.io +INTERACTIVE_KEY=your_interactive_key +INTERACTIVE_SECRET=your_interactive_secret diff --git a/README.md b/README.md index ec47f6c..b615f03 100644 --- a/README.md +++ b/README.md @@ -39,11 +39,8 @@ Breakout is a fun speed networking experience. - Access: Click on the key asset to open the drawer and then select the Admin tab. Any changes you make here will only affect this instance of the application and will not impact other instances dropped in this or other worlds. - Admins can configure and start a breakout session. Anyone who is in the breakout area at the start of a round will be included in the experience. -- The number of groups may be adjusted at the start of a round to account for the increase or decrease in the number of participants. -- The Admin who started the breakout session cannot leave the world while the session is in progress, otherwise it will be halted. - - - +- The number of groups may be adjusted at the start of a round to account for the increase or decrease in the number of participants. +- The Admin who started the breakout session cannot leave the world while the session is in progress, otherwise it will be halted. ### Data objects @@ -62,6 +59,20 @@ _We use data objects to store information about each implementation of the app p - totalGamesResetCount (`keyAssets.${assetId}.totalGamesResetCount`) - totalGamesWonCount (`keyAssets.${assetId}.totalGamesWonCount`) +## Environment Variables + +Create a `.env` file in the root directory. See `.env-example` for a template. + +| Variable | Description | Required | +| -------------------- | ---------------------------------------------------------------------------------- | -------- | +| `PORT` | Server port | Yes | +| `INSTANCE_PROTOCOL` | Protocol for Topia API (`https` for production) | Yes | +| `NODE_ENV` | Node environment | No | +| `APP_URL` | Public URL for the app, used for webhook callbacks | Yes | +| `INSTANCE_DOMAIN` | Topia API domain (`api.topia.io` for production, `api-stage.topia.io` for staging) | Yes | +| `INTERACTIVE_KEY` | Topia interactive app key | Yes | +| `INTERACTIVE_SECRET` | Topia interactive app secret | Yes | + ## Developers: ### Getting Started @@ -76,15 +87,9 @@ _We use data objects to store information about each implementation of the app p ### Add your .env environmental variables -```json -API_KEY=xxxxxxxxxxxxx -INSTANCE_DOMAIN=api.topia.io -INSTANCE_PROTOCOL=https -INTERACTIVE_KEY=xxxxxxxxxxxxx -INTERACTIVE_SECRET=xxxxxxxxxxxxxx -``` +See [Environment Variables](#environment-variables) above. -### Where to find API_KEY, INTERACTIVE_KEY and INTERACTIVE_SECRET +### Where to find INTERACTIVE_KEY and INTERACTIVE_SECRET [Topia Dev Account Dashboard](https://dev.topia.io/t/dashboard/integrations)