Skip to content

Commit 209005b

Browse files
Merge branch 'main' into jason-t-hankins/issue27
2 parents a7b0bd1 + 4954dc4 commit 209005b

196 files changed

Lines changed: 28225 additions & 62465 deletions

File tree

Some content is hidden

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

.force-deploy

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# .force-deploy configuration file for ShareThrift monorepo
2+
# Set FORCE_DEPLOY_* flags to control manual deployment overrides
3+
# Set to 'true' to force deployment, 'false' to disable
4+
5+
FORCE_DEPLOY_API=false
6+
FORCE_DEPLOY_UI=false
7+
FORCE_DEPLOY_DOCS=false
8+
9+
# Developers: Change any value to 'true' to force deployment of that package
10+
# Example:
11+
# FORCE_DEPLOY_API=true
12+
# FORCE_DEPLOY_UI=true
13+
# FORCE_DEPLOY_DOCS=true

.github/workflows/copilot-setup-steps.yml

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -33,64 +33,50 @@ jobs:
3333
uses: actions/setup-node@v4
3434
with:
3535
node-version: "22"
36-
cache: "npm"
3736

38-
- name: Cache node modules
39-
id: npm-cache
37+
- name: Install PNPM
38+
run: |
39+
npm install --global corepack@latest
40+
corepack enable
41+
corepack prepare pnpm@latest-10 --activate
42+
pnpm --version
43+
44+
- name: Cache pnpm store
45+
id: pnpm-cache
4046
uses: actions/cache@v4
4147
with:
4248
path: |
43-
~/.npm
44-
~/.cache
49+
~/.local/share/pnpm/store/v3
4550
node_modules
4651
packages/*/node_modules
4752
apps/*/node_modules
48-
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
53+
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
4954
restore-keys: |
50-
${{ runner.os }}-node-
55+
${{ runner.os }}-pnpm-
5156
5257
- name: Install JavaScript dependencies
53-
run: npm ci
54-
if: steps.npm-cache.outputs.cache-hit != 'true'
58+
run: pnpm install --frozen-lockfile
59+
if: steps.pnpm-cache.outputs.cache-hit != 'true'
5560

5661
- name: Cache Playwright browsers
5762
id: playwright-cache
5863
uses: actions/cache@v4
5964
with:
6065
path: /home/runner/.cache/ms-playwright
61-
key: ${{ runner.os }}-playwright-${{ hashFiles('**/package-lock.json') }}
66+
key: ${{ runner.os }}-playwright-${{ hashFiles('**/pnpm-lock.yaml') }}
6267
restore-keys: |
6368
${{ runner.os }}-playwright-
64-
6569
6670
- name: Install Playwright browsers
6771
run: |
6872
echo "Installing Playwright browsers for UI testing..."
69-
npx playwright install --with-deps
73+
pnpm exec playwright install --with-deps
7074
env:
7175
PLAYWRIGHT_BROWSERS_PATH: /home/runner/.cache/ms-playwright
7276
if: steps.playwright-cache.outputs.cache-hit != 'true'
7377

74-
7578
- name: Install Java SDK (Required for SonarCloud)
7679
uses: actions/setup-java@v4
7780
with:
7881
distribution: 'temurin'
7982
java-version: '17'
80-
81-
82-
# - name: Verify required environment variables
83-
# run: |
84-
# if [ -z "$SONAR_TOKEN" ]; then
85-
# echo "Error: SONAR_TOKEN is not set."
86-
# exit 1
87-
# fi
88-
# if [ -z "$GH_TOKEN" ]; then
89-
# echo "Error: GH_TOKEN is not set."
90-
# exit 1
91-
# fi
92-
# echo "All required environment variables are set."
93-
# env:
94-
# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
95-
# GH_TOKEN: ${{ secrets.GH_TOKEN }}
96-

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Simnova, LLC
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
[
2+
{
3+
"name": "APPLICATION_NAME",
4+
"value": "STH",
5+
"slotSetting": false
6+
},
7+
{
8+
"name": "AZURE_STORAGE_CONNECTION_STRING",
9+
"value": "@Microsoft.KeyVault(SecretUri=https://sharethrift-keyvault.vault.azure.net/secrets/STH-AZURE-STORAGE-CONNECTION-STRING)",
10+
"slotSetting": false
11+
},
12+
{
13+
"name": "AZURE_SUBSCRIPTION_ID",
14+
"value": "b46b070d-1eee-4d27-943a-32728cfca0b5",
15+
"slotSetting": false
16+
},
17+
{
18+
"name": "AZURE_RESOURCE_GROUP_NAME",
19+
"value": "rg-sharethrift",
20+
"slotSetting": false
21+
},
22+
{
23+
"name": "BLACK_LISTED_EMAILS",
24+
"value": "[]",
25+
"slotSetting": false
26+
},
27+
{
28+
"name": "COSMOSDB_CONNECTION_STRING",
29+
"value": "@Microsoft.KeyVault(SecretUri=https://sharethrift-keyvault.vault.azure.net/secrets/STH-COSMOSDB-CONNECTION-STRING)",
30+
"slotSetting": false
31+
},
32+
{
33+
"name": "COSMOSDB_DBNAME",
34+
"value": "sthdevcosmosdatbd52ztvowoqqe",
35+
"slotSetting": false
36+
},
37+
{
38+
"name": "KEY_VAULT_URL",
39+
"value": "https://sharethrift-keyvault.vault.azure.net/",
40+
"slotSetting": false
41+
},
42+
{
43+
"name": "NODE_ENV",
44+
"value": "production",
45+
"slotSetting": false
46+
},
47+
{
48+
"name": "PAYMENT_API_URL",
49+
"value": "",
50+
"slotSetting": false
51+
},
52+
{
53+
"name": "SENDGRID_API_KEY",
54+
"value": "@Microsoft.KeyVault(SecretUri=https://sharethrift-keyvault.vault.azure.net/secrets/STH-SENDGRID-API-KEY)",
55+
"slotSetting": false
56+
},
57+
{
58+
"name": "TWILIO_ACCOUNT_SID",
59+
"value": "@Microsoft.KeyVault(SecretUri=https://sharethrift-keyvault.vault.azure.net/secrets/STH-TWILIO-ACCOUNT-SID)",
60+
"slotSetting": false
61+
},
62+
{
63+
"name": "TWILIO_AUTH_TOKEN",
64+
"value": "@Microsoft.KeyVault(SecretUri=https://sharethrift-keyvault.vault.azure.net/secrets/STH-TWILIO-AUTH-TOKEN)",
65+
"slotSetting": false
66+
},
67+
{
68+
"name": "USER_PORTAL_OIDC_AUDIENCE",
69+
"value": "https://sharethrift.com/auth-redirect",
70+
"slotSetting": false
71+
},
72+
{
73+
"name": "USER_PORTAL_OIDC_ENDPOINT",
74+
"value": "https://sharethriftb2c.b2clogin.com/sharethriftb2c.onmicrosoft.com/b2c_1a_signup_signin/discovery/v2.0/keys",
75+
"slotSetting": false
76+
},
77+
{
78+
"name": "USER_PORTAL_OIDC_ISSUER",
79+
"value": "https://sharethriftb2c.b2clogin.com/961394d2-0a14-4946-9913-6eb4944419af/",
80+
"slotSetting": false
81+
}
82+
]

apps/api/deploy-api.yml

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,41 +11,85 @@ parameters:
1111
type: string
1212
- name: vmImageName
1313
type: string
14-
- name: functionAppNamePri
14+
- name: appSettingsJsonFileRelativePathPri
15+
displayName: 'AppSettings Json File Relative Path for Primary instance'
1516
type: string
1617

1718
jobs:
1819
- job: Infrastructure
1920
displayName: Infrastructure Setup
20-
condition: eq(stageDependencies.Build.BuildJob.outputs['BuildJob.HAS_BACKEND_CHANGES'], 'true')
21+
condition: eq(stageDependencies.Build.Build.outputs['BuildJob.HAS_BACKEND_CHANGES'], 'true')
2122
pool:
2223
vmImage: ${{parameters.vmImageName}}
2324
steps:
2425
- task: AzureResourceManagerTemplateDeployment@3
26+
name: deployInfrastructure
27+
displayName: 'Deploy API Infrastructure'
2528
inputs:
2629
connectedServiceName: ${{parameters.ServiceConnectionName}}
27-
deploymentName: $(Build.BuildNumber)
30+
deploymentName: $(Build.BuildNumber)-api
2831
location: ${{parameters.deploymentDefaultLocation}}
2932
resourceGroupName: ${{parameters.resourceGroupName}}
3033
csmFile: apps/api/iac/main.bicep
31-
overrideParameters: >
32-
-environment ${{parameters.environmentNameBicep}}
34+
csmParametersFile: apps/api/iac/${{parameters.environmentNameBicep}}.bicepparam
35+
deploymentOutputs: 'armOutputs'
36+
# overrideParameters: >
37+
# -environment ${{parameters.environmentNameBicep}}
38+
39+
- task: PowerShell@2
40+
name: captureOutputs
41+
displayName: 'Capture Infrastructure Outputs'
42+
inputs:
43+
targetType: 'inline'
44+
script: |
45+
Write-Host "Debug - armOutputs: $(armOutputs)"
46+
$var = ConvertFrom-Json '$(armOutputs)'
47+
$functionAppNamePri = $var.functionAppNamePri.value
48+
Write-Host "Function App Name (Primary): $functionAppNamePri"
49+
Write-Host "##vso[task.setvariable variable=functionAppNamePri;isOutput=true]$functionAppNamePri"
50+
3351
- deployment: Application_Deployment_Pri
3452
displayName: Application Deployment (Primary)
35-
condition: eq(stageDependencies.Build.BuildJob.outputs['BuildJob.HAS_BACKEND_CHANGES'], 'true')
53+
condition: and(succeeded(), eq(stageDependencies.Build.Build.outputs['BuildJob.HAS_BACKEND_CHANGES'], 'true'))
54+
dependsOn: Infrastructure
3655
environment: ${{parameters.environmentNameDevOps}}
3756
pool:
3857
vmImage: ${{parameters.vmImageName}}
58+
variables:
59+
functionAppNamePri: $[ dependencies.Infrastructure.outputs['captureOutputs.functionAppNamePri'] ]
3960
strategy:
4061
runOnce:
4162
deploy:
4263
steps:
64+
- download: current
65+
displayName: 'Artifact: Download API package'
66+
artifact: api
4367
- task: AzureFunctionApp@1
44-
displayName: 'Azure Functions App Deploy: ${{parameters.functionAppNamePri}}'
68+
displayName: 'Azure Functions App Deploy: $(functionAppNamePri)'
4569
inputs:
4670
azureSubscription: ${{parameters.ServiceConnectionName}}
4771
appType: 'functionAppLinux'
48-
appName: ${{parameters.functionAppNamePri}}
49-
package: '$(Pipeline.Workspace)/drop/$(Build.BuildId).zip'
72+
appName: $(functionAppNamePri)
73+
package: '$(Pipeline.Workspace)/api/api-$(Build.BuildId).zip'
5074
runtimeStack: 'NODE|22'
51-
deploymentMethod: 'runFromPackage'
75+
deploymentMethod: 'runFromPackage'
76+
77+
- job: Application_Settings_Pri
78+
displayName: Application Settings (Primary)
79+
condition: and(succeeded(), eq(stageDependencies.Build.Build.outputs['BuildJob.HAS_BACKEND_CHANGES'], 'true'))
80+
dependsOn:
81+
- Infrastructure
82+
- Application_Deployment_Pri
83+
pool:
84+
vmImage: ${{parameters.vmImageName}}
85+
variables:
86+
functionAppNamePri: $[ dependencies.Infrastructure.outputs['captureOutputs.functionAppNamePri'] ]
87+
steps:
88+
- powershell: |
89+
$output = Get-Content '$(Build.SourcesDirectory)/${{parameters.appSettingsJsonFileRelativePathPri}}'
90+
Write-Host "##vso[task.setvariable variable=appSettingsPri]$($output)"
91+
- task: AzureAppServiceSettings@1
92+
inputs:
93+
azureSubscription: ${{parameters.ServiceConnectionName}}
94+
appName: $(functionAppNamePri)
95+
appSettings: '$(appSettingsPri)'

apps/api/iac/dev.bicepparam

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using './main.bicep'
2+
3+
param env = 'dev'
4+
param applicationPrefix = 'sth'
5+
param tags = {
6+
environment: 'dev'
7+
application: 'sth'
8+
}
9+
10+
//app service plan
11+
param appServicePlanInstanceName = 'pri-001'
12+
param appServicePlanLocation = 'eastus2'
13+
param appServicePlanSku = 'B1'
14+
param appServicePlanOperatingSystem = 'linux'
15+
16+
// application insights
17+
param applicationInsightsLocation = 'eastus2'
18+
19+
//function app
20+
param functionAppStorageAccountName = 'cxadevfunceastus2'
21+
param functionAppLocation = 'eastus2'
22+
param functionAppInstanceName = 'pri'
23+
param functionWorkerRuntime = 'node'
24+
param functionExtensionVersion = '~4'
25+
param maxOldSpaceSizeMB = 3072
26+
param linuxFxVersion = 'NODE|22'
27+
param allowedOrigins = [
28+
'https://sharethrift.com'
29+
]
30+
param keyVaultName = 'sharethrift-keyvault'
31+
32+
//storage account
33+
param storageAccountName = 'app'
34+
param storageAccountLocation = 'eastus2'
35+
param storageAccountSku = 'Standard_RAGZRS'
36+
param storageAccountManagementPolicy = {
37+
enable: false
38+
deleteAfterNDaysList: []
39+
}
40+
param enableBlobService = true
41+
param containers = [
42+
{
43+
name: 'public'
44+
publicAccess: 'blob'
45+
}
46+
{
47+
name: 'private'
48+
publicAccess: 'None'
49+
}
50+
]
51+
param enableQueueService = true
52+
param queues = []
53+
param cors = {
54+
allowedOrigins: [
55+
'https://sharethrift.com'
56+
]
57+
allowedMethods: [
58+
'GET'
59+
'POST'
60+
'PUT'
61+
'OPTIONS'
62+
]
63+
allowedHeaders: [
64+
'*'
65+
]
66+
exposedHeaders: [
67+
'x-ms-version-id'
68+
]
69+
maxAgeInSeconds: 0
70+
}
71+
param enableTableService = false
72+
param isVersioningEnabled = true
73+
param tables = []
74+
75+
76+
//cosmos
77+
param cosmosMongoDBInstanceName = 'dat'
78+
param cosmosLocation = 'eastus2'
79+
param totalThroughputLimit = 3200
80+
param backupIntervalInMinutes = 240
81+
param backupRetentionIntervalInHours = 96
82+
param maxThroughput = 1000
83+
param runRbacRoleAssignment = false
84+
param enableAnalyticalStorage = true
85+
param rbacMembers = []

0 commit comments

Comments
 (0)