Skip to content

Build New Releases #819

Build New Releases

Build New Releases #819

# ============================================
# Build New Releases
# Automatically detects and builds new releases
# from cedya77/aiometadata every 6 hours
# Uses native ARM64 runners to avoid QEMU issues
# ============================================
name: Build New Releases
on:
schedule:
# Run every 6 hours
- cron: '0 */6 * * *'
workflow_dispatch:
inputs:
force_version:
description: 'Force build specific version (leave empty for auto-detect)'
required: false
default: ''
env:
REGISTRY: ghcr.io
IMAGE_NAME: jigsawfr/aiometadata-docker
SOURCE_REPO: cedya77/aiometadata
permissions:
contents: write
packages: write
id-token: write # For cosign OIDC
jobs:
# ============================================
# Job 1: Check for new releases
# ============================================
check-releases:
name: Check for New Releases
runs-on: ubuntu-latest
outputs:
has_new_stable: ${{ steps.check.outputs.has_new_stable }}
has_new_beta: ${{ steps.check.outputs.has_new_beta }}
stable_version: ${{ steps.check.outputs.stable_version }}
stable_sha: ${{ steps.check.outputs.stable_sha }}
stable_body: ${{ steps.check.outputs.stable_body }}
stable_date: ${{ steps.check.outputs.stable_date }}
beta_version: ${{ steps.check.outputs.beta_version }}
beta_sha: ${{ steps.check.outputs.beta_sha }}
beta_body: ${{ steps.check.outputs.beta_body }}
beta_date: ${{ steps.check.outputs.beta_date }}
steps:
- name: Check for new releases
id: check
uses: actions/github-script@v7
with:
script: |
// Force version override
const forceVersion = '${{ inputs.force_version }}';
if (forceVersion) {
console.log(`Force building version: ${forceVersion}`);
const isPrerelease = forceVersion.includes('beta') || forceVersion.includes('alpha');
try {
const { data: release } = await github.rest.repos.getReleaseByTag({
owner: 'cedya77',
repo: 'aiometadata',
tag: forceVersion.startsWith('v') ? forceVersion : `v${forceVersion}`
});
const version = release.tag_name.replace(/^v/, '');
if (isPrerelease) {
core.setOutput('has_new_beta', 'true');
core.setOutput('has_new_stable', 'false');
core.setOutput('beta_version', version);
core.setOutput('beta_sha', release.target_commitish);
core.setOutput('beta_body', release.body || '');
core.setOutput('beta_date', release.published_at);
} else {
core.setOutput('has_new_stable', 'true');
core.setOutput('has_new_beta', 'false');
core.setOutput('stable_version', version);
core.setOutput('stable_sha', release.target_commitish);
core.setOutput('stable_body', release.body || '');
core.setOutput('stable_date', release.published_at);
}
return;
} catch (e) {
console.log(`Release ${forceVersion} not found: ${e.message}`);
}
}
// Get all releases from source
const { data: releases } = await github.rest.repos.listReleases({
owner: 'cedya77',
repo: 'aiometadata',
per_page: 20
});
const latestStable = releases.find(r => !r.prerelease && !r.tag_name.includes('beta'));
const latestBeta = releases.find(r => r.prerelease || r.tag_name.includes('beta'));
// Check if images exist
const checkImageExists = async (version) => {
try {
const response = await fetch(
`https://ghcr.io/v2/jigsawfr/aiometadata-docker/manifests/${version}`,
{ method: 'HEAD' }
);
return response.ok;
} catch {
return false;
}
};
// Check stable
if (latestStable) {
const stableVersion = latestStable.tag_name.replace(/^v/, '');
const stableExists = await checkImageExists(stableVersion);
if (!stableExists) {
console.log(`New stable release found: ${stableVersion}`);
core.setOutput('has_new_stable', 'true');
core.setOutput('stable_version', stableVersion);
core.setOutput('stable_sha', latestStable.target_commitish);
core.setOutput('stable_body', latestStable.body || '');
core.setOutput('stable_date', latestStable.published_at);
} else {
console.log(`Stable release ${stableVersion} already exists`);
core.setOutput('has_new_stable', 'false');
}
} else {
core.setOutput('has_new_stable', 'false');
}
// Check beta
if (latestBeta) {
const betaVersion = latestBeta.tag_name.replace(/^v/, '');
const betaExists = await checkImageExists(betaVersion);
if (!betaExists) {
console.log(`New beta release found: ${betaVersion}`);
core.setOutput('has_new_beta', 'true');
core.setOutput('beta_version', betaVersion);
core.setOutput('beta_sha', latestBeta.target_commitish);
core.setOutput('beta_body', latestBeta.body || '');
core.setOutput('beta_date', latestBeta.published_at);
} else {
console.log(`Beta release ${betaVersion} already exists`);
core.setOutput('has_new_beta', 'false');
}
} else {
core.setOutput('has_new_beta', 'false');
}
# ============================================
# Job 2: Build stable per-arch (native runners)
# ============================================
build-stable-arch:
name: Build Stable ${{ matrix.arch }}
needs: check-releases
if: needs.check-releases.outputs.has_new_stable == 'true'
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
strategy:
fail-fast: false
matrix:
arch: [amd64, arm64]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and Push ${{ matrix.arch }} image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
platforms: linux/${{ matrix.arch }}
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.check-releases.outputs.stable_version }}-${{ matrix.arch }}
build-args: |
VERSION=${{ needs.check-releases.outputs.stable_version }}
BUILD_DATE=${{ needs.check-releases.outputs.stable_date }}
VCS_REF=${{ needs.check-releases.outputs.stable_sha }}
cache-from: type=gha,scope=stable-${{ matrix.arch }}
cache-to: type=gha,scope=stable-${{ matrix.arch }},mode=max
provenance: false
sbom: false
outputs: type=image,compression=zstd
# ============================================
# Job 3: Create stable manifest & sign
# ============================================
create-stable-manifest:
name: Stable Manifest
needs: [check-releases, build-stable-arch]
runs-on: ubuntu-latest
steps:
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version components
id: version
run: |
VERSION="${{ needs.check-releases.outputs.stable_version }}"
MAJOR=$(echo $VERSION | cut -d. -f1)
MINOR=$(echo $VERSION | cut -d. -f2)
echo "major=$MAJOR" >> $GITHUB_OUTPUT
echo "minor=$MINOR" >> $GITHUB_OUTPUT
echo "major_minor=${MAJOR}.${MINOR}" >> $GITHUB_OUTPUT
- name: Create multi-arch manifest
run: |
VERSION="${{ needs.check-releases.outputs.stable_version }}"
IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
echo "📦 Creating manifest for ${VERSION}..."
# Create and push version tag
docker manifest create ${IMAGE}:${VERSION} \
${IMAGE}:${VERSION}-amd64 \
${IMAGE}:${VERSION}-arm64
docker manifest push ${IMAGE}:${VERSION}
# Major.minor tag
docker manifest create ${IMAGE}:${{ steps.version.outputs.major_minor }} \
${IMAGE}:${VERSION}-amd64 \
${IMAGE}:${VERSION}-arm64
docker manifest push ${IMAGE}:${{ steps.version.outputs.major_minor }}
# Major tag
docker manifest create ${IMAGE}:${{ steps.version.outputs.major }} \
${IMAGE}:${VERSION}-amd64 \
${IMAGE}:${VERSION}-arm64
docker manifest push ${IMAGE}:${{ steps.version.outputs.major }}
# Latest tag
docker manifest create ${IMAGE}:latest \
${IMAGE}:${VERSION}-amd64 \
${IMAGE}:${VERSION}-arm64
docker manifest push ${IMAGE}:latest
echo "✅ All manifests pushed"
- name: Install Cosign
uses: sigstore/cosign-installer@v3
- name: Sign manifest
run: |
VERSION="${{ needs.check-releases.outputs.stable_version }}"
IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
# Get the manifest list digest (not individual arch digests)
DIGEST=$(docker buildx imagetools inspect --raw ${IMAGE}:${VERSION} | sha256sum | awk '{print "sha256:"$1}')
echo "🔐 Signing ${IMAGE}@${DIGEST}..."
cosign sign --yes ${IMAGE}@${DIGEST}
echo "✅ Signed successfully"
- name: Test container
continue-on-error: true
run: |
echo "🧪 Testing container..."
docker run -d --name redis-test -p 6379:6379 redis:alpine
sleep 5
docker run -d --name app-test \
--link redis-test:redis \
-p 1337:1337 \
-e REDIS_URL=redis://redis:6379 \
-e HOST_NAME=http://localhost:1337 \
-e DATABASE_URI=sqlite://./addon/data/addon.db \
-e TMDB_API=test \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.check-releases.outputs.stable_version }}
# Wait for container to be ready (non-blocking)
HEALTHY=false
for i in {1..30}; do
# Try multiple health endpoints
if curl -sf http://localhost:1337/health > /dev/null 2>&1 || \
curl -sf http://localhost:1337/api/cache/health > /dev/null 2>&1 || \
curl -sf http://localhost:1337/ > /dev/null 2>&1; then
echo "✅ Container is responding!"
HEALTHY=true
break
fi
echo "⏳ Waiting for container... ($i/30)"
sleep 5
done
if [ "$HEALTHY" != "true" ]; then
echo "⚠️ Container health check timed out (non-blocking)"
echo "📋 Container logs:"
docker logs app-test 2>&1 | tail -50
fi
docker stop app-test redis-test 2>/dev/null || true
docker rm app-test redis-test 2>/dev/null || true
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.check-releases.outputs.stable_version }}
name: v${{ needs.check-releases.outputs.stable_version }}
body: |
## 🐳 Docker Image
```bash
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.check-releases.outputs.stable_version }}
```
### Available Tags
- `${{ needs.check-releases.outputs.stable_version }}` - This version
- `${{ steps.version.outputs.major_minor }}` - Latest patch
- `${{ steps.version.outputs.major }}` - Latest for major
- `latest` - Latest stable
### Architectures
- `linux/amd64`
- `linux/arm64`
---
📦 **Source**: [cedya77/aiometadata v${{ needs.check-releases.outputs.stable_version }}](https://github.com/cedya77/aiometadata/releases/tag/v${{ needs.check-releases.outputs.stable_version }})
🔐 **Image signed with Cosign**
draft: false
prerelease: false
# ============================================
# Job 4: Build beta per-arch (native runners)
# ============================================
build-beta-arch:
name: Build Beta ${{ matrix.arch }}
needs: check-releases
if: needs.check-releases.outputs.has_new_beta == 'true'
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
strategy:
fail-fast: false
matrix:
arch: [amd64, arm64]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and Push ${{ matrix.arch }} image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
platforms: linux/${{ matrix.arch }}
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.check-releases.outputs.beta_version }}-${{ matrix.arch }}
build-args: |
VERSION=${{ needs.check-releases.outputs.beta_version }}
BUILD_DATE=${{ needs.check-releases.outputs.beta_date }}
VCS_REF=${{ needs.check-releases.outputs.beta_sha }}
cache-from: type=gha,scope=beta-${{ matrix.arch }}
cache-to: type=gha,scope=beta-${{ matrix.arch }},mode=max
provenance: false
sbom: false
outputs: type=image,compression=zstd
# ============================================
# Job 5: Create beta manifest & sign
# ============================================
create-beta-manifest:
name: Beta Manifest
needs: [check-releases, build-beta-arch]
runs-on: ubuntu-latest
steps:
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create multi-arch manifest
run: |
VERSION="${{ needs.check-releases.outputs.beta_version }}"
IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
echo "📦 Creating beta manifest for ${VERSION}..."
# Version tag
docker manifest create ${IMAGE}:${VERSION} \
${IMAGE}:${VERSION}-amd64 \
${IMAGE}:${VERSION}-arm64
docker manifest push ${IMAGE}:${VERSION}
# Beta tag
docker manifest create ${IMAGE}:beta \
${IMAGE}:${VERSION}-amd64 \
${IMAGE}:${VERSION}-arm64
docker manifest push ${IMAGE}:beta
echo "✅ Beta manifests pushed"
- name: Install Cosign
uses: sigstore/cosign-installer@v3
- name: Sign manifest
run: |
VERSION="${{ needs.check-releases.outputs.beta_version }}"
IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
# Get the manifest list digest (not individual arch digests)
DIGEST=$(docker buildx imagetools inspect --raw ${IMAGE}:${VERSION} | sha256sum | awk '{print "sha256:"$1}')
echo "🔐 Signing ${IMAGE}@${DIGEST}..."
cosign sign --yes ${IMAGE}@${DIGEST}
echo "✅ Signed successfully"
- name: Create GitHub Pre-Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.check-releases.outputs.beta_version }}
name: v${{ needs.check-releases.outputs.beta_version }} (Beta)
body: |
## ⚠️ Beta Release
This is a pre-release version and may contain bugs.
## 🐳 Docker Image
```bash
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.check-releases.outputs.beta_version }}
# or
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:beta
```
### Architectures
- `linux/amd64`
- `linux/arm64`
---
📦 **Source**: [cedya77/aiometadata v${{ needs.check-releases.outputs.beta_version }}](https://github.com/cedya77/aiometadata/releases/tag/v${{ needs.check-releases.outputs.beta_version }})
draft: false
prerelease: true