1313 runs-on : ubuntu-latest
1414 permissions :
1515 contents : read
16- env :
17- _MENTRA_APP_MIN_INSTANCES : " 1"
18- _MENTRA_APP_MAX_INSTANCES : " 2"
19- _MENTRA_APP_USE_SPECS : 2.0-4.0Gi
20- _MENTRA_APP_VSWITCH : vsw-wz94gyb5cinmsod89a4tj, vsw-wz9p9qoldncmf9k5se950
21- _MENTRA_APP_SECURITY_GROUP : sg-wz95j71022jl4tezfozp
22- _MENTRA_APP_CONTAINER_GROUP_NAME : mentraos-dev-api-cg
23- _MENTRA_APP_CONTAINER_NAME : mentraos-dev-api-eci
24- _MENTRA_APP_SCALING_CONFIGURATION_NAME : mentraos-dev-api-scalingConfiguration
25- _MENTRA_APP_IMAGE : mentra-acr-cnsz-a-registry-vpc.cn-shenzhen.cr.aliyuncs.com/dev/api:latest
26- NODE_ENV : production
27- PORT : " 80"
28- SYSTEM_DASHBOARD_PACKAGE_NAME : system.augmentos.dashboard
29- CLOUD_VERSION : 2.1.2
30- REDEPLOY : 2
31- DEPLOYMENT_REGION : china
32- ADMIN_EMAILS : israelov@mentra.glass, isaiah@mentra.glass, matt@mentra.glass, cayden@mentra.glass, nicolo@mentra.glass, team@mentra.glass
33- CLOUD_PUBLIC_HOST_NAME : api.mentraglass.cn
34- CLOUD_HOST_NAME : api.mentraglass.cn
35- CLOUD_LOCAL_HOST_NAME : cloud-prod-cloud.default.svc.cluster.local:80
36- PORTER_APP_NAME : cloud-prod
37- ACR_INSTANCE_ID : cri-h675v46p9lj694l6
38- ACR_REGION_ID : cn-shenzhen
39- ACR_PUBLIC_DOMAIN : mentra-acr-cnsz-a-registry.cn-shenzhen.cr.aliyuncs.com
40- # Mentra config
41- MONGO_URL : ${{ secrets.MONGO_URL }}
42- AUGMENTOS_AUTH_JWT_SECRET : ${{ secrets.AUGMENTOS_AUTH_JWT_SECRET }}
43- INVITE_JWT_SECRET : ${{ secrets.INVITE_JWT_SECRET }}
44- JOE_MAMA_USER_JWT : ${{ secrets.JOE_MAMA_USER_JWT }}
45- TPA_AUTH_JWT_PRIVATE_KEY : ${{ secrets.TPA_AUTH_JWT_PRIVATE_KEY }}
46- # Livekit config
47- LIVEKIT_URL : ${{ secrets.LIVEKIT_URL }}
48- LIVEKIT_API_SECRET : ${{ secrets.LIVEKIT_API_SECRET }}
49- LIVEKIT_API_KEY : ${{ secrets.LIVEKIT_API_KEY }}
50- # Authing config
51- AUTHING_APP_SECRET : ${{ secrets.AUTHING_APP_SECRET }}
52- AUTHING_APP_ID : ${{ secrets.AUTHING_APP_ID }}
53- AUTHING_APP_HOST : ${{ secrets.AUTHING_APP_HOST }}
54- # Supabase config
55- SUPABASE_URL : ${{ secrets.SUPABASE_URL }}
56- SUPABASE_SERVICE_KEY : ${{ secrets.SUPABASE_SERVICE_KEY }}
57- SUPABASE_JWT_SECRET : ${{ secrets.SUPABASE_JWT_SECRET }}
58- # Azure OpenAI config
59- AZURE_OPENAI_API_DEPLOYMENT_NAME : gpt-4o
60- AZURE_OPENAI_API_INSTANCE_NAME : mentra-uscentral-resource
61- AZURE_OPENAI_API_KEY : ${{ secrets.AZURE_OPENAI_API_KEY }}
62- AZURE_OPENAI_API_VERSION : 2024-08-01-preview
63- # Azure Speech config
64- AZURE_SPEECH_KEY : ${{ secrets.AZURE_SPEECH_KEY }}
65- AZURE_SPEECH_REGION : centralus
66- # Soniox config
67- SONIOX_API_KEY : ${{ secrets.SONIOX_API_KEY }}
68- # Anthropic config
69- ANTHROPIC_API_KEY : ${{ secrets.ANTHROPIC_API_KEY }}
70- # ElevenLabs config
71- ELEVENLABS_API_KEY : ${{ secrets.ELEVENLABS_API_KEY }}
72- ELEVENLABS_DEFAULT_VOICE_ID : TX3LPaxmHKxFdv7VOQHJ
73- # OpenAI config
74- OPENAI_API_KEY : ${{ secrets.OPENAI_API_KEY }}
75- # LLM config
76- LLM_MODEL : gpt-4o
77- LLM_PROVIDER : azure
78- # Alibaba config
79- ALIBABA_ENDPOINT : ${{ secrets.ALIBABA_ENDPOINT }}
80- ALIBABA_WORKSPACE : ${{ secrets.ALIBABA_WORKSPACE }}
81- ALIBABA_DASHSCOPE_API_KEY : ${{ secrets.ALIBABA_DASHSCOPE_API_KEY }}
82- ALIBABA_ACCESS_KEY_ID : ${{ secrets.ALIBABA_ACCESS_KEY_ID }}
83- ALIBABA_ACCESS_KEY_SECRET : ${{ secrets.ALIBABA_ACCESS_KEY_SECRET }}
84- # BetterStack config
85- BETTERSTACK_SOURCE_TOKEN : ${{ secrets.BETTERSTACK_SOURCE_TOKEN }}
86- # Posthog config
87- POSTHOG_HOST : https://us.i.posthog.com
88- POSTHOG_PROJECT_API_KEY : ${{ secrets.POSTHOG_PROJECT_API_KEY }}
89- # Sentry config
90- SENTRY_DSN : ${{ secrets.SENTRY_DSN }}
91- # SerpAPI config
92- SERPAPI_API_KEY : ${{ secrets.SERPAPI_API_KEY }}
93- # Cloudflare config
94- CLOUDFLARE_ACCOUNT_ID : ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
95- CLOUDFLARE_API_TOKEN : ${{ secrets.CLOUDFLARE_API_TOKEN }}
96- CLOUD_URL : cloud
97- # Resend config
98- RESEND_API_KEY : ${{ secrets.RESEND_API_KEY }}
9916
10017 steps :
10118 # 1. Checkout source code
@@ -105,152 +22,126 @@ jobs:
10522 - id : vars
10623 run : echo "sha_short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
10724
108- # 3. Compute Docker tags dynamically
109- - id : docker-tags
110- run : |
111- BRANCH=${GITHUB_REF_NAME//\//-}
112- echo "tags=$BRANCH latest" >> "$GITHUB_OUTPUT"
113-
114- # 4. Docker Buildx
115- - uses : docker/setup-buildx-action@v2
116-
117- # 5. Install Alibaba Cloud CLI
118- - name : Install Alibaba Cloud CLI
119- run : |
120- curl -sSL https://aliyuncli.alicdn.com/aliyun-cli-linux-latest-amd64.tgz | tar -xz
121- sudo mv aliyun /usr/local/bin/
122-
123- # 6. Configure Alibaba CLI with long-lived AK/SK
124- - name : Configure Alibaba Cloud CLI
125- run : |
126- aliyun configure set \
127- --profile default \
128- --mode AK \
129- --region $ACR_REGION_ID \
130- --access-key-id ${{ secrets.ALIBABA_ACCESS_KEY_ID }} \
131- --access-key-secret ${{ secrets.ALIBABA_ACCESS_KEY_SECRET }}
132- shell : bash
133-
134- # 7. Get temporary Docker login token
135- - id : acr-token
136- run : |
137- TOKEN=$(aliyun cr GetAuthorizationToken \
138- --InstanceId $ACR_INSTANCE_ID \
139- --RegionId $ACR_REGION_ID \
140- | jq -r '.AuthorizationToken')
141- echo "token=$TOKEN" >> "$GITHUB_OUTPUT"
142-
143- # 8. Docker login with temporary token
144- - name : Docker Login to ACR
145- run : |
146- docker login \
147- --username cr_temp_user \
148- --password ${{ steps.acr-token.outputs.token }} \
149- $ACR_PUBLIC_DOMAIN
150-
151- # 9. Build & push Docker image
152- - uses : docker/build-push-action@v4
25+ - uses : Mentra-Community/cloud-actions/deploy-app-alibaba@v1
15326 with :
154- context : ./cloud
155- file : ./cloud/docker/Dockerfile.livekit
156- push : true
157- tags : |
158- ${{ env.ACR_PUBLIC_DOMAIN }}/dev/api:${{ steps.vars.outputs.sha_short }}
159- ${{ env.ACR_PUBLIC_DOMAIN }}/dev/api:latest
160-
161- # 10. Replace secrets in autoscaling config
162- - name : Replace secrets in autoscaling config
163- run : |
164- envsubst < .github/workflows/eci-autoscaling-config-new.yml > final-deployment.yml
165- shell : bash
166-
167- # 11. Fetch Scaling Group ID
168- - name : Fetch Scaling Group ID
169- id : fetch-sg
170- run : |
171- set -e
172- SCALING_GROUP_NAME="mentraos-dev-api-scalingGroup"
173-
174- echo "🔍 Fetching Scaling Group ID..."
175- RAW_JSON=$(aliyun ess DescribeScalingGroups \
176- --RegionId $ACR_REGION_ID \
177- --ScalingGroupName $SCALING_GROUP_NAME)
178-
179- SCALING_GROUP_ID=$(echo "$RAW_JSON" | jq -r '.ScalingGroups.ScalingGroup[0].ScalingGroupId')
180- echo "Scaling_Group_ID=$SCALING_GROUP_ID" >> $GITHUB_OUTPUT
181-
182- # 12. Create Scaling Configuration
183- - name : Create Scaling Configuration
184- id : create-config
185- run : |
186- echo "🧩 Creating new scaling configuration..."
187- CONFIG_JSON=$(aliyun ess ApplyEciScalingConfiguration \
188- --RegionId $ACR_REGION_ID \
189- --ScalingGroupId ${{ steps.fetch-sg.outputs.Scaling_Group_ID }} \
190- --Content "$(cat final-deployment.yml)" \
191- --version 2022-02-22 --method POST --force)
192-
193- CONFIG_ID=$(echo "$CONFIG_JSON" | jq -r '.ScalingConfigurationId')
194- echo "Scaling_Configuration_ID=$CONFIG_ID" >> $GITHUB_OUTPUT
195- echo "✅ Created scaling configuration: $CONFIG_ID"
196-
197- # 13. Start Instance Refresh
198- - name : Start Instance Refresh
199- id : start-refresh
200- run : |
201- set -e
202- echo "🚀 Starting instance refresh..."
203- REFRESH_JSON=$(aliyun ess StartInstanceRefresh \
204- --ScalingGroupId ${{ steps.fetch-sg.outputs.Scaling_Group_ID }} \
205- --DesiredConfiguration.ScalingConfigurationId ${{ steps.create-config.outputs.Scaling_Configuration_ID }} \
206- --Strategy Rolling \
207- --DesiredPercentage 100 \
208- --SkipMatching false \
209- --version 2022-02-22 --method POST --force)
210-
211- REFRESH_ID=$(echo "$REFRESH_JSON" | jq -r '.InstanceRefreshTaskId')
212- echo "Instance_Refresh_Task_ID=$REFRESH_ID" >> $GITHUB_OUTPUT
213- echo "🌀 Started Instance Refresh Task: $REFRESH_ID"
214-
215- # 14. Monitor Instance Refresh
216- - name : Monitor Instance Refresh
217- run : |
218- set -e
219- MAX_ATTEMPTS=40
220- INTERVAL=15
221-
222- SCALING_GROUP_ID="${{ steps.fetch-sg.outputs.Scaling_Group_ID }}"
223- INSTANCE_REFRESH_TASK_ID="${{ steps.start-refresh.outputs.Instance_Refresh_Task_ID }}"
224-
225- for ((i=1; i<=MAX_ATTEMPTS; i++)); do
226- STATUS_JSON=$(aliyun ess DescribeInstanceRefreshes \
227- --ScalingGroupId "$SCALING_GROUP_ID" \
228- --InstanceRefreshTaskIds "$INSTANCE_REFRESH_TASK_ID" \
229- --RegionId "$ACR_REGION_ID" \
230- --method GET \
231- --version 2022-02-22 \
232- --force)
233-
234- # Extract the status of the specified instance refresh task
235- STATUS=$(echo "$STATUS_JSON" | jq -r '.InstanceRefreshTasks[0].Status')
236- echo "⏱️ Attempt $i: Current status = $STATUS"
237-
238- case "$STATUS" in
239- Successful)
240- echo "✅ Instance refresh completed successfully!"
241- exit 0
242- ;;
243- Failed)
244- echo "❌ Instance refresh failed!"
245- exit 1
246- ;;
247- InProgress)
248- echo "⏳ Instance refresh in progress..."
249- ;;
250- *)
251- echo "⚠️ Unexpected status: $STATUS"
252- ;;
253- esac
254-
255- sleep $INTERVAL
256- done
27+ environment : " dev"
28+ alibaba-access-key-id : ${{ secrets.ALIBABA_ACCESS_KEY_ID }}
29+ alibaba-access-key-secret : ${{ secrets.ALIBABA_ACCESS_KEY_SECRET }}
30+ deployment-region : " cn-shenzhen"
31+ app-name : " api"
32+ acr-instance-id : " cri-h675v46p9lj694l6"
33+ acr-vpc-domain : " mentra-acr-cnsz-a-registry-vpc.cn-shenzhen.cr.aliyuncs.com"
34+ acr-public-domain : " mentra-acr-cnsz-a-registry.cn-shenzhen.cr.aliyuncs.com"
35+ docker-context : " ./cloud"
36+ dockerfile : " ./cloud/docker/Dockerfile.livekit"
37+ image-tag : ${{ steps.vars.outputs.sha_short }}
38+ min-instances : 1
39+ max-instances : 2
40+ use-specs : " 2.0-4.0Gi"
41+ vswitch : " vsw-wz94gyb5cinmsod89a4tj, vsw-wz9p9qoldncmf9k5se950"
42+ security-group : " sg-wz95j71022jl4tezfozp"
43+ env-yaml : |
44+ - name: redeploy
45+ value: "2"
46+ - name: DEPLOYMENT_REGION
47+ value: "china"
48+ - name: NODE_ENV
49+ value: "production"
50+ - name: PORT
51+ value: "80"
52+ - name: SYSTEM_DASHBOARD_PACKAGE_NAME
53+ value: "system.augmentos.dashboard"
54+ - name: CLOUD_VERSION
55+ value: "2.1.2"
56+ - name: ADMIN_EMAILS
57+ value: "israelov@mentra.glass, isaiah@mentra.glass, matt@mentra.glass, cayden@mentra.glass, nicolo@mentra.glass, team@mentra.glass"
58+ - name: CLOUD_PUBLIC_HOST_NAME
59+ value: "api.mentraglass.cn"
60+ - name: CLOUD_HOST_NAME
61+ value: "api.mentraglass.cn"
62+ - name: CLOUD_LOCAL_HOST_NAME
63+ value: "cloud-prod-cloud.default.svc.cluster.local:80"
64+ - name: PORTER_APP_NAME
65+ value: "cloud-prod"
66+ - name: MONGO_URL
67+ value: "${{ secrets.MONGO_URL }}"
68+ - name: AUGMENTOS_AUTH_JWT_SECRET
69+ value: "${{ secrets.AUGMENTOS_AUTH_JWT_SECRET }}"
70+ - name: INVITE_JWT_SECRET
71+ value: "${{ secrets.INVITE_JWT_SECRET }}"
72+ - name: JOE_MAMA_USER_JWT
73+ value: "${{ secrets.JOE_MAMA_USER_JWT }}"
74+ - name: TPA_AUTH_JWT_PRIVATE_KEY
75+ value: "${{ secrets.TPA_AUTH_JWT_PRIVATE_KEY }}"
76+ - name: LIVEKIT_URL
77+ value: "${{ secrets.LIVEKIT_URL }}"
78+ - name: LIVEKIT_API_SECRET
79+ value: "${{ secrets.LIVEKIT_API_SECRET }}"
80+ - name: LIVEKIT_API_KEY
81+ value: "${{ secrets.LIVEKIT_API_KEY }}"
82+ - name: AUTHING_APP_SECRET
83+ value: "${{ secrets.AUTHING_APP_SECRET }}"
84+ - name: AUTHING_APP_ID
85+ value: "${{ secrets.AUTHING_APP_ID }}"
86+ - name: AUTHING_APP_HOST
87+ value: "${{ secrets.AUTHING_APP_HOST }}"
88+ - name: SUPABASE_URL
89+ value: "${{ secrets.SUPABASE_URL }}"
90+ - name: SUPABASE_SERVICE_KEY
91+ value: "${{ secrets.SUPABASE_SERVICE_KEY }}"
92+ - name: SUPABASE_JWT_SECRET
93+ value: "${{ secrets.SUPABASE_JWT_SECRET }}"
94+ - name: AZURE_OPENAI_API_DEPLOYMENT_NAME
95+ value: "gpt-4o"
96+ - name: AZURE_OPENAI_API_INSTANCE_NAME
97+ value: "mentra-uscentral-resource"
98+ - name: AZURE_OPENAI_API_KEY
99+ value: "${{ secrets.AZURE_OPENAI_API_KEY }}"
100+ - name: AZURE_OPENAI_API_VERSION
101+ value: "2024-08-01-preview"
102+ - name: AZURE_SPEECH_KEY
103+ value: "${{ secrets.AZURE_SPEECH_KEY }}"
104+ - name: AZURE_SPEECH_REGION
105+ value: "centralus"
106+ - name: SONIOX_API_KEY
107+ value: "${{ secrets.SONIOX_API_KEY }}"
108+ - name: ANTHROPIC_API_KEY
109+ value: "${{ secrets.ANTHROPIC_API_KEY }}"
110+ - name: ELEVENLABS_API_KEY
111+ value: "${{ secrets.ELEVENLABS_API_KEY }}"
112+ - name: ELEVENLABS_DEFAULT_VOICE_ID
113+ value: "TX3LPaxmHKxFdv7VOQHJ"
114+ - name: OPENAI_API_KEY
115+ value: "${{ secrets.OPENAI_API_KEY }}"
116+ - name: LLM_MODEL
117+ value: "gpt-4o"
118+ - name: LLM_PROVIDER
119+ value: "azure"
120+ - name: ALIBABA_ENDPOINT
121+ value: "${{ secrets.ALIBABA_ENDPOINT }}"
122+ - name: ALIBABA_WORKSPACE
123+ value: "${{ secrets.ALIBABA_WORKSPACE }}"
124+ - name: ALIBABA_DASHSCOPE_API_KEY
125+ value: "${{ secrets.ALIBABA_DASHSCOPE_API_KEY }}"
126+ - name: ALIBABA_ACCESS_KEY_ID
127+ value: "${{ secrets.ALIBABA_ACCESS_KEY_ID }}"
128+ - name: ALIBABA_ACCESS_KEY_SECRET
129+ value: "${{ secrets.ALIBABA_ACCESS_KEY_SECRET }}"
130+ - name: BETTERSTACK_SOURCE_TOKEN
131+ value: "${{ secrets.BETTERSTACK_SOURCE_TOKEN }}"
132+ - name: POSTHOG_HOST
133+ value: "https://us.i.posthog.com"
134+ - name: POSTHOG_PROJECT_API_KEY
135+ value: "${{ secrets.POSTHOG_PROJECT_API_KEY }}"
136+ - name: SENTRY_DSN
137+ value: "${{ secrets.SENTRY_DSN }}"
138+ - name: SERPAPI_API_KEY
139+ value: "${{ secrets.SERPAPI_API_KEY }}"
140+ - name: CLOUDFLARE_ACCOUNT_ID
141+ value: "${{ secrets.CLOUDFLARE_ACCOUNT_ID }}"
142+ - name: CLOUDFLARE_API_TOKEN
143+ value: "${{ secrets.CLOUDFLARE_API_TOKEN }}"
144+ - name: CLOUD_URL
145+ value: "cloud"
146+ - name: RESEND_API_KEY
147+ value: "${{ secrets.RESEND_API_KEY }}"
0 commit comments