Skip to content

Commit

Permalink
Improvement/build cicd (#406)
Browse files Browse the repository at this point in the history
* Enhance GitHub Actions workflow for multi-platform deployment

- Updated artifact naming to include sanitized platform name and added error handling for missing files.
- Changed the download artifact step to use a pattern for better flexibility.
- Configured Git settings for the action and implemented a rebase strategy before committing version updates.
- Added logic to conditionally update the version for the multi platform based on the environment.
- Improved push logic with retry mechanism for better reliability.

This update streamlines the deployment process and ensures version consistency across platforms.

* Refine GitHub Actions workflow conditions for multi-platform deployment

- Updated job conditions to improve handling of workflow events, specifically for 'workflow_run' scenarios.
- Enhanced failure handling in the CI job by explicitly exiting with an error code.
- Adjusted the 'information' job to trigger on additional event types, ensuring better integration with release processes.
- Streamlined conditions for the 'publish_addon' job to ensure it only runs when all dependencies succeed.

These changes enhance the robustness and reliability of the deployment process.

* Enhance GitHub Actions workflow with retry logic and batch processing

- Introduced a retry mechanism with exponential backoff for the manifest creation and image inspection steps to improve reliability.
- Implemented batch processing for manifest creation to handle digests in smaller groups, reducing the risk of failures during the process.
- Added logging for batch processing to provide better visibility into the workflow execution.

These changes enhance the robustness of the deployment process, ensuring smoother multi-platform deployments.

* Refactor GitHub Actions workflow for multi-platform deployment

* Enhance GitHub Actions workflow with additional logging and wait times

- Added logging statements to indicate wait periods during manifest creation and image inspection steps.
- Introduced consistent wait times (30 seconds after manifest creation, 10 seconds between platform inspections, and 5 seconds before retrying pushes) to improve stability and reliability of the deployment process.

These changes aim to provide better visibility into the workflow execution and ensure smoother multi-platform deployments.
  • Loading branch information
maslyankov authored Jan 22, 2025
1 parent f75cb4c commit 02f085f
Showing 1 changed file with 156 additions and 24 deletions.
180 changes: 156 additions & 24 deletions .github/workflows/deploy-multi-mp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,20 @@ env:
jobs:
ci-failure:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
if: |
github.event_name == 'workflow_run' &&
github.event.workflow_run.conclusion == 'failure'
steps:
- run: echo 'CI failed'
- run: exit 1

information:
name: Gather add-on information
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'release' }}
if: |
github.event_name == 'workflow_dispatch' ||
github.event_name == 'release' ||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')
outputs:
architectures: ${{ steps.information.outputs.architectures }}
build: ${{ steps.information.outputs.build }}
Expand Down Expand Up @@ -172,14 +179,20 @@ jobs:
- name: Artifact platform file for later
uses: actions/upload-artifact@v4
with:
name: outputs
name: platform-outputs-${{ env.SANITIZED_PLATFORM }}
path: outputs/*.txt
if-no-files-found: error
retention-days: 1

merge:
runs-on: ubuntu-latest
needs:
- information
- build
if: |
always() &&
needs.information.result == 'success' &&
needs.build.result != 'failure'
steps:
- name: Download digests
uses: actions/download-artifact@v4
Expand All @@ -204,11 +217,12 @@ jobs:
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Load outputs
- name: Download platform outputs
uses: actions/download-artifact@v4
with:
name: outputs
pattern: platform-outputs-*
path: outputs
merge-multiple: true

- name: Load outputs to variable
id: platforms_raw
Expand Down Expand Up @@ -247,37 +261,155 @@ jobs:
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create $TAGS_STRING \
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
# Function to retry with exponential backoff
function retry_with_backoff() {
local max_attempts=5
local timeout=10 # Start with 10 seconds
local attempt=1
while true; do
echo "Attempt $attempt of $max_attempts"
if "$@"; then
return 0
fi
if [[ $attempt -ge $max_attempts ]]; then
echo "Failed after $attempt attempts"
return 1
fi
echo "Attempt $attempt failed! Retrying in $timeout seconds..."
sleep $timeout
timeout=$((timeout * 2))
attempt=$((attempt + 1))
done
}
# Get all digests
digests=($(ls))
echo "Found digests: ${digests[*]}"
# Create base manifest first
echo "Creating base manifest..."
retry_with_backoff docker buildx imagetools create \
-t ${{ env.REGISTRY_IMAGE }}:${{ needs.information.outputs.version }} \
-t ${{ env.REGISTRY_IMAGE }}:${{ needs.information.outputs.environment }} \
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' "${digests[@]}")
echo "Waiting 30 seconds after base manifest creation before processing platform-specific tags..."
sleep 30 # Wait 30 seconds before processing platform-specific tags
# Process each platform separately
platforms="${{ steps.platforms_raw.outputs.value }}"
IFS=',' read -ra PLATFORM_ARRAY <<< "$platforms"
for PLATFORM in "${PLATFORM_ARRAY[@]}"; do
echo "Processing platform: $PLATFORM"
retry_with_backoff docker buildx imagetools create \
-t ${{ env.REGISTRY_IMAGE }}/${PLATFORM}:${{ needs.information.outputs.version }} \
-t ${{ env.REGISTRY_IMAGE }}/${PLATFORM}:${{ needs.information.outputs.environment }} \
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' "${digests[@]}")
echo "Completed manifest for $PLATFORM"
echo "Waiting 30 seconds before processing next platform..."
sleep 30 # Wait 30 seconds between platforms
done
- name: Inspect image
run: |
# Inspect the image using the first tag from TAGS_STRING (without the leading '-t ' part)
INSPECT_TAG=$(echo "${TAGS_STRING}" | awk '{print $2}')
# Log the tag being inspected
echo "Inspecting image with tag: $INSPECT_TAG"
# Run the inspection
docker buildx imagetools inspect $INSPECT_TAG
# Function to retry with exponential backoff
function retry_with_backoff() {
local max_attempts=5
local timeout=10
local attempt=1
while true; do
echo "Attempt $attempt of $max_attempts"
if "$@"; then
return 0
fi
if [[ $attempt -ge $max_attempts ]]; then
echo "Failed after $attempt attempts"
return 1
fi
echo "Attempt $attempt failed! Retrying in $timeout seconds..."
sleep $timeout
timeout=$((timeout * 2))
attempt=$((attempt + 1))
done
}
echo "Waiting 30 seconds for manifests to settle before starting inspections..."
sleep 30
# Inspect base image first
echo "Inspecting base image..."
retry_with_backoff docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ needs.information.outputs.version }}
# Inspect each platform
platforms="${{ steps.platforms_raw.outputs.value }}"
IFS=',' read -ra PLATFORM_ARRAY <<< "$platforms"
for PLATFORM in "${PLATFORM_ARRAY[@]}"; do
echo "Inspecting platform: $PLATFORM"
retry_with_backoff docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}/${PLATFORM}:${{ needs.information.outputs.version }}
echo "Waiting 10 seconds before inspecting next platform..."
sleep 10
done
publish_addon:
name: 🆕 Update addon version to ${{ needs.information.outputs.version }}
needs: [information, build, merge]
if: |
always() &&
needs.information.result == 'success' &&
needs.build.result != 'failure' &&
needs.merge.result == 'success'
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Point edge to the new ref
with:
fetch-depth: 0
ref: main

- name: Configure Git
run: |
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
- name: Update versions and commit changes
run: |
# Pull latest changes with rebase strategy
git pull --rebase origin main
# Make the version updates
sed -i 's/version:.*/version: "${{ needs.information.outputs.version }}"/g' hass-addon-sunsynk-edge/config.yaml
- name: Point multi to the new ref
if: "${{ needs.information.outputs.environment == 'stable'}}"
if [[ "${{ needs.information.outputs.environment }}" == "stable" ]]; then
sed -i 's/version:.*/version: "${{ needs.information.outputs.version }}"/g' hass-addon-sunsynk-multi/config.yaml
fi
# Stage and commit changes
git add hass-addon-sunsynk-edge/config.yaml hass-addon-sunsynk-multi/config.yaml
git commit -m "Update addon version to ${{ needs.information.outputs.version }} [no ci]" || echo "No changes to commit"
- name: Push changes
run: |
sed -i 's/version:.*/version: "${{ needs.information.outputs.version }}"/g' hass-addon-sunsynk-multi/config.yaml
- uses: stefanzweifel/git-auto-commit-action@v5
with:
branch: main
commit_user_email: [email protected]
commit_message: Update addon version to ${{ needs.information.outputs.version }} [no ci]
# Try to push changes
for i in {1..3}; do
if git push origin main; then
echo "Successfully pushed changes"
exit 0
else
echo "Push failed, attempting to rebase and retry..."
git pull --rebase origin main
fi
echo "Waiting 5 seconds before next push attempt..."
sleep 5
done
echo "Failed to push after 3 attempts"
exit 1

0 comments on commit 02f085f

Please sign in to comment.