Skip to content

Commit 186d4af

Browse files
authored
Merge pull request #36 from metaversecloud-com/dev
EXP-572: Badges
2 parents c9dadfa + 001cef0 commit 186d4af

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1862
-595
lines changed
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
name: Auto Release on Main Merge
2+
on:
3+
pull_request:
4+
types: [closed]
5+
branches:
6+
- main
7+
8+
concurrency:
9+
group: ${{ github.event.pull_request.number || github.ref }}
10+
cancel-in-progress: true
11+
12+
permissions:
13+
contents: write
14+
pull-requests: read
15+
16+
jobs:
17+
auto_release:
18+
runs-on: ubuntu-latest
19+
if: github.event.pull_request.merged == true
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
with:
24+
fetch-depth: 0
25+
ref: main
26+
token: ${{ secrets.PAT }}
27+
28+
- name: Check if user is authorized
29+
id: auth_check
30+
run: |
31+
merged_by="${{ github.event.pull_request.merged_by.login }}"
32+
echo "PR was merged by: $merged_by"
33+
34+
# Get authorized users from CODEOWNERS file
35+
authorized_users=()
36+
37+
# Read CODEOWNERS file if it exists
38+
if [[ -f ".github/CODEOWNERS" ]]; then
39+
echo "[INFO] Reading CODEOWNERS file..."
40+
# Extract usernames from CODEOWNERS (remove @ prefix)
41+
codeowners=$(grep -v '^#' .github/CODEOWNERS | grep -o '@[a-zA-Z0-9_-]*' | sed 's/@//' | sort -u)
42+
for user in $codeowners; do
43+
authorized_users+=("$user")
44+
echo " - CODEOWNER: $user"
45+
done
46+
else
47+
echo "[WARN] No CODEOWNERS file found"
48+
fi
49+
50+
# Get repository collaborators with admin/maintain permissions using GitHub API
51+
echo "[CHECK] Checking repository permissions..."
52+
53+
# Check if user has admin or maintain permissions
54+
user_permission=$(curl -s -H "Authorization: token ${{ secrets.PAT }}" \
55+
-H "Accept: application/vnd.github.v3+json" \
56+
"https://api.github.com/repos/${{ github.repository }}/collaborators/$merged_by/permission" | \
57+
jq -r '.permission // "none"')
58+
59+
echo "User $merged_by has permission level: $user_permission"
60+
61+
# Check if user is authorized
62+
is_authorized=false
63+
64+
# Check if user is in CODEOWNERS
65+
for user in "${authorized_users[@]}"; do
66+
if [[ "$user" == "$merged_by" ]]; then
67+
is_authorized=true
68+
echo "[OK] User $merged_by is authorized via CODEOWNERS"
69+
break
70+
fi
71+
done
72+
73+
# Check if user has admin or maintain permissions
74+
if [[ "$user_permission" == "admin" || "$user_permission" == "maintain" ]]; then
75+
is_authorized=true
76+
echo "[OK] User $merged_by is authorized via repository permissions ($user_permission)"
77+
fi
78+
79+
# Check if user is organization owner (for metaversecloud-com org)
80+
org_response=$(curl -s -H "Authorization: token ${{ secrets.PAT }}" \
81+
-H "Accept: application/vnd.github.v3+json" \
82+
"https://api.github.com/orgs/metaversecloud-com/members/$merged_by" \
83+
-w "%{http_code}")
84+
85+
# Extract HTTP status code from the response
86+
http_code=${org_response: -3}
87+
88+
if [[ "$http_code" == "200" ]]; then
89+
# Check if user is an owner
90+
owner_status=$(curl -s -H "Authorization: token ${{ secrets.PAT }}" \
91+
-H "Accept: application/vnd.github.v3+json" \
92+
"https://api.github.com/orgs/metaversecloud-com/memberships/$merged_by" | \
93+
jq -r '.role // "none"')
94+
95+
if [[ "$owner_status" == "admin" ]]; then
96+
is_authorized=true
97+
echo "[OK] User $merged_by is authorized as organization owner"
98+
fi
99+
fi
100+
101+
echo "is_authorized=$is_authorized" >> $GITHUB_OUTPUT
102+
103+
if [[ "$is_authorized" == "false" ]]; then
104+
echo "[ERROR] User $merged_by is not authorized to trigger releases"
105+
echo "[TIP] Authorized users include:"
106+
echo " - CODEOWNERS: ${authorized_users[*]}"
107+
echo " - Repository admins and maintainers"
108+
echo " - Organization owners"
109+
exit 0
110+
else
111+
echo "[SUCCESS] User $merged_by is authorized to trigger releases"
112+
fi
113+
114+
- name: Check for release labels and determine version bumps
115+
if: steps.auth_check.outputs.is_authorized == 'true'
116+
id: check
117+
run: |
118+
labels='${{ toJson(github.event.pull_request.labels.*.name) }}'
119+
echo "PR Labels: $labels"
120+
121+
has_release_label=false
122+
has_major=false
123+
has_minor=false
124+
has_patch=false
125+
126+
# Check if release label exists
127+
if echo "$labels" | grep -q "release"; then
128+
has_release_label=true
129+
130+
# Check for each type of version bump
131+
if echo "$labels" | grep -q "major"; then
132+
has_major=true
133+
fi
134+
if echo "$labels" | grep -q "minor"; then
135+
has_minor=true
136+
fi
137+
if echo "$labels" | grep -q "patch"; then
138+
has_patch=true
139+
fi
140+
141+
# If no specific version type is specified, default to patch
142+
if [[ "$has_major" == "false" && "$has_minor" == "false" && "$has_patch" == "false" ]]; then
143+
has_patch=true
144+
fi
145+
fi
146+
147+
echo "should_release=$has_release_label" >> $GITHUB_OUTPUT
148+
echo "has_major=$has_major" >> $GITHUB_OUTPUT
149+
echo "has_minor=$has_minor" >> $GITHUB_OUTPUT
150+
echo "has_patch=$has_patch" >> $GITHUB_OUTPUT
151+
echo "Should release: $has_release_label"
152+
echo "Has major: $has_major, minor: $has_minor, patch: $has_patch"
153+
154+
- name: Setup Node.js
155+
if: steps.auth_check.outputs.is_authorized == 'true' && steps.check.outputs.should_release == 'true'
156+
uses: actions/setup-node@v4
157+
with:
158+
node-version: 20.10
159+
160+
- name: Calculate new version with cumulative bumps
161+
if: steps.auth_check.outputs.is_authorized == 'true' && steps.check.outputs.should_release == 'true'
162+
id: version
163+
run: |
164+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
165+
git config --global user.name "github-actions[bot]"
166+
167+
# Get the latest tag from git
168+
latest_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
169+
echo "Latest git tag: $latest_tag"
170+
171+
# Remove 'v' prefix if present
172+
current_version=${latest_tag#v}
173+
echo "Current version: $current_version"
174+
175+
# Parse current version
176+
IFS='.' read -r major minor patch <<< "$current_version"
177+
echo "Parsed version - Major: $major, Minor: $minor, Patch: $patch"
178+
179+
# Apply cumulative version bumps
180+
if [[ "${{ steps.check.outputs.has_major }}" == "true" ]]; then
181+
major=$((major + 1))
182+
minor=0 # Reset minor when major is bumped
183+
patch=0 # Reset patch when major is bumped
184+
echo "Applied major bump: $major.0.0"
185+
fi
186+
187+
if [[ "${{ steps.check.outputs.has_minor }}" == "true" ]]; then
188+
minor=$((minor + 1))
189+
if [[ "${{ steps.check.outputs.has_major }}" != "true" ]]; then
190+
patch=0 # Reset patch when minor is bumped (only if major wasn't bumped)
191+
fi
192+
echo "Applied minor bump: $major.$minor.$patch"
193+
fi
194+
195+
if [[ "${{ steps.check.outputs.has_patch }}" == "true" ]]; then
196+
patch=$((patch + 1))
197+
echo "Applied patch bump: $major.$minor.$patch"
198+
fi
199+
200+
new_version="$major.$minor.$patch"
201+
echo "Final calculated version: $new_version"
202+
203+
# Create package.json if it doesn't exist
204+
if [[ ! -f "package.json" ]]; then
205+
echo '{"version": "0.0.0"}' > package.json
206+
fi
207+
208+
# Update package.json with new version
209+
npm version $new_version --no-git-tag-version --allow-same-version
210+
211+
echo "NEW_VERSION=v$new_version" >> $GITHUB_ENV
212+
echo "New version will be: v$new_version"
213+
214+
- name: Create Release
215+
if: steps.auth_check.outputs.is_authorized == 'true' && steps.check.outputs.should_release == 'true'
216+
uses: softprops/action-gh-release@v2
217+
with:
218+
token: ${{ secrets.PAT }} # Use PAT to trigger other workflows
219+
tag_name: ${{ env.NEW_VERSION }}
220+
name: "Release ${{ env.NEW_VERSION }}"
221+
generate_release_notes: true
222+
make_latest: true
223+
body: |
224+
## ? Release ${{ env.NEW_VERSION }}
225+
226+
**Version Bumps Applied:**
227+
- Major: ${{ steps.check.outputs.has_major }}
228+
- Minor: ${{ steps.check.outputs.has_minor }}
229+
- Patch: ${{ steps.check.outputs.has_patch }}
230+
231+
**Triggered by:** PR #${{ github.event.pull_request.number }} - ${{ github.event.pull_request.title }}
232+
**Merged by:** @${{ github.event.pull_request.merged_by.login }}
233+
234+
### Changes in this PR
235+
${{ github.event.pull_request.body }}
236+
237+
---
238+
*This release was automatically created by the Auto Release workflow*
239+

.github/workflows/aws_prod_release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
cache: 'npm'
5151
- run: git config --global user.email devops@topia.io
5252
- run: git config --global user.name Devops
53-
- run: npm version --workspaces --include-workspace-root true ${{ github.event.release.tag_name }}
53+
- run: npm version --no-git-tag-version --workspaces --include-workspace-root true ${{ github.event.release.tag_name }}
5454
- run: npm i
5555
- run: CI=false npm run build
5656

client/index.html

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@
55
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77

8-
<link href="https://fonts.googleapis.com/css?family=Quicksand" rel="stylesheet" />
9-
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet" />
10-
<link href="https://sdk-style.s3.amazonaws.com/styles-2.0.0.css" rel="stylesheet" />
8+
<link
9+
href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&family=Quicksand:wght@300..700&display=swap"
10+
rel="stylesheet"
11+
/>
12+
<link
13+
href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap"
14+
rel="stylesheet"
15+
/>
16+
<link href="https://sdk-style.s3.amazonaws.com/styles-3.0.2.css" rel="stylesheet" />
1117

1218
<title>Race</title>
1319
</head>

client/src/App.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { useCallback, useContext, useEffect, useMemo, useState } from "react";
22
import { Route, Routes, useSearchParams } from "react-router-dom";
33

4-
// pagrs
4+
// pages
55
import Home from "@pages/Home";
6-
import Leaderboard from "@pages/Leaderboard";
6+
import LeaderboardPage from "@pages/LeaderboardPage";
77
import Error from "@pages/Error";
88

99
// context
@@ -89,7 +89,7 @@ const App = () => {
8989
return (
9090
<Routes>
9191
<Route path="/start" element={<Home />} />
92-
<Route path="/leaderboard" element={<Leaderboard />} />
92+
<Route path="/leaderboard" element={<LeaderboardPage />} />
9393
<Route path="*" element={<Error />} />
9494
</Routes>
9595
);

client/src/components/Admin/AdminGear.jsx

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import PropTypes from "prop-types";
2+
3+
export const AdminIconButton = ({ setShowSettings, showSettings }) => {
4+
return (
5+
<div className="icon-btn mb-4 text-right" onClick={() => setShowSettings(showSettings)}>
6+
{showSettings ? "←" : "⛭"}
7+
</div>
8+
);
9+
};
10+
11+
AdminIconButton.propTypes = {
12+
setShowSettings: PropTypes.func,
13+
showSettings: PropTypes.bool,
14+
};
15+
16+
export default AdminIconButton;

0 commit comments

Comments
 (0)