Merge branch 'main' of sobina-git:jbourdon/social-media
All checks were successful
deploy-socialize / image (push) Successful in 2m7s
deploy-socialize / deploy (push) Successful in 32s

This commit is contained in:
2026-05-05 23:26:59 -04:00
14 changed files with 70 additions and 363 deletions

View File

@@ -0,0 +1,54 @@
name: deploy-socialize
on:
push:
branches:
- main
jobs:
image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Docker CLI
run: apt-get update && apt-get install -y docker.io
- name: Login to Gitea container registry
env:
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
run: printf '%s' "$REGISTRY_PASSWORD" | docker login git.mapachotes.com -u "$REGISTRY_USER" --password-stdin
- name: Build images
run: |
docker build \
-t git.mapachotes.com/jbourdon/socialize-api:${{ gitea.sha }} \
-t git.mapachotes.com/jbourdon/socialize-api:latest \
-f backend/src/Socialize.Api/Dockerfile .
docker build \
--build-arg VITE_API_URL=/api \
-t git.mapachotes.com/jbourdon/socialize-web:${{ gitea.sha }} \
-t git.mapachotes.com/jbourdon/socialize-web:latest \
-f frontend/Dockerfile .
- name: Push images
run: |
docker push git.mapachotes.com/jbourdon/socialize-api:${{ gitea.sha }}
docker push git.mapachotes.com/jbourdon/socialize-api:latest
docker push git.mapachotes.com/jbourdon/socialize-web:${{ gitea.sha }}
docker push git.mapachotes.com/jbourdon/socialize-web:latest
deploy:
needs: image
runs-on: bookworm
steps:
- name: Install SSH client
run: apt-get update && apt-get install -y openssh-client
- name: Deploy on sobina
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_SSH_PRIVATE_KEY_B64: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY_B64 }}
run: |
mkdir -p ~/.ssh
printf '%s' "$DEPLOY_SSH_PRIVATE_KEY_B64" | base64 -d > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=accept-new "$DEPLOY_USER@$DEPLOY_HOST" \
'cd /srv/prod/socialize && ./deploy.sh'

View File

@@ -1,39 +0,0 @@
name: Backend CI/CD
on:
push:
branches:
- main
env:
AZURE_WEBAPP_NAME: hutopy-backend-api
DOTNET_VERSION: '10.0.x'
jobs:
build_and_deploy:
runs-on: ubuntu-latest
environment: dev
steps:
# Checkout the repository
- uses: actions/checkout@v2
# Setup .NET Core
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
# Run dotnet publish
- name: dotnet build and publish
run: |
cd backend
dotnet publish --configuration Release --artifacts-path ./publish/ Socialize.slnx
# Deploy to Azure WebApp
- name: Deploy to Azure WebApp
uses: azure/webapps-deploy@v2
with:
app-name: ${{ env.AZURE_WEBAPP_NAME }}
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
package: './backend/publish/publish/Socialize.Api/release/'

View File

@@ -1,38 +0,0 @@
name: Frontend CI/CD
on:
push:
branches:
- main
env:
AZURE_SWA_NAME: hutopy-portal
jobs:
build_and_deploy:
runs-on: ubuntu-latest
steps:
# Checkout the repository
- uses: actions/checkout@v2
# Npm install
- name: npm install
run: |
cd frontend
npm install
# Npm run build
- name: npm run build
run: |
cd frontend
npm run build
# Deploy to Azure SWA
- name: Deploy to Azure SWA
uses: azure/static-web-apps-deploy@v1
with:
action: "upload"
app_location: 'frontend'
output_location: 'dist'
azure_static_web_apps_api_token: ${{ secrets.AZURE_SWA_TOKEN }}

View File

