Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9f4cea1
feat: Add workflow to sync officer images from Firebase
jeydinpham Feb 11, 2026
3228f1c
fix: AddPR branch tag
jeydinpham Feb 19, 2026
d6b4e3a
fix: Attempting to fix the first deployment error
jeydinpham Feb 19, 2026
96ce493
fix: Firebase storage bucket error
jeydinpham Feb 19, 2026
12fe90f
feat: Update officer image sync workflow to clear old images and fetc…
jeydinpham Feb 19, 2026
8bdda17
fix: Re-add PR tag
jeydinpham Feb 19, 2026
263fa51
fix: Install opentelemetry I guess
jeydinpham Feb 19, 2026
97350fc
fix: Remove fancy summary and fix PR bug issue
jeydinpham Feb 20, 2026
41fd32b
feat: Attempting to sync data from Firestore
jeydinpham Feb 20, 2026
4b450f7
feat: Improve schema layout and Firestore data handling
jeydinpham Feb 20, 2026
021710c
feat: Update officer role extraction and image handling logic
jeydinpham Feb 20, 2026
30ac37d
refactor: Edit filepath of some officer page assets
jeydinpham Feb 20, 2026
9fbf2b4
fix: Some apostrophe error
jeydinpham Feb 20, 2026
87e68ab
fix: Attempt to fix filepath extension issue
jeydinpham Feb 21, 2026
489e0ea
feat: Add John Cole as a permanent advisor
jeydinpham Feb 21, 2026
5d53bac
feat: Add social links to officer cards
jeydinpham Feb 21, 2026
b654614
style: Adjust icon padding with the things above it
jeydinpham Feb 21, 2026
24bec2d
refactor: Revert change on officers config
jeydinpham Feb 21, 2026
f469763
fix: Attempt to fix problem by switching base branch for the PR
jeydinpham Feb 21, 2026
87343c9
fix: Add image module declarations for various formats
jeydinpham Feb 21, 2026
4f33b3d
fix: Attempt to fix branching issue by basing the PR off my branch
jeydinpham Feb 21, 2026
a2fef7d
fix: Second attempt to fix the PNG errors
jeydinpham Feb 21, 2026
50b6db6
feat: Let's see if Ruben's stuff still works right out of the box!
jeydinpham Feb 21, 2026
9f75b4e
feat: Use officer peechi
jeydinpham Feb 22, 2026
05da7a3
style: Free officer page from looking like a dumb grid
jeydinpham Feb 22, 2026
a937fcf
refactor: Revert that last commit holy moly
jeydinpham Feb 22, 2026
99dedc3
style: Remove grid layout and hover effects
jeydinpham Feb 23, 2026
aeafb85
fix: John Cole image pathing
jeydinpham Feb 23, 2026
14ba393
style: Adjust social links display, and remove Instagram as a social …
jeydinpham Feb 23, 2026
ec2775b
feat: Add officer count for every division
jeydinpham Feb 23, 2026
bd6c0af
style: Reduce size of the officer count text
jeydinpham Feb 23, 2026
2eff11e
style: Literally shifting the links array to the right
jeydinpham Feb 23, 2026
b516b65
feat: Add initial sorting by level, and then by alphabetical order
jeydinpham Feb 23, 2026
99f9ce3
refactor: Simplify division normalization by removing alias mapping
jeydinpham Feb 23, 2026
acc3645
refactor: Hide officer count for Advisor section
jeydinpham Feb 23, 2026
22a8c40
refactor: Change base branch to main
jeydinpham Feb 25, 2026
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
102 changes: 102 additions & 0 deletions .github/workflows/sync-firebase-images.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: Sync Firebase Officer Images

on:
pull_request:
workflow_dispatch:
inputs:
dry_run:
description: 'Perform a dry run without creating PR'
required: false
default: 'false'
type: choice
options:
- 'true'
- 'false'
storage_bucket:
description: 'Firebase Storage bucket name (leave empty for default)'
required: false
type: string

permissions:
contents: write
pull-requests: write

jobs:
sync-images:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref || 'main' }}

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '24'

- name: Install project dependencies
run: npm ci

- name: Install sync script dependencies
run: npm install --no-save firebase-admin @opentelemetry/api

- name: Create Firebase config
run: |
cat <<'EOF' > firebase-config.json
${{ secrets.FIREBASE_SERVICE_ACCOUNT_JSON }}
EOF

- name: Run sync script
env:
FIREBASE_CONFIG_PATH: firebase-config.json
DRY_RUN: ${{ github.event.inputs.dry_run || 'false' }}
FIREBASE_STORAGE_BUCKET: ${{ github.event.inputs.storage_bucket || secrets.FIREBASE_STORAGE_BUCKET || '' }}
run: node scripts/sync-firebase-images.js

