-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathaction.yml
More file actions
316 lines (278 loc) · 15 KB
/
action.yml
File metadata and controls
316 lines (278 loc) · 15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# ------------------------------------------------------------------------------------
# Cache Redis Image Composite Action (GoFortress)
#
# Purpose: Cache Redis Docker images to accelerate service container startup.
# Provides intelligent caching similar to Go module and build caching, pinned to
# Redis version for proper cache invalidation.
#
# Features:
# - Docker image caching using actions/cache
# - Version-pinned cache keys tied to REDIS_VERSION
# - Cross-platform image caching support
# - Performance tracking and metrics
# - Automatic fallback to Docker Hub on cache miss
# - Cache compression for storage efficiency
#
# Usage:
# - uses: ./.github/actions/cache-redis-image
# with:
# redis-version: ${{ env.REDIS_VERSION }}
# runner-os: ${{ runner.os }}
# cache-mode: "restore-save" # restore, save, restore-save
#
# Maintainer: @mrz1836
#
# ------------------------------------------------------------------------------------
name: "Cache Redis Image"
description: "Cache Redis Docker images for faster service container startup with version-pinned keys"
inputs:
redis-version:
description: "Redis Docker image version (e.g., 7-alpine, 6-alpine)"
required: true
runner-os:
description: "Operating system for cache keys (e.g., Linux, macOS)"
required: true
cache-mode:
description: "Cache operation mode: restore, save, restore-save"
required: false
default: "restore-save"
force-pull:
description: "Force pull image even if cache exists (for cache warming)"
required: false
default: "false"
outputs:
cache-hit:
description: "Whether Redis image was restored from cache (true/false)"
value: ${{ steps.restore-redis-image.outputs.cache-hit }}
image-size:
description: "Size of Redis image in MB"
value: ${{ steps.image-info.outputs.image-size }}
operation-time:
description: "Total operation time in seconds"
value: ${{ steps.operation-summary.outputs.operation-time }}
cache-key:
description: "Cache key used for Redis image"
value: ${{ steps.cache-config.outputs.cache-key }}
image-available:
description: "Whether Redis image is available locally (true/false)"
value: ${{ steps.image-verification.outputs.image-available }}
runs:
using: "composite"
steps:
# ————————————————————————————————————————————————————————————————
# Initialize operation tracking
# ————————————————————————————————————————————————————————————————
- name: ⏱️ Initialize operation tracking
id: operation-start
shell: bash
run: |
echo "🗄️ Starting Redis image caching operation..."
OPERATION_START=$(date +%s)
echo "operation-start=$OPERATION_START" >> $GITHUB_OUTPUT
echo "📋 Configuration:"
echo " • Redis Version: ${{ inputs.redis-version }}"
echo " • Runner OS: ${{ inputs.runner-os }}"
echo " • Cache Mode: ${{ inputs.cache-mode }}"
echo " • Force Pull: ${{ inputs.force-pull }}"
echo ""
# ————————————————————————————————————————————————————————————————
# Configure cache settings and keys
# ————————————————————————————————————————————————————————————————
- name: 🔧 Configure cache settings
id: cache-config
shell: bash
run: |
echo "🔧 Configuring Redis image cache settings..."
# Generate cache key pinned to Redis version and OS
REDIS_VERSION="${{ inputs.redis-version }}"
RUNNER_OS="${{ inputs.runner-os }}"
# Normalize Redis version for cache key (remove special characters)
NORMALIZED_VERSION=$(echo "$REDIS_VERSION" | sed 's/[^a-zA-Z0-9.-]/_/g')
# Create cache key
CACHE_KEY="redis-image-${RUNNER_OS}-${NORMALIZED_VERSION}"
# Define cache paths
CACHE_DIR="$HOME/.cache/redis-images"
IMAGE_TAR="redis-${NORMALIZED_VERSION}.tar"
CACHE_PATH="${CACHE_DIR}/${IMAGE_TAR}"
echo "📋 Cache Configuration:"
echo " • Cache Key: $CACHE_KEY"
echo " • Cache Directory: $CACHE_DIR"
echo " • Image Tar: $IMAGE_TAR"
echo " • Cache Path: $CACHE_PATH"
# Create cache directory
mkdir -p "$CACHE_DIR"
# Set outputs
echo "cache-key=$CACHE_KEY" >> $GITHUB_OUTPUT
echo "cache-dir=$CACHE_DIR" >> $GITHUB_OUTPUT
echo "image-tar=$IMAGE_TAR" >> $GITHUB_OUTPUT
echo "cache-path=$CACHE_PATH" >> $GITHUB_OUTPUT
echo "normalized-version=$NORMALIZED_VERSION" >> $GITHUB_OUTPUT
# ————————————————————————————————————————————————————————————————
# Restore Redis image from cache
# ————————————————————————————————————————————————————————————————
- name: 💾 Restore Redis image from cache
if: contains(inputs.cache-mode, 'restore')
id: restore-redis-image
uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: ${{ steps.cache-config.outputs.cache-path }}
key: ${{ steps.cache-config.outputs.cache-key }}
# ————————————————————————————————————————————————————————————————
# Load cached Redis image into Docker
# ————————————————————————————————————————————————————————————————
- name: 📦 Load cached Redis image
if: contains(inputs.cache-mode, 'restore') && steps.restore-redis-image.outputs.cache-hit == 'true' && inputs.force-pull != 'true'
id: load-cached-image
shell: bash
run: |
echo "📦 Loading Redis image from cache..."
CACHE_PATH="${{ steps.cache-config.outputs.cache-path }}"
if [ -f "$CACHE_PATH" ]; then
echo "✅ Cache file found: $CACHE_PATH"
# Load image from tar file
if docker load < "$CACHE_PATH"; then
echo "✅ Redis image loaded successfully from cache"
echo "image-loaded=true" >> $GITHUB_OUTPUT
else
echo "❌ Failed to load Redis image from cache"
echo "image-loaded=false" >> $GITHUB_OUTPUT
exit 1
fi
else
echo "❌ Cache file not found: $CACHE_PATH"
echo "image-loaded=false" >> $GITHUB_OUTPUT
exit 1
fi
# ————————————————————————————————————————————————————————————————
# Pull Redis image if not cached or force-pull enabled
# ————————————————————————————————————————————————————————————————
- name: 📥 Pull Redis image from Docker Hub
if: (contains(inputs.cache-mode, 'restore') && steps.restore-redis-image.outputs.cache-hit != 'true') || inputs.force-pull == 'true'
id: pull-redis-image
shell: bash
run: |
echo "📥 Pulling Redis image from Docker Hub..."
REDIS_IMAGE="redis:${{ inputs.redis-version }}"
echo "🔍 Pulling image: $REDIS_IMAGE"
# Pull the image with progress
if docker pull "$REDIS_IMAGE"; then
echo "✅ Redis image pulled successfully: $REDIS_IMAGE"
echo "image-pulled=true" >> $GITHUB_OUTPUT
else
echo "❌ Failed to pull Redis image: $REDIS_IMAGE"
echo "image-pulled=false" >> $GITHUB_OUTPUT
exit 1
fi
# ————————————————————————————————————————————————————————————————
# Save Redis image to cache
# ————————————————————————————————————————————————————————————————
- name: 💾 Save Redis image to cache
if: contains(inputs.cache-mode, 'save') && (steps.pull-redis-image.outputs.image-pulled == 'true' || inputs.force-pull == 'true')
id: save-redis-image
shell: bash
run: |
echo "💾 Saving Redis image to cache..."
REDIS_IMAGE="redis:${{ inputs.redis-version }}"
CACHE_PATH="${{ steps.cache-config.outputs.cache-path }}"
echo "🔍 Saving image: $REDIS_IMAGE"
echo "📁 Cache path: $CACHE_PATH"
# Save image as tar file
if docker save "$REDIS_IMAGE" | gzip > "$CACHE_PATH"; then
echo "✅ Redis image saved to cache successfully"
# Get file size
if [ -f "$CACHE_PATH" ]; then
FILE_SIZE_BYTES=$(stat -c%s "$CACHE_PATH" 2>/dev/null || stat -f%z "$CACHE_PATH" 2>/dev/null || echo "0")
FILE_SIZE_MB=$((FILE_SIZE_BYTES / 1024 / 1024))
echo "📊 Cache file size: ${FILE_SIZE_MB}MB"
echo "cache-size-mb=$FILE_SIZE_MB" >> $GITHUB_OUTPUT
fi
echo "image-saved=true" >> $GITHUB_OUTPUT
else
echo "❌ Failed to save Redis image to cache"
echo "image-saved=false" >> $GITHUB_OUTPUT
exit 1
fi
# ————————————————————————————————————————————————————————————————
# Save cache using actions/cache
# ————————————————————————————————————————————————————————————————
- name: 🗄️ Save Redis image cache
if: contains(inputs.cache-mode, 'save') && steps.save-redis-image.outputs.image-saved == 'true'
uses: actions/cache/save@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: ${{ steps.cache-config.outputs.cache-path }}
key: ${{ steps.cache-config.outputs.cache-key }}
# ————————————————————————————————————————————————————————————————
# Verify Redis image availability
# ————————————————————————————————————————————————————————————————
- name: 🔍 Verify Redis image availability
id: image-verification
shell: bash
run: |
echo "🔍 Verifying Redis image availability..."
REDIS_IMAGE="redis:${{ inputs.redis-version }}"
# Check if image exists locally
if docker image inspect "$REDIS_IMAGE" >/dev/null 2>&1; then
echo "✅ Redis image available locally: $REDIS_IMAGE"
echo "image-available=true" >> $GITHUB_OUTPUT
else
echo "❌ Redis image not available locally: $REDIS_IMAGE"
echo "image-available=false" >> $GITHUB_OUTPUT
exit 1
fi
# ————————————————————————————————————————————————————————————————
# Gather image information and metrics
# ————————————————————————————————————————————————————————————————
- name: 📊 Gather image information
id: image-info
shell: bash
run: |
echo "📊 Gathering Redis image information..."
REDIS_IMAGE="redis:${{ inputs.redis-version }}"
# Get image size
IMAGE_SIZE_BYTES=$(docker image inspect "$REDIS_IMAGE" --format='{{.Size}}' 2>/dev/null || echo "0")
IMAGE_SIZE_MB=$((IMAGE_SIZE_BYTES / 1024 / 1024))
# Get image ID and created date
IMAGE_ID=$(docker image inspect "$REDIS_IMAGE" --format='{{.Id}}' 2>/dev/null | cut -d: -f2 | head -c 12)
IMAGE_CREATED=$(docker image inspect "$REDIS_IMAGE" --format='{{.Created}}' 2>/dev/null || echo "unknown")
echo "📋 Image Information:"
echo " • Image: $REDIS_IMAGE"
echo " • Size: ${IMAGE_SIZE_MB}MB"
echo " • ID: $IMAGE_ID"
echo " • Created: $IMAGE_CREATED"
# Set outputs
echo "image-size=$IMAGE_SIZE_MB" >> $GITHUB_OUTPUT
echo "image-id=$IMAGE_ID" >> $GITHUB_OUTPUT
echo "image-created=$IMAGE_CREATED" >> $GITHUB_OUTPUT
# ————————————————————————————————————————————————————————————————
# Operation summary and timing
# ————————————————————————————————————————————————————————————————
- name: ✅ Operation summary
id: operation-summary
shell: bash
run: |
echo "✅ Redis image caching operation completed"
# Calculate operation time
OPERATION_START="${{ steps.operation-start.outputs.operation-start }}"
OPERATION_END=$(date +%s)
OPERATION_TIME=$((OPERATION_END - OPERATION_START))
# Determine cache status
CACHE_HIT="${{ steps.restore-redis-image.outputs.cache-hit || 'false' }}"
IMAGE_AVAILABLE="${{ steps.image-verification.outputs.image-available }}"
echo "📊 Operation Summary:"
echo " • Cache Hit: $CACHE_HIT"
echo " • Image Available: $IMAGE_AVAILABLE"
echo " • Operation Time: ${OPERATION_TIME}s"
echo " • Cache Key: ${{ steps.cache-config.outputs.cache-key }}"
# Set outputs
echo "operation-time=$OPERATION_TIME" >> $GITHUB_OUTPUT
echo "cache-hit-final=$CACHE_HIT" >> $GITHUB_OUTPUT
if [[ "$IMAGE_AVAILABLE" == "true" ]]; then
if [[ "$CACHE_HIT" == "true" ]]; then
echo "🚀 Redis image restored from cache in ${OPERATION_TIME}s"
else
echo "📥 Redis image pulled and cached in ${OPERATION_TIME}s"
fi
else
echo "❌ Redis image operation failed after ${OPERATION_TIME}s"
exit 1
fi