@@ -1,82 +0,0 @@
name: Build
on:
pull_request:
branches: [ main ]
paths-ignore:
- '.scripts/**'
- .gitignore
- CODE_OF_CONDUCT.md
- LICENSE
- README.md
workflow_call:
inputs:
build-artifacts:
type: boolean
required: true
default: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
name: Checkout code
- name: Cache NuGet packages
uses: actions/cache@v3
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
restore-keys: |
${{ runner.os }}-nuget-
- name: Install .NET
uses: actions/setup-dotnet@v3
- name: Restore solution
run: dotnet restore
- name: Build solution
run: dotnet build --no-restore --configuration Release
- name: Test solution
run: dotnet test --no-build --configuration Release --filter "FullyQualifiedName!~AcceptanceTests"
- name: Publish website
if: ${{ inputs.build-artifacts == true }}
run: |
dotnet publish --configuration Release --runtime win-x86 --self-contained --output ./publish
cd publish
zip -r ./publish.zip .
working-directory: ./src/Web/
- name: Upload website artifact (website)
if: ${{ inputs.build-artifacts == true }}
uses: actions/upload-artifact@v3
with:
name: website
path: ./src/Web/publish/publish.zip
if-no-files-found: error
- name: Create EF Core migrations bundle
if: ${{ inputs.build-artifacts == true }}
run: |
dotnet new tool-manifest
dotnet tool install dotnet-ef
dotnet ef migrations bundle --configuration Release -p ./src/Infrastructure/ -s ./src/Web/ -o efbundle.exe
zip -r ./efbundle.zip efbundle.exe
env:
SkipNSwag: True
- name: Upload EF Core migrations bundle artifact (efbundle)
if: ${{ inputs.build-artifacts == true }}
uses: actions/upload-artifact@v3
with:
name: efbundle
path: ./efbundle.zip
if-no-files-found: error

View File

@@ -1,42 +0,0 @@
name: CICD
on:
push:
branches: [ main ]
paths-ignore:
- .gitignore
- CODE_OF_CONDUCT.md
- LICENSE
- README.md
permissions:
id-token: write
contents: read
jobs:
build:
uses: ./.github/workflows/build.yml
with:
build-artifacts: true
deploy-development:
uses: ./.github/workflows/deploy.yml
secrets: inherit
needs: [ build ]
with:
environmentName: Development
deploy-staging:
uses: ./.github/workflows/deploy.yml
secrets: inherit
needs: [ deploy-development ]
with:
environmentName: Staging
deploy-production:
uses: ./.github/workflows/deploy.yml
secrets: inherit
needs: [ deploy-staging ]
with:
environmentName: Production

View File

@@ -1,107 +0,0 @@
name: Deploy
on:
workflow_call:
inputs:
environmentName:
required: true
type: string
permissions:
id-token: write
contents: read
jobs:
validate:
runs-on: ubuntu-latest
environment: ${{ inputs.environmentName }}
steps:
- uses: actions/checkout@v3
name: Checkout code
- uses: azure/login@v1
name: Login to Azure
with:
client-id: ${{ vars.AZURE_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TENANT_ID }}
subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}
- if: inputs.environmentName == 'Development'
uses: azure/arm-deploy@v1
name: Run preflight validation
with:
deploymentName: ${{ github.run_number }}
resourceGroupName: ${{ vars.AZURE_RESOURCE_GROUP_NAME }}
template: ./.azure/bicep/main.bicep
parameters: >
environmentName=${{ inputs.environmentName }}
sqlAdministratorUsername=${{ vars.AZURE_SQL_ADMINISTRATOR_USERNAME }}
sqlAdministratorPassword=${{ secrets.AZURE_SQL_ADMINISTRATOR_PASSWORD }}
projectName=${{ vars.PROJECT_NAME }}
deploymentMode: Validate
- if: inputs.environmentName != 'Development'
uses: azure/arm-deploy@v1
name: Run what-if
with:
failOnStdErr: false
resourceGroupName: ${{ vars.AZURE_RESOURCE_GROUP_NAME }}
template: ./.azure/bicep/main.bicep
parameters: >
environmentName=${{ inputs.environmentName }}
sqlAdministratorUsername=${{ vars.AZURE_SQL_ADMINISTRATOR_USERNAME }}
sqlAdministratorPassword=${{ secrets.AZURE_SQL_ADMINISTRATOR_PASSWORD }}
projectName=${{ vars.PROJECT_NAME }}
additionalArguments: --what-if
deploy:
needs: [ validate ]
runs-on: ubuntu-latest
environment: ${{ inputs.environmentName }}
steps:
- uses: actions/checkout@v3
name: Checkout code
- uses: actions/download-artifact@v3
name: Download artifacts
- name: Install .NET
uses: actions/setup-dotnet@v3
- uses: azure/login@v1
name: Login to Azure
with:
client-id: ${{ vars.AZURE_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TENANT_ID }}
subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}
- uses: azure/arm-deploy@v1
id: deploy
name: Deploy infrastructure
with:
failOnStdErr: false
deploymentName: ${{ github.run_number }}
resourceGroupName: ${{ vars.AZURE_RESOURCE_GROUP_NAME }}
template: ./.azure/bicep/main.bicep
parameters: >
environmentName=${{ inputs.environmentName }}
sqlAdministratorUsername=${{ vars.AZURE_SQL_ADMINISTRATOR_USERNAME }}
sqlAdministratorPassword=${{ secrets.AZURE_SQL_ADMINISTRATOR_PASSWORD }}
projectName=${{ vars.PROJECT_NAME }}
- name: Initialise database
run: |
unzip -o ./efbundle/efbundle.zip
echo '{ "ConnectionStrings": { "DefaultConnection": "" } }' > appsettings.json
./efbundle.exe --connection "Server=${{ steps.deploy.outputs.sqlServerFullyQualifiedDomainName }};Initial Catalog=${{ steps.deploy.outputs.sqlDatabaseName }};Persist Security Info=False;User ID=${{ vars.AZURE_SQL_ADMINISTRATOR_USERNAME }};Password=${{ secrets.AZURE_SQL_ADMINISTRATOR_PASSWORD }};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" --verbose
- uses: azure/webapps-deploy@v2
name: Deploy website
with:
app-name: ${{ steps.deploy.outputs.appServiceAppName }}
package: website/publish.zip

View File

@@ -1,4 +1,3 @@
using Azure.Identity;
using FastEndpoints; using FastEndpoints;
using FastEndpoints.Swagger; using FastEndpoints.Swagger;
using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.HttpOverrides;
@@ -25,11 +24,10 @@ using Socialize.Api.Modules.Workspaces;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
if (!builder.Environment.IsDevelopment()) string? vaultUri = Environment.GetEnvironmentVariable("VaultUri");
if (!string.IsNullOrWhiteSpace(vaultUri))
{ {
var vaultUri = Environment.GetEnvironmentVariable("VaultUri") ?? throw new InvalidOperationException("Missing VaultUri configuration setting"); throw new InvalidOperationException("VaultUri configuration is not supported by this deployment. Move secrets to environment variables.");
builder.Configuration.AddAzureKeyVault(new Uri(vaultUri), new DefaultAzureCredential());
} }
builder.Services.AddCors(options => builder.Services.AddCors(options =>

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net10.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
@@ -12,11 +12,10 @@
<TreatWarningsAsErrors>false</TreatWarningsAsErrors> <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningsAsErrors /> <WarningsAsErrors />
<NoWarn>$(NoWarn);CA1515;CA2007</NoWarn> <!-- disable ConfigureAwait warning - not present in ASP.NET Core --> <NoWarn>$(NoWarn);CA1515;CA2007</NoWarn> <!-- disable ConfigureAwait warning - not present in ASP.NET Core -->
<EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.5.0" />
<PackageReference Include="Azure.Identity" Version="1.18.0" />
<PackageReference Include="FastEndpoints" Version="5.35.0" /> <PackageReference Include="FastEndpoints" Version="5.35.0" />
<PackageReference Include="FastEndpoints.Swagger" Version="5.35.0" /> <PackageReference Include="FastEndpoints.Swagger" Version="5.35.0" />
<PackageReference Include="JetBrains.Annotations" Version="2024.3.0" /> <PackageReference Include="JetBrains.Annotations" Version="2024.3.0" />

View File

@@ -1,11 +1,15 @@
{ {
"ConnectionStrings": {
"PostgresConnection": "Server=hutopypostgress.postgres.database.azure.com,5432;Database=hutopy;User Id=hutopy;Password=General2024!;Ssl Mode=Require;"
},
"Stripe": { "Stripe": {
"SocializeRate": 0.05 "SocializeRate": 0.05
}, },
"Website": { "Website": {
"FrontendBaseUrl": "https://hutopy.com" "FrontendBaseUrl": "https://socialize.mapachotes.com"
},
"LocalBlobStorage": {
"RootPath": "App_Data/blob-storage",
"RequestPath": "/api/storage"
},
"DevelopmentSeed": {
"Enabled": false
} }
} }

View File

@@ -1,6 +1,7 @@
VITE_API_URL=https://hutopy-backend-api.azurewebsites.net VITE_API_URL=/api
VITE_STRIPE_API_KEY=51OoveVDrRyqXtNdBAxIo183PujtqFyU0xUMK9YNtIijcHeDlcLN6pqkZWHbgaBA0FHrwLMSoy3yVLN33NX8ExOxL00MSZwgJN7 VITE_STRIPE_API_KEY=51OoveVDrRyqXtNdBAxIo183PujtqFyU0xUMK9YNtIijcHeDlcLN6pqkZWHbgaBA0FHrwLMSoy3yVLN33NX8ExOxL00MSZwgJN7
VITE_GOOGLE_CLIENT_ID=213344094492-7c83lqoh7mnjgadpeqo2lcs1krhbsnnd.apps.googleusercontent.com VITE_GOOGLE_CLIENT_ID=213344094492-7c83lqoh7mnjgadpeqo2lcs1krhbsnnd.apps.googleusercontent.com
VITE_FACEBOOK_APP_ID=1076433907621883 VITE_FACEBOOK_APP_ID=1076433907621883
AZURE_SUBSCRIPTION_ID=46feb20f-3ae1-495a-830b-a31f7b76483d AZURE_SUBSCRIPTION_ID=46feb20f-3ae1-495a-830b-a31f7b76483d
AZURE_TENANT_ID=2f389c0d-131d-4de4-a7ac-03bab7e7a04f AZURE_TENANT_ID=2f389c0d-131d-4de4-a7ac-03bab7e7a04f
VITE_PUBLIC_SITE_URL=https://socialize.mapachotes.com

View File

@@ -27,7 +27,7 @@ const disallowedRoutes = [
'/verify-email', '/verify-email',
]; ];
const siteUrl = (process.env.VITE_PUBLIC_SITE_URL ?? process.env.SITE_URL ?? 'http://localhost:5173') const siteUrl = (process.env.VITE_PUBLIC_SITE_URL ?? process.env.SITE_URL ?? 'https://socialize.mapachotes.com')
.replace(/\/$/, ''); .replace(/\/$/, '');
const distDir = resolve(process.cwd(), 'dist'); const distDir = resolve(process.cwd(), 'dist');

View File

@@ -1,16 +0,0 @@
{
"navigationFallback": {
"rewrite": "/index.html",
"exclude": ["/images/*.{png,jpg,gif}", "/css/*"]
},
"mimeTypes": {
".json": "application/json",
".webmanifest": "application/manifest+json"
},
"responseOverrides": {
"404": {
"rewrite": "/index.html",
"statusCode": 200
}
}
}

View File

@@ -1,15 +0,0 @@
{
"$schema": "https://aka.ms/azure/static-web-apps-cli/schema",
"configurations": {
"taim-ui": {
"appLocation": ".",
"outputLocation": "dist",
"appBuildCommand": "npm run build",
"run": "npm run dev",
"appDevserverUrl": "http://localhost:5173",
"resourceGroup": "Hutopy",
"appName": "hutopy-portal",
"env": "production"
}
}
}

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<staticContent>
<mimeMap fileExtension=".json" mimeType="application/json" />
<mimeMap fileExtension=".js" mimeType="application/javascript" />
<mimeMap fileExtension=".mjs" mimeType="application/javascript" />
</staticContent>
</system.webServer>
</configuration>