From 3e49906e97a82842f01fca6965baf7a7984c9338 Mon Sep 17 00:00:00 2001 From: Jonathan Rampersad Date: Fri, 30 May 2025 14:40:57 -0400 Subject: [PATCH] Pull image before creating container --- .gitea/workflows/publish-registry.yml | 46 +++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/publish-registry.yml b/.gitea/workflows/publish-registry.yml index 73dd0f8..e88c083 100644 --- a/.gitea/workflows/publish-registry.yml +++ b/.gitea/workflows/publish-registry.yml @@ -50,7 +50,8 @@ jobs: PORTAINER_URL: ${{ secrets.PORTAINER_URL }} PORTAINER_API_KEY: ${{ secrets.PORTAINER_API_KEY }} PORTAINER_ENVIRONMENT_ID: ${{ secrets.PORTAINER_ENVIRONMENT_ID }} - IMAGE_TO_DEPLOY: ${{ vars.REGISTRY_URL }}${{ gitea.repository }}:latest + IMAGE_TO_DEPLOY: ${{ vars.REGISTRY_URL }}/${{ gitea.repository }}:latest + IMAGE_NAME: ${{ gitea.repository }}:latest CONTAINER_NAME: ${{ vars.PORTAINER_CONTAINER_NAME || 'deep-research' }} # Name of the container in Portainer HOST_PORT: "8005" # Host port to map to container's 3000 CONTAINER_PORT: "3000" # Container port @@ -65,9 +66,48 @@ jobs: set -e # Exit immediately if a command exits with a non-zero status. echo "Starting deployment of image ${{ env.IMAGE_TO_DEPLOY }} as container ${{ env.CONTAINER_NAME }}" - PORTAINER_API_DOCKER_BASE="${{ env.PORTAINER_URL }}/api/endpoints/${{ env.PORTAINER_ENVIRONMENT_ID }}/docker" + PORTAINER_API_BASE="${{ env.PORTAINER_URL }}/api/endpoints/${{ env.PORTAINER_ENVIRONMENT_ID }}" + PORTAINER_API_DOCKER_BASE="${PORTAINER_API_BASE}/docker" AUTH_HEADER="X-API-Key: ${{ env.PORTAINER_API_KEY }}" + # 0. Explicitly pull the image using Portainer's configured registry credentials + echo "Attempting to pull image '${{ env.IMAGE_TO_DEPLOY }}' via Portainer..." + IMAGE_FULL_NAME_FOR_PULL="${{ env.IMAGE_TO_DEPLOY }}" + # Extract image name (everything before the last colon) and tag (everything after the last colon) + IMAGE_NAME_NO_TAG_FOR_PULL=$(echo "$IMAGE_FULL_NAME_FOR_PULL" | sed -n 's/\(.*\):\([^:]*\)/\1/p') + IMAGE_TAG_FOR_PULL=$(echo "$IMAGE_FULL_NAME_FOR_PULL" | sed -n 's/\(.*\):\([^:]*\)/\2/p') + + # If sed didn't find a tag (e.g., image name had no colon, or only one part like 'imagename'), assume 'latest' + if [ -z "$IMAGE_TAG_FOR_PULL" ] || [ "$IMAGE_NAME_NO_TAG_FOR_PULL" == "" ]; then + IMAGE_TAG_FOR_PULL="latest" + IMAGE_NAME_NO_TAG_FOR_PULL="$IMAGE_FULL_NAME_FOR_PULL" # Assume full name was without tag if parsing failed + if echo "$IMAGE_NAME_NO_TAG_FOR_PULL" | grep -q ':'; then # If it still contains ':', it's likely it was just 'image:tag' and parsing failed above + IMAGE_NAME_NO_TAG_FOR_PULL=$(echo "$IMAGE_FULL_NAME_FOR_PULL" | cut -d: -f1) # fallback for simple 'image:tag' + fi + fi + + echo "Pulling image name: '$IMAGE_NAME_NO_TAG_FOR_PULL' with tag: '$IMAGE_TAG_FOR_PULL'" + + HTTP_CODE_PULL=$(curl ${{ env.CURL_OPTS }} -w "%{http_code}" -o /tmp/portainer_pull_response.txt -X POST \ + -H "$AUTH_HEADER" \ + "${PORTAINER_API_BASE}/images/create?fromImage=${IMAGE_NAME_NO_TAG_FOR_PULL}&tag=${IMAGE_TAG_FOR_PULL}") + PULL_RESPONSE_BODY=$(cat /tmp/portainer_pull_response.txt) + + if [ "$HTTP_CODE_PULL" -eq 200 ]; then + echo "Image pull initiated successfully by Portainer (HTTP 200)." + echo "Portainer pull response (first 10 lines):"; head -n 10 /tmp/portainer_pull_response.txt + echo "Waiting 60 seconds for image pull to complete..." + sleep 60 + elif [ "$HTTP_CODE_PULL" -eq 401 ] || [ "$HTTP_CODE_PULL" -eq 403 ] || [ "$HTTP_CODE_PULL" -eq 500 ]; then + echo "Error during image pull (HTTP $HTTP_CODE_PULL). This strongly indicates an AUTHENTICATION FAILURE with the Gitea registry via Portainer." + echo "Please RE-VERIFY the credentials (username/token and its permissions) for '${{ vars.REGISTRY_URL }}' in Portainer's Registries section." + echo "Response body: $PULL_RESPONSE_BODY"; exit 1 + elif [ "$HTTP_CODE_PULL" -eq 404 ]; then + echo "Error during image pull (HTTP $HTTP_CODE_PULL). Image '${IMAGE_NAME_NO_TAG_FOR_PULL}:${IMAGE_TAG_FOR_PULL}' not found in the Gitea registry."; echo "Response body: $PULL_RESPONSE_BODY"; exit 1 + else + echo "Error initiating image pull. Portainer responded with HTTP code: $HTTP_CODE_PULL"; echo "Response body: $PULL_RESPONSE_BODY"; exit 1 + fi + # 1. Find existing container by name echo "Searching for existing container named '${{ env.CONTAINER_NAME }}'..." # Portainer API often prepends '/' to container names in the .Names field. @@ -94,7 +134,7 @@ jobs: echo "Creating new container '${{ env.CONTAINER_NAME }}' with image '${{ env.IMAGE_TO_DEPLOY }}'..." CREATE_PAYLOAD=$(cat <