Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
74 changes: 43 additions & 31 deletions .github/workflows/apphost-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,48 @@ permissions:

jobs:
build:
name: AppHost Build
name: ${{ matrix.apphost.name }} Build
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
apphost:
- name: AppHost
project_name: Aspire.Dev.AppHost
project_path: src/apphost/Aspire.Dev.AppHost
artifact_name: apphost-release
- name: Preview AppHost
project_name: Aspire.Dev.Preview.AppHost
project_path: src/apphost/Aspire.Dev.Preview.AppHost
artifact_name: preview-apphost-release
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
with:
global-json-file: global.json

- name: Restore
run: cd src/apphost/Aspire.Dev.AppHost && dotnet restore

- name: Build
run: cd src/apphost/Aspire.Dev.AppHost && dotnet build --no-restore --configuration Release

- name: Verify output
run: |
APPHOST_DLL=$(ls -1 src/apphost/Aspire.Dev.AppHost/bin/Release/*/Aspire.Dev.AppHost.dll 2>/dev/null | head -n 1)
if [ -z "$APPHOST_DLL" ]; then
echo "AppHost build failed - output assembly not found"
ls -R src/apphost/Aspire.Dev.AppHost/bin/Release || true
exit 1
fi
echo "Found $APPHOST_DLL"
- name: Upload artifact
if: ${{ always() }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: apphost-release
path: src/apphost/Aspire.Dev.AppHost/bin/Release/*/
if-no-files-found: warn
retention-days: 7
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
with:
global-json-file: global.json

- name: Restore
run: cd ${{ matrix.apphost.project_path }} && dotnet restore

- name: Build
run: cd ${{ matrix.apphost.project_path }} && dotnet build --no-restore --configuration Release

- name: Verify output
run: |
APPHOST_DLL=$(ls -1 ${{ matrix.apphost.project_path }}/bin/Release/*/${{ matrix.apphost.project_name }}.dll 2>/dev/null | head -n 1)
if [ -z "$APPHOST_DLL" ]; then
echo "AppHost build failed - output assembly not found"
ls -R ${{ matrix.apphost.project_path }}/bin/Release || true
exit 1
fi
echo "Found $APPHOST_DLL"
- name: Upload artifact
if: ${{ always() }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ matrix.apphost.artifact_name }}
path: ${{ matrix.apphost.project_path }}/bin/Release/*/
if-no-files-found: warn
retention-days: 7
67 changes: 66 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,29 +68,84 @@ jobs:
uses: ./.github/workflows/frontend-build.yml
with:
node_version: '24.x'
artifact_name: ${{ github.event_name == 'pull_request' && format('frontend-dist-pr-{0}', github.event.pull_request.number) || 'frontend-dist' }}
artifact_retention_days: ${{ github.event_name == 'pull_request' && 30 || 7 }}
site_base_path: ${{ github.event_name == 'pull_request' && format('/prs/{0}', github.event.pull_request.number) || '/' }}

preview-registration-metadata:
needs: [changes, frontend-build]
if: ${{ github.event_name == 'pull_request' && needs.frontend-build.result == 'success' }}
runs-on: ubuntu-latest
steps:
- name: Write preview registration metadata
shell: bash
env:
REPOSITORY_OWNER: ${{ github.repository_owner }}
REPOSITORY_NAME: ${{ github.event.repository.name }}
PR_NUMBER: ${{ github.event.pull_request.number }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
ARTIFACT_NAME: ${{ needs.frontend-build.outputs.artifact_name }}
ARTIFACT_RUN_ID: ${{ needs.frontend-build.outputs.artifact_run_id }}
ARTIFACT_RUN_ATTEMPT: ${{ needs.frontend-build.outputs.artifact_run_attempt }}
COMPLETED_AT_UTC: ${{ needs.frontend-build.outputs.completed_at_utc }}
run: |
metadata_dir="$RUNNER_TEMP/pr-preview-registration"
mkdir -p "$metadata_dir"

jq -n \
--arg repositoryOwner "$REPOSITORY_OWNER" \
--arg repositoryName "$REPOSITORY_NAME" \
--arg headSha "$HEAD_SHA" \
--arg artifactName "$ARTIFACT_NAME" \
--arg completedAtUtc "$COMPLETED_AT_UTC" \
--argjson pullRequestNumber "$PR_NUMBER" \
--argjson runId "$ARTIFACT_RUN_ID" \
--argjson runAttempt "$ARTIFACT_RUN_ATTEMPT" \
'{
repositoryOwner: $repositoryOwner,
repositoryName: $repositoryName,
pullRequestNumber: $pullRequestNumber,
headSha: $headSha,
runId: $runId,
runAttempt: $runAttempt,
artifactName: $artifactName,
completedAtUtc: $completedAtUtc
}' > "$metadata_dir/preview-registration.json"

- name: Upload preview registration metadata
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: pr-preview-registration
path: ${{ runner.temp }}/pr-preview-registration/preview-registration.json
if-no-files-found: error
retention-days: 7

apphost-build:
needs: changes
if: ${{ needs.changes.outputs.apphost == 'true' }}
uses: ./.github/workflows/apphost-build.yml

ci-gate:
needs: [changes, frontend-build, apphost-build]
needs: [changes, frontend-build, preview-registration-metadata, apphost-build]
if: ${{ always() && !cancelled() }}
runs-on: ubuntu-latest
steps:
- name: Verify CI results
shell: bash
env:
IS_PULL_REQUEST: ${{ github.event_name == 'pull_request' }}
CHANGES_RESULT: ${{ needs.changes.result }}
FRONTEND_CHANGED: ${{ needs.changes.outputs.frontend }}
APPHOST_CHANGED: ${{ needs.changes.outputs.apphost }}
FRONTEND_RESULT: ${{ needs['frontend-build'].result }}
PREVIEW_METADATA_RESULT: ${{ needs['preview-registration-metadata'].result }}
APPHOST_RESULT: ${{ needs['apphost-build'].result }}
run: |
echo "is pull_request event: $IS_PULL_REQUEST"
echo "changes result: $CHANGES_RESULT"
echo "frontend changed: $FRONTEND_CHANGED"
echo "frontend-build result: $FRONTEND_RESULT"
echo "preview-registration-metadata result: $PREVIEW_METADATA_RESULT"
echo "apphost changed: $APPHOST_CHANGED"
echo "apphost-build result: $APPHOST_RESULT"

Expand All @@ -109,6 +164,16 @@ jobs:
exit 1
fi

if [[ "$IS_PULL_REQUEST" == "true" && "$FRONTEND_CHANGED" == "true" ]]; then
if [[ "$PREVIEW_METADATA_RESULT" != "success" ]]; then
echo "preview-registration-metadata should have run and succeeded."
exit 1
fi
elif [[ "$PREVIEW_METADATA_RESULT" != "skipped" ]]; then
echo "preview-registration-metadata should have been skipped."
exit 1
fi

if [[ "$APPHOST_CHANGED" == "true" ]]; then
if [[ "$APPHOST_RESULT" != "success" ]]; then
echo "apphost-build should have run and succeeded."
Expand Down
47 changes: 45 additions & 2 deletions .github/workflows/frontend-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,34 @@ on:
required: true
default: "24.x"
type: string
artifact_name:
description: Artifact name to publish
required: false
default: "frontend-dist"
type: string
artifact_retention_days:
description: Number of days to keep the uploaded artifact
required: false
default: 7
type: number
site_base_path:
description: Path base to use for the Astro build
required: false
default: "/"
type: string
outputs:
artifact_name:
description: Artifact name published by the workflow
value: ${{ jobs.build.outputs.artifact_name }}
artifact_run_id:
description: Workflow run ID that owns the published artifact
value: ${{ jobs.build.outputs.artifact_run_id }}
artifact_run_attempt:
description: Workflow run attempt that published the artifact
value: ${{ jobs.build.outputs.artifact_run_attempt }}
completed_at_utc:
description: UTC timestamp when the artifact workflow completed successfully
value: ${{ jobs.build.outputs.completed_at_utc }}

permissions:
contents: read
Expand All @@ -16,6 +44,11 @@ jobs:
build:
name: Frontend Build
runs-on: ubuntu-latest
outputs:
artifact_name: ${{ steps.publish-metadata.outputs.artifact_name }}
artifact_run_id: ${{ steps.publish-metadata.outputs.artifact_run_id }}
artifact_run_attempt: ${{ steps.publish-metadata.outputs.artifact_run_attempt }}
completed_at_utc: ${{ steps.publish-metadata.outputs.completed_at_utc }}
defaults:
run:
working-directory: src/frontend
Expand All @@ -41,6 +74,7 @@ jobs:
env:
MODE: production
ASTRO_TELEMETRY_DISABLED: 1
ASTRO_BASE_PATH: ${{ inputs.site_base_path }}
run: pnpm build:production

- name: Check dist
Expand All @@ -61,7 +95,16 @@ jobs:
if: ${{ always() }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: frontend-dist
name: ${{ inputs.artifact_name }}
path: src/frontend/dist
if-no-files-found: warn
retention-days: 7
retention-days: ${{ inputs.artifact_retention_days }}

- name: Capture artifact metadata
id: publish-metadata
shell: bash
run: |
echo "artifact_name=${{ inputs.artifact_name }}" >> "$GITHUB_OUTPUT"
echo "artifact_run_id=${{ github.run_id }}" >> "$GITHUB_OUTPUT"
echo "artifact_run_attempt=${{ github.run_attempt }}" >> "$GITHUB_OUTPUT"
echo "completed_at_utc=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> "$GITHUB_OUTPUT"
72 changes: 72 additions & 0 deletions .github/workflows/pr-preview-cleanup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: PR Preview Cleanup

on:
pull_request:
types: [ closed ]

permissions:
pull-requests: write

jobs:
cleanup-preview:
if: ${{ vars.PR_PREVIEW_BASE_URL != '' }}
runs-on: ubuntu-latest
steps:
- name: Check preview configuration
id: config
env:
PREVIEW_REGISTRATION_TOKEN: ${{ secrets.PR_PREVIEW_REGISTRATION_TOKEN }}
ASPIRE_BOT_APP_ID: ${{ secrets.ASPIRE_BOT_APP_ID }}
ASPIRE_BOT_PRIVATE_KEY: ${{ secrets.ASPIRE_BOT_PRIVATE_KEY }}
run: |
if [ -z "$PREVIEW_REGISTRATION_TOKEN" ]; then
echo "configured=false" >> "$GITHUB_OUTPUT"
else
echo "configured=true" >> "$GITHUB_OUTPUT"
fi

if [ -z "$ASPIRE_BOT_APP_ID" ] || [ -z "$ASPIRE_BOT_PRIVATE_KEY" ]; then
echo "app_configured=false" >> "$GITHUB_OUTPUT"
else
echo "app_configured=true" >> "$GITHUB_OUTPUT"
fi

- name: Create Aspire bot token
if: ${{ steps.config.outputs.app_configured == 'true' }}
id: app-token
uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
with:
app-id: ${{ secrets.ASPIRE_BOT_APP_ID }}
private-key: ${{ secrets.ASPIRE_BOT_PRIVATE_KEY }}
permission-pull-requests: write

- name: Remove preview registration
if: ${{ steps.config.outputs.configured == 'true' }}
env:
PREVIEW_BASE_URL: ${{ vars.PR_PREVIEW_BASE_URL }}
PREVIEW_REGISTRATION_TOKEN: ${{ secrets.PR_PREVIEW_REGISTRATION_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
curl --fail-with-body \
--request DELETE \
--url "${PREVIEW_BASE_URL%/}/api/previews/${PR_NUMBER}" \
--header "Authorization: Bearer $PREVIEW_REGISTRATION_TOKEN"

- name: Remove preview block from PR description
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
github-token: ${{ steps.app-token.outputs.token || github.token }}
script: |
const markerStart = '<!-- pr-preview:start -->';
const markerEnd = '<!-- pr-preview:end -->';
const pullRequest = context.payload.pull_request;
const existingBody = pullRequest.body ?? '';
const blockExpression = new RegExp(`\\n?${markerStart}[\\s\\S]*?${markerEnd}\\n?`, 'm');
const updatedBody = existingBody.replace(blockExpression, '\n').trimEnd();

await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pullRequest.number,
body: updatedBody,
});
Loading
Loading