- name: Validate generated TypeScript
run: npx tsc --noEmit

- name: Create Pull Request
if: (github.event.inputs.dry_run || 'false') == 'false'
id: create-pr
uses: peter-evans/create-pull-request@v5
with:
commit-message: 'chore: sync officer images from firebase'
title: 'chore: sync officer images from firebase'
body: |
This PR automatically syncs officer images from Firebase Storage.

**Changes:**
- Cleared old images from `public/assets/officer/`
- Downloaded latest officer images from Firebase Storage
- Exported Firestore officers grouped by division to `config/officers.config.ts`

The sync script:
1. Removes all existing images
2. Fetches current officer data from Firestore
3. Downloads images from Firebase Storage
4. Renames files based on officer names (firstName-lastName)
5. Exports officers from `officers` collection as typed division-based arrays

Generated by: [Sync Firebase Officer Images](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
branch: sync/firebase-officer-images
base: ${{ github.event.pull_request.head.ref || 'main' }}
delete-branch: true
labels: automated
add-paths: |
public/assets/officer/**
config/officers.config.ts

- name: Summary
if: always()
run: |
echo "## Sync Summary" >> $GITHUB_STEP_SUMMARY
echo "**Status:** Sync completed" >> $GITHUB_STEP_SUMMARY
if [ "${{ github.event.inputs.dry_run || 'false' }}" == "true" ]; then
echo "Mode: dry run" >> $GITHUB_STEP_SUMMARY
elif [ -n "${{ steps.create-pr.outputs.pull-request-number }}" ]; then
echo "PR: #${{ steps.create-pr.outputs.pull-request-number }}" >> $GITHUB_STEP_SUMMARY
else
echo "No PR created" >> $GITHUB_STEP_SUMMARY
fi
76 changes: 67 additions & 9 deletions config/officers.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,29 @@ import { industryOfficers } from './industry.config';
import { mediaOfficers } from './media.config';
import { projectsOfficers } from './projects.config';
import { researchOfficers } from './research.config';

export type Officer = {
name: string;
position: string;
image: string;
level?: number;
socialLinks?: Record<string, string>;
};

const defaultOfficer: Officer = {
name: 'Saksham Sangrula',
position: 'President',
image: '/assets/officer/OfficerImage.png',
export type ExportedOfficer = {
firstName: string;
lastName: string;
photo: {
url: string;
};
socialLinks: Record<string, string>;
level: number;
title: string;
};

type Divisions =
| 'advisor'
| 'executive'
| 'board'
| 'media'
| 'research'
Expand All @@ -32,11 +41,14 @@ type Divisions =
| 'industry';

export const divisionOfficerMap: Record<Divisions, Officer[]> = {
advisor: [{
image: '/assets/officer/JohnCole.png',
name: 'John Cole',
position: 'ACM Faculty Advisor',
}],
advisor: [
{
image: '/assets/officer/JohnCole.png',
name: 'John Cole',
position: 'ACM Faculty Sponsor',
},
],
executive: boardOfficers,
board: boardOfficers,
community: communityOfficers,
development: developmentOfficers,
Expand All @@ -47,3 +59,49 @@ export const divisionOfficerMap: Record<Divisions, Officer[]> = {
research: researchOfficers,
projects: projectsOfficers,
};

function splitName(name: string) {
const trimmedName = name.trim();
const nameParts = trimmedName.split(/\s+/);

if (nameParts.length === 0) {
return { firstName: '', lastName: '' };
}

if (nameParts.length === 1) {
return { firstName: nameParts[0], lastName: '' };
}

return {
firstName: nameParts[0],
lastName: nameParts.slice(1).join(' '),
};
}

function toExportedOfficer(officer: Officer): ExportedOfficer {
const { firstName, lastName } = splitName(officer.name);

return {
firstName,
lastName,
photo: {
url: officer.image,
},
socialLinks: {},
level: 0,
title: officer.position,
};
}

export const officersByDivision: Record<string, ExportedOfficer[]> = {
Advisor: divisionOfficerMap.advisor.map(toExportedOfficer),
Executive: divisionOfficerMap.executive.map(toExportedOfficer),
Media: divisionOfficerMap.media.map(toExportedOfficer),
Research: divisionOfficerMap.research.map(toExportedOfficer),
Development: divisionOfficerMap.development.map(toExportedOfficer),
Projects: divisionOfficerMap.projects.map(toExportedOfficer),
Education: divisionOfficerMap.education.map(toExportedOfficer),
Community: divisionOfficerMap.community.map(toExportedOfficer),
HackUTD: divisionOfficerMap.hackutd.map(toExportedOfficer),
Industry: divisionOfficerMap.industry.map(toExportedOfficer),
};
File renamed without changes
File renamed without changes
Binary file added public/assets/officer-peechi.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading