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
3 changes: 0 additions & 3 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,3 @@ client/webui/frontend/cypress/
.github/actions
.github/workflows
wss-unified-agent.config

# Lock file (not needed in container)
uv.lock
32 changes: 31 additions & 1 deletion .github/helper_scripts/build_frontend.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,44 @@
import os
import shutil
import subprocess
from sys import stdout, exit as sys_exit
from sys import exit as sys_exit
from sys import stdout

from hatchling.builders.hooks.plugin.interface import BuildHookInterface


class CustomBuildHook(BuildHookInterface):
def initialize(self, version, build_data):
super().initialize(version, build_data)

# Check if we should skip UI builds (static assets already present)
skip_ui_build = os.environ.get("SAM_SKIP_UI_BUILD", "").lower() in (
"true",
"1",
"yes",
)

if skip_ui_build:
self.app.display_info("SAM_SKIP_UI_BUILD is set, skipping UI build steps\n")
self.app.display_info("Verifying static assets exist...\n")

required_paths = [
"config_portal/frontend/static",
"client/webui/frontend/static",
"docs/build",
]

missing = [p for p in required_paths if not os.path.exists(p)]
if missing:
raise RuntimeError(
f"SAM_SKIP_UI_BUILD is set but required static assets are missing: {', '.join(missing)}"
)

self.app.display_info(
"All required static assets found, proceeding with Python build only\n"
)
return

npm = shutil.which("npm")
if npm is None:
raise RuntimeError(
Expand Down
67 changes: 51 additions & 16 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,21 @@ jobs:
- name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0

- name: Install uv
uses: astral-sh/setup-uv@38f3f104447c67c051c4a08e39b64a148898af3a # v4.2.0
with:
enable-cache: true

- name: Sync and verify uv.lock
run: |
# Sync lock file with pyproject.toml
uv lock --upgrade-package solace-agent-mesh
# Check if lock file was modified
if ! git diff --quiet uv.lock; then
echo "Warning: uv.lock was out of sync and has been updated"
# In CI, we just warn but continue. In development, developers should commit the updated lock file.
fi

- name: Get Commit Hash
id: get_commit_hash
run: |
Expand All @@ -63,7 +78,7 @@ jobs:
- name: Get Version from hatch
id: get_version
run: |
python3 -m pip install hatch
uv tool install hatch
echo "version=$(hatch version)" >> $GITHUB_OUTPUT
echo "Found version: $(hatch version)"

Expand Down Expand Up @@ -154,19 +169,17 @@ jobs:
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0

- name: Configure AWS credentials
if: fromJSON(needs.prepare-metadata.outputs.docker_push)
- name: Configure AWS credentials (for ECR access)
uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1
with:
aws-access-key-id: ${{ secrets.SAM_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.SAM_AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_DEFAULT_REGION }}

- name: Login to Amazon ECR
if: fromJSON(needs.prepare-metadata.outputs.docker_push)
- name: Login to Amazon ECR (for cache access)
uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1

- name: Determine Image Name
- name: Determine Image Name and Cache Configuration
id: image_name
run: |
if [[ "${{ fromJSON(needs.prepare-metadata.outputs.use_ecr) }}" == "true" ]]; then
Expand All @@ -178,6 +191,27 @@ jobs:
fi
echo "image_name=${image_name}" >> $GITHUB_OUTPUT

# Always use ECR for cache reference (main branch writes here, PRs read from here)
ecr_cache_ref="${{ secrets.SAM_AWS_ECR_REGISTRY }}/solace-agent-mesh:buildcache-${{ matrix.platform.tag_suffix }}"
echo "ecr_cache_ref=${ecr_cache_ref}" >> $GITHUB_OUTPUT

# Configure cache settings based on build type
if [[ "${{ fromJSON(needs.prepare-metadata.outputs.docker_push) }}" == "true" ]]; then
# Main branch push: read from and write to ECR registry cache
echo "cache_from=type=registry,ref=${ecr_cache_ref}" >> $GITHUB_OUTPUT
echo "cache_to=type=registry,ref=${ecr_cache_ref},mode=max,ignore-error=true" >> $GITHUB_OUTPUT
echo "Main branch: Using ECR registry cache (read/write)"
else
# PR builds: read from ECR cache (best effort) + GHA cache, write to GHA cache only
# Multiple cache sources are newline-separated in docker/build-push-action
cat >> $GITHUB_OUTPUT << EOF
cache_from=type=registry,ref=${ecr_cache_ref}
type=gha,scope=${{ matrix.platform.tag_suffix }}
EOF
echo "cache_to=type=gha,scope=${{ matrix.platform.tag_suffix }},mode=max" >> $GITHUB_OUTPUT
echo "PR build: Reading from ECR registry cache + GHA cache, writing to GHA cache"
fi

- name: Build and Push Platform-Specific Image
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0
with:
Expand All @@ -186,8 +220,10 @@ jobs:
platforms: ${{ matrix.platform.name }}
tags: ${{ steps.image_name.outputs.image_name }}:${{ needs.prepare-metadata.outputs.version }}-${{ needs.prepare-metadata.outputs.short_sha }}-${{ matrix.platform.tag_suffix }}
push: ${{ fromJSON(needs.prepare-metadata.outputs.docker_push) }}
cache-from: type=gha,scope=${{ matrix.platform.tag_suffix }}
cache-to: type=gha,scope=${{ matrix.platform.tag_suffix }},mode=max
cache-from: ${{ steps.image_name.outputs.cache_from }}
cache-to: ${{ steps.image_name.outputs.cache_to }}
provenance: false
sbom: false

# ----------------------------------------------------
# PHASE 3: Merge Multi-Platform Manifest (Always)
Expand All @@ -199,15 +235,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Configure AWS credentials
if: fromJSON(needs.prepare-metadata.outputs.docker_push)
uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1
with:
aws-access-key-id: ${{ secrets.SAM_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.SAM_AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_DEFAULT_REGION }}

- name: Login to Amazon ECR
if: fromJSON(needs.prepare-metadata.outputs.docker_push)
uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1

- name: Setup Docker Buildx
Expand All @@ -224,17 +258,17 @@ jobs:
image_name="${{ github.repository }}"
echo "Using GitHub repository: ${image_name}"
fi

# Reconstruct tags
version="${{ needs.prepare-metadata.outputs.version }}"
release_tag="${{ needs.prepare-metadata.outputs.release_tag }}"
short_sha="${{ needs.prepare-metadata.outputs.short_sha }}"

tags="${image_name}:${version}"
tags="${tags},${image_name}:${version}-${short_sha}"
tags="${tags},${image_name}:${release_tag}"
tags="${tags},${image_name}:${release_tag}-${short_sha}"

echo "image_name=${image_name}" >> $GITHUB_OUTPUT
echo "tags=${tags}" >> $GITHUB_OUTPUT
echo "Created tags: ${tags}"
Expand All @@ -245,22 +279,23 @@ jobs:
# Define the platform-specific tags
AMD_TAG="${{ steps.image_tags.outputs.image_name }}:${{ needs.prepare-metadata.outputs.version }}-${{ needs.prepare-metadata.outputs.short_sha }}-amd64"
ARM_TAG="${{ steps.image_tags.outputs.image_name }}:${{ needs.prepare-metadata.outputs.version }}-${{ needs.prepare-metadata.outputs.short_sha }}-arm64"

echo "AMD64 Tag: ${AMD_TAG}"
echo "ARM64 Tag: ${ARM_TAG}"

# Convert comma-separated tags string to array and create manifest for each
IFS=',' read -ra TAGS <<< "${{ steps.image_tags.outputs.tags }}"
for TAG in "${TAGS[@]}"; do
# Trim any whitespace

TAG=$(echo "$TAG" | xargs)
echo "Creating manifest for tag: $TAG"
docker buildx imagetools create \
--tag "$TAG" \
"$AMD_TAG" \
"$ARM_TAG"
done

echo "Multi-platform manifest created successfully"

- name: Update Release Manifest
Expand Down
Loading
Loading