-
Notifications
You must be signed in to change notification settings - Fork 104
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* 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
1 parent
f75cb4c
commit 02f085f
Showing
1 changed file
with
156 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 }} | ||
|
@@ -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 | ||
|
@@ -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 | ||
|
@@ -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 |