|
| 1 | +name: docker-artifacts |
| 2 | + |
| 3 | +on: |
| 4 | + repository_dispatch: |
| 5 | + types: [docker-published] |
| 6 | + pull_request: |
| 7 | + paths: |
| 8 | + - '.github/workflows/docker-artifacts.yml' |
| 9 | + workflow_dispatch: |
| 10 | + inputs: |
| 11 | + version: |
| 12 | + description: 'Version to extract Docker artifacts for (e.g., v1.2.3 or 1.2.3)' |
| 13 | + required: true |
| 14 | + type: string |
| 15 | + |
| 16 | +permissions: |
| 17 | + contents: write |
| 18 | + |
| 19 | +jobs: |
| 20 | + extract-docker-artifacts: |
| 21 | + runs-on: ubuntu-latest |
| 22 | + strategy: |
| 23 | + matrix: |
| 24 | + platform: |
| 25 | + - name: ruby |
| 26 | + image: metanorma/metanorma:latest |
| 27 | + bundle_path: /usr/local/bundle/Gemfile.lock |
| 28 | + - name: ubuntu |
| 29 | + image: metanorma/metanorma:ubuntu-latest |
| 30 | + bundle_path: /usr/local/bundle/Gemfile.lock |
| 31 | + - name: alpine |
| 32 | + image: metanorma/metanorma:alpine-latest |
| 33 | + bundle_path: /usr/local/bundle/Gemfile.lock |
| 34 | + fail-fast: false |
| 35 | + |
| 36 | + steps: |
| 37 | + - name: Determine version |
| 38 | + id: version |
| 39 | + run: | |
| 40 | + if [ "${{ github.event_name }}" == "repository_dispatch" ]; then |
| 41 | + VERSION="${{ github.event.client_payload.version }}" |
| 42 | + elif [ "${{ github.event_name }}" == "workflow_dispatch" ]; then |
| 43 | + VERSION="${{ github.event.inputs.version }}" |
| 44 | + elif [ "${{ github.event_name }}" == "pull_request" ]; then |
| 45 | + # For PR testing, use a test version |
| 46 | + VERSION="v1.13.3" |
| 47 | + fi |
| 48 | +
|
| 49 | + # Normalize version (remove 'v' prefix if present) |
| 50 | + VERSION=${VERSION#v} |
| 51 | + echo "version=${VERSION}" >> $GITHUB_OUTPUT |
| 52 | + echo "tag=v${VERSION}" >> $GITHUB_OUTPUT |
| 53 | + echo "Extracting Docker artifacts for version: ${VERSION}" |
| 54 | +
|
| 55 | + - name: Extract Gemfile.lock from ${{ matrix.platform.name }} container |
| 56 | + id: extract |
| 57 | + run: | |
| 58 | + PLATFORM="${{ matrix.platform.name }}" |
| 59 | + VERSION="${{ steps.version.outputs.version }}" |
| 60 | +
|
| 61 | + # Try version-specific tag first, then fall back to latest |
| 62 | + IMAGE_TAG="${{ matrix.platform.image }}" |
| 63 | + if [ "$PLATFORM" = "ruby" ]; then |
| 64 | + # For ruby platform, try version-specific tag |
| 65 | + VERSIONED_IMAGE="metanorma/metanorma:${{ steps.version.outputs.tag }}" |
| 66 | + if docker pull "$VERSIONED_IMAGE" 2>/dev/null; then |
| 67 | + IMAGE_TAG="$VERSIONED_IMAGE" |
| 68 | + echo "Using versioned image: $IMAGE_TAG" |
| 69 | + else |
| 70 | + echo "Versioned image not found, using latest: $IMAGE_TAG" |
| 71 | + fi |
| 72 | + fi |
| 73 | +
|
| 74 | + echo "Pulling Docker image: $IMAGE_TAG" |
| 75 | + if docker pull "$IMAGE_TAG"; then |
| 76 | + echo "Successfully pulled $IMAGE_TAG" |
| 77 | +
|
| 78 | + # Extract Gemfile.lock |
| 79 | + LOCK_FILE="metanorma-cli-${VERSION}-docker-${PLATFORM}.lock" |
| 80 | + echo "Extracting Gemfile.lock to: $LOCK_FILE" |
| 81 | +
|
| 82 | + if docker run --rm "$IMAGE_TAG" cat "${{ matrix.platform.bundle_path }}" > "$LOCK_FILE"; then |
| 83 | + echo "Successfully extracted Gemfile.lock" |
| 84 | + echo "lock_file=$LOCK_FILE" >> $GITHUB_OUTPUT |
| 85 | + echo "success=true" >> $GITHUB_OUTPUT |
| 86 | +
|
| 87 | + # Verify the file is not empty and contains expected content |
| 88 | + if [ -s "$LOCK_FILE" ] && grep -q "GEM" "$LOCK_FILE"; then |
| 89 | + echo "Gemfile.lock validation passed" |
| 90 | + echo "First 10 lines of extracted Gemfile.lock:" |
| 91 | + head -10 "$LOCK_FILE" |
| 92 | + else |
| 93 | + echo "❌ Gemfile.lock validation failed - file is empty or invalid" |
| 94 | + echo "success=false" >> $GITHUB_OUTPUT |
| 95 | + fi |
| 96 | + else |
| 97 | + echo "❌ Failed to extract Gemfile.lock from container" |
| 98 | + echo "success=false" >> $GITHUB_OUTPUT |
| 99 | + fi |
| 100 | + else |
| 101 | + echo "❌ Failed to pull Docker image: $IMAGE_TAG" |
| 102 | + echo "success=false" >> $GITHUB_OUTPUT |
| 103 | + fi |
| 104 | +
|
| 105 | + - name: Generate checksum for ${{ matrix.platform.name }} |
| 106 | + if: steps.extract.outputs.success == 'true' |
| 107 | + run: | |
| 108 | + LOCK_FILE="${{ steps.extract.outputs.lock_file }}" |
| 109 | + sha256sum "$LOCK_FILE" > "${LOCK_FILE}.sha256" |
| 110 | + echo "Generated checksum for $LOCK_FILE:" |
| 111 | + cat "${LOCK_FILE}.sha256" |
| 112 | +
|
| 113 | + - name: Upload ${{ matrix.platform.name }} artifacts to release |
| 114 | + if: steps.extract.outputs.success == 'true' && github.event_name != 'pull_request' |
| 115 | + uses: softprops/action-gh-release@v2 |
| 116 | + with: |
| 117 | + tag_name: ${{ steps.version.outputs.tag }} |
| 118 | + files: | |
| 119 | + ${{ steps.extract.outputs.lock_file }} |
| 120 | + ${{ steps.extract.outputs.lock_file }}.sha256 |
| 121 | +
|
| 122 | + - name: Platform summary |
| 123 | + run: | |
| 124 | + if [ "${{ steps.extract.outputs.success }}" = "true" ]; then |
| 125 | + if [ "${{ github.event_name }}" = "pull_request" ]; then |
| 126 | + echo "🧪 ${{ matrix.platform.name }} platform artifacts built but not uploaded (PR mode)" |
| 127 | + else |
| 128 | + echo "✅ ${{ matrix.platform.name }} platform artifacts completed successfully!" |
| 129 | + echo "📦 Uploaded: ${{ steps.extract.outputs.lock_file }}" |
| 130 | + fi |
| 131 | + else |
| 132 | + echo "❌ ${{ matrix.platform.name }} platform artifacts failed" |
| 133 | + echo "This may be expected if the Docker image is not yet available" |
| 134 | + fi |
| 135 | +
|
| 136 | + extract-windows-artifacts: |
| 137 | + runs-on: windows-latest |
| 138 | + steps: |
| 139 | + - name: Determine version |
| 140 | + id: version |
| 141 | + run: | |
| 142 | + if ("${{ github.event_name }}" -eq "repository_dispatch") { |
| 143 | + $VERSION = "${{ github.event.client_payload.version }}" |
| 144 | + } elseif ("${{ github.event_name }}" -eq "workflow_dispatch") { |
| 145 | + $VERSION = "${{ github.event.inputs.version }}" |
| 146 | + } elseif ("${{ github.event_name }}" -eq "pull_request") { |
| 147 | + # For PR testing, use a test version |
| 148 | + $VERSION = "v1.13.3" |
| 149 | + } |
| 150 | +
|
| 151 | + # Normalize version (remove 'v' prefix if present) |
| 152 | + $VERSION = $VERSION -replace '^v', '' |
| 153 | + echo "version=$VERSION" >> $env:GITHUB_OUTPUT |
| 154 | + echo "tag=v$VERSION" >> $env:GITHUB_OUTPUT |
| 155 | + echo "Extracting Windows Docker artifacts for version: $VERSION" |
| 156 | +
|
| 157 | + - name: Extract Gemfile.lock from Windows container |
| 158 | + id: extract |
| 159 | + run: | |
| 160 | + $VERSION = "${{ steps.version.outputs.version }}" |
| 161 | + $IMAGE_TAG = "metanorma/metanorma:windows-ltsc2022" |
| 162 | +
|
| 163 | + Write-Host "Pulling Windows Docker image: $IMAGE_TAG" |
| 164 | + try { |
| 165 | + docker pull $IMAGE_TAG |
| 166 | + Write-Host "Successfully pulled $IMAGE_TAG" |
| 167 | +
|
| 168 | + # Extract Gemfile.lock |
| 169 | + $LOCK_FILE = "metanorma-cli-$VERSION-docker-windows.lock" |
| 170 | + Write-Host "Extracting Gemfile.lock to: $LOCK_FILE" |
| 171 | +
|
| 172 | + # Try multiple possible locations for Gemfile.lock |
| 173 | + $POSSIBLE_PATHS = @( |
| 174 | + "C:\metanorma\Gemfile.lock", |
| 175 | + "C:\setup\Gemfile.lock", |
| 176 | + "C:\usr\local\bundle\Gemfile.lock" |
| 177 | + ) |
| 178 | +
|
| 179 | + $SUCCESS = $false |
| 180 | + foreach ($PATH in $POSSIBLE_PATHS) { |
| 181 | + Write-Host "Trying path: $PATH" |
| 182 | + try { |
| 183 | + docker run --rm $IMAGE_TAG cmd /c "type `"$PATH`"" | Out-File -FilePath $LOCK_FILE -Encoding UTF8 |
| 184 | + if (Test-Path $LOCK_FILE -PathType Leaf) { |
| 185 | + $content = Get-Content $LOCK_FILE -Raw |
| 186 | + if ($content -and $content.Contains("GEM")) { |
| 187 | + Write-Host "✅ Successfully extracted Gemfile.lock from: $PATH" |
| 188 | + $SUCCESS = $true |
| 189 | + break |
| 190 | + } |
| 191 | + } |
| 192 | + } catch { |
| 193 | + Write-Host "❌ Failed to extract from: $PATH" |
| 194 | + } |
| 195 | + } |
| 196 | +
|
| 197 | + if (-not $SUCCESS) { |
| 198 | + Write-Host "❌ Could not find Gemfile.lock in any expected location" |
| 199 | + # List directory contents to help debug |
| 200 | + Write-Host "Listing C:\ contents recursively:" |
| 201 | + docker run --rm $IMAGE_TAG cmd /c "dir C:\ /s /b | findstr /i gemfile" |
| 202 | + Write-Host "Searching for all Gemfile.lock files:" |
| 203 | + docker run --rm $IMAGE_TAG cmd /c "dir C:\*.lock /s /b" |
| 204 | + Write-Host "Searching for all Gemfile files:" |
| 205 | + docker run --rm $IMAGE_TAG cmd /c "dir C:\*Gemfile* /s /b" |
| 206 | + Write-Host "Listing C:\metanorma contents:" |
| 207 | + docker run --rm $IMAGE_TAG cmd /c "if exist C:\metanorma (dir C:\metanorma /b) else (echo Directory C:\metanorma does not exist)" |
| 208 | + Write-Host "Listing C:\setup contents:" |
| 209 | + docker run --rm $IMAGE_TAG cmd /c "if exist C:\setup (dir C:\setup /b) else (echo Directory C:\setup does not exist)" |
| 210 | + } |
| 211 | +
|
| 212 | + if (Test-Path $LOCK_FILE -PathType Leaf) { |
| 213 | + $content = Get-Content $LOCK_FILE -Raw |
| 214 | + if ($content -and $content.Contains("GEM")) { |
| 215 | + Write-Host "Successfully extracted and validated Gemfile.lock" |
| 216 | + echo "lock_file=$LOCK_FILE" >> $env:GITHUB_OUTPUT |
| 217 | + echo "success=true" >> $env:GITHUB_OUTPUT |
| 218 | +
|
| 219 | + Write-Host "First 10 lines of extracted Gemfile.lock:" |
| 220 | + Get-Content $LOCK_FILE | Select-Object -First 10 |
| 221 | + } else { |
| 222 | + Write-Host "❌ Gemfile.lock validation failed - file is empty or invalid" |
| 223 | + echo "success=false" >> $env:GITHUB_OUTPUT |
| 224 | + } |
| 225 | + } else { |
| 226 | + Write-Host "❌ Failed to extract Gemfile.lock from container" |
| 227 | + echo "success=false" >> $env:GITHUB_OUTPUT |
| 228 | + } |
| 229 | + } catch { |
| 230 | + Write-Host "❌ Failed to pull or extract from Windows Docker image: $_" |
| 231 | + echo "success=false" >> $env:GITHUB_OUTPUT |
| 232 | + } |
| 233 | +
|
| 234 | + - name: Generate checksum for Windows |
| 235 | + if: steps.extract.outputs.success == 'true' |
| 236 | + run: | |
| 237 | + $LOCK_FILE = "${{ steps.extract.outputs.lock_file }}" |
| 238 | + $hash = Get-FileHash -Path $LOCK_FILE -Algorithm SHA256 |
| 239 | + "$($hash.Hash.ToLower()) $LOCK_FILE" | Out-File -FilePath "$LOCK_FILE.sha256" -Encoding ASCII |
| 240 | + Write-Host "Generated checksum for $LOCK_FILE:" |
| 241 | + Get-Content "$LOCK_FILE.sha256" |
| 242 | +
|
| 243 | + - name: Upload Windows artifacts to release |
| 244 | + if: steps.extract.outputs.success == 'true' && github.event_name != 'pull_request' |
| 245 | + uses: softprops/action-gh-release@v2 |
| 246 | + with: |
| 247 | + tag_name: ${{ steps.version.outputs.tag }} |
| 248 | + files: | |
| 249 | + ${{ steps.extract.outputs.lock_file }} |
| 250 | + ${{ steps.extract.outputs.lock_file }}.sha256 |
| 251 | +
|
| 252 | + - name: Windows summary |
| 253 | + run: | |
| 254 | + if ("${{ steps.extract.outputs.success }}" -eq "true") { |
| 255 | + if ("${{ github.event_name }}" -eq "pull_request") { |
| 256 | + Write-Host "🧪 Windows platform artifacts built but not uploaded (PR mode)" |
| 257 | + } else { |
| 258 | + Write-Host "✅ Windows platform artifacts completed successfully!" |
| 259 | + Write-Host "📦 Uploaded: ${{ steps.extract.outputs.lock_file }}" |
| 260 | + } |
| 261 | + } else { |
| 262 | + Write-Host "❌ Windows platform artifacts failed" |
| 263 | + Write-Host "This may be expected if the Windows Docker image is not yet available" |
| 264 | + } |
| 265 | +
|
| 266 | + summary: |
| 267 | + runs-on: ubuntu-latest |
| 268 | + needs: [extract-docker-artifacts, extract-windows-artifacts] |
| 269 | + if: always() |
| 270 | + steps: |
| 271 | + - name: Determine version |
| 272 | + id: version |
| 273 | + run: | |
| 274 | + if [ "${{ github.event_name }}" == "repository_dispatch" ]; then |
| 275 | + VERSION="${{ github.event.client_payload.version }}" |
| 276 | + elif [ "${{ github.event_name }}" == "workflow_dispatch" ]; then |
| 277 | + VERSION="${{ github.event.inputs.version }}" |
| 278 | + elif [ "${{ github.event_name }}" == "pull_request" ]; then |
| 279 | + # For PR testing, use a test version |
| 280 | + VERSION="v1.13.3" |
| 281 | + fi |
| 282 | +
|
| 283 | + # Normalize version (remove 'v' prefix if present) |
| 284 | + VERSION=${VERSION#v} |
| 285 | + echo "tag=v${VERSION}" >> $GITHUB_OUTPUT |
| 286 | +
|
| 287 | + - name: Final summary |
| 288 | + run: | |
| 289 | + echo "🐳 Docker artifacts extraction completed for version: ${{ steps.version.outputs.tag }}" |
| 290 | + echo "🔗 Check the release at: https://github.com/metanorma/metanorma-cli/releases/tag/${{ steps.version.outputs.tag }}" |
| 291 | + echo "" |
| 292 | + echo "Expected artifacts:" |
| 293 | + echo " • metanorma-cli-*-docker-ruby.lock" |
| 294 | + echo " • metanorma-cli-*-docker-ubuntu.lock" |
| 295 | + echo " • metanorma-cli-*-docker-alpine.lock" |
| 296 | + echo " • metanorma-cli-*-docker-windows.lock" |
| 297 | + echo " • SHA256 checksums for all lock files" |
| 298 | + echo "" |
| 299 | + echo "Note: Some artifacts may be missing if corresponding Docker images are not yet available." |
0 commit comments