Fix crypto package loading and enhance CI with release action #3
This file contains hidden or 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
| name: Release | |
| on: | |
| workflow_dispatch: | |
| push: | |
| branches: [main] | |
| paths: | |
| - '.github/workflows/docker-build.yml' | |
| - 'Dockerfile' | |
| - 'compose.yml' | |
| - 'package.json' | |
| - 'package-lock.json' | |
| - 'tsconfig.json' | |
| - 'src/**' | |
| - '.env.example' | |
| pull_request: | |
| branches: [main] | |
| paths: | |
| - 'Dockerfile' | |
| - 'compose.yml' | |
| - 'package.json' | |
| - 'package-lock.json' | |
| - 'tsconfig.json' | |
| - 'src/**' | |
| - '.env.example' | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| # Human‑readable description used for OCI annotations / GHCR package description | |
| IMAGE_DESCRIPTION: > | |
| CinePro Core is the central scraping and streaming engine of the CinePro | |
| ecosystem. It exposes an OMSS-compliant HTTP API for resolving movie and TV | |
| show streams from multiple providers. | |
| concurrency: | |
| group: docker-build-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| prepare: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| run_date: ${{ steps.meta.outputs.run_date }} | |
| app_version: ${{ steps.meta.outputs.app_version }} | |
| arch_tag_amd64: ${{ steps.meta.outputs.arch_tag_amd64 }} | |
| arch_tag_arm64: ${{ steps.meta.outputs.arch_tag_arm64 }} | |
| steps: | |
| - id: meta | |
| run: | | |
| RUN_DATE="$(date +%Y%m%d)" | |
| APP_VERSION="main-${RUN_DATE}-${{ github.run_number }}" | |
| { | |
| echo "run_date=${RUN_DATE}" | |
| echo "app_version=${APP_VERSION}" | |
| echo "arch_tag_amd64=${APP_VERSION}-amd64" | |
| echo "arch_tag_arm64=${APP_VERSION}-arm64" | |
| } >> "$GITHUB_OUTPUT" | |
| build-amd64: | |
| runs-on: ubuntu-latest | |
| needs: [prepare] | |
| permissions: | |
| contents: read | |
| packages: write | |
| outputs: | |
| digest: ${{ steps.build-push.outputs.digest }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set lowercase image name | |
| run: echo "IMAGE_NAME_LC=${GITHUB_REPOSITORY,,}" >> "$GITHUB_ENV" | |
| - uses: docker/setup-buildx-action@v3 | |
| - uses: docker/login-action@v3 | |
| if: github.event_name != 'pull_request' | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build test image | |
| run: docker buildx build --load -t cinepro-core:test . | |
| - name: Test Docker image | |
| run: | | |
| docker run -d --name cinepro-core-test \ | |
| -p 3000:3000 \ | |
| -e NODE_ENV=production \ | |
| -e HOST=0.0.0.0 \ | |
| -e PORT=3000 \ | |
| -e CACHE_TYPE=memory \ | |
| -e TMDB_API_KEY=dummy-ci-key \ | |
| cinepro-core:test | |
| sleep 10 | |
| docker logs cinepro-core-test | |
| curl -sf http://localhost:3000 || true | |
| - name: Cleanup test container | |
| if: always() | |
| run: docker rm -f cinepro-core-test || true | |
| - name: Build and push Docker image (amd64) | |
| id: build-push | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| platforms: linux/amd64 | |
| push: ${{ github.event_name != 'pull_request' }} | |
| provenance: false | |
| sbom: false | |
| tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:${{ needs.prepare.outputs.arch_tag_amd64 }} | |
| cache-from: type=gha,scope=amd64 | |
| cache-to: type=gha,mode=max,scope=amd64 | |
| build-arm64: | |
| runs-on: ubuntu-24.04-arm | |
| needs: [prepare] | |
| permissions: | |
| contents: read | |
| packages: write | |
| outputs: | |
| digest: ${{ steps.build-push.outputs.digest }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set lowercase image name | |
| run: echo "IMAGE_NAME_LC=${GITHUB_REPOSITORY,,}" >> "$GITHUB_ENV" | |
| - uses: docker/setup-buildx-action@v3 | |
| - uses: docker/login-action@v3 | |
| if: github.event_name != 'pull_request' | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build and push Docker image (arm64) | |
| id: build-push | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| platforms: linux/arm64 | |
| push: ${{ github.event_name != 'pull_request' }} | |
| provenance: false | |
| sbom: false | |
| tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:${{ needs.prepare.outputs.arch_tag_arm64 }} | |
| cache-from: type=gha,scope=arm64 | |
| cache-to: type=gha,mode=max,scope=arm64 | |
| manifest: | |
| runs-on: ubuntu-latest | |
| needs: [prepare, build-amd64, build-arm64] | |
| if: github.event_name != 'pull_request' | |
| permissions: | |
| contents: write # needed so softprops can create the release (and tag) | |
| packages: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set lowercase image name | |
| run: echo "IMAGE_NAME_LC=${GITHUB_REPOSITORY,,}" >> "$GITHUB_ENV" | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - uses: docker/setup-buildx-action@v3 | |
| - name: Create and push multi-arch manifests with description | |
| run: | | |
| IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}" | |
| AMD64_IMAGE="$IMAGE:${{ needs.prepare.outputs.arch_tag_amd64 }}" | |
| ARM64_IMAGE="$IMAGE:${{ needs.prepare.outputs.arch_tag_arm64 }}" | |
| DESC="${IMAGE_DESCRIPTION}" | |
| # Versioned tag | |
| docker buildx imagetools create \ | |
| --annotation "index:org.opencontainers.image.description=${DESC}" \ | |
| -t "$IMAGE:${{ needs.prepare.outputs.app_version }}" \ | |
| "$AMD64_IMAGE" "$ARM64_IMAGE" | |
| # Moving tags | |
| docker buildx imagetools create \ | |
| --annotation "index:org.opencontainers.image.description=${DESC}" \ | |
| -t "$IMAGE:main" \ | |
| "$AMD64_IMAGE" "$ARM64_IMAGE" | |
| docker buildx imagetools create \ | |
| --annotation "index:org.opencontainers.image.description=${DESC}" \ | |
| -t "$IMAGE:latest" \ | |
| "$AMD64_IMAGE" "$ARM64_IMAGE" | |
| # --- New: categorized release notes without using git tags as triggers --- | |
| - name: Generate categorized release notes | |
| id: release_notes | |
| run: | | |
| CURRENT_TAG="${{ needs.prepare.outputs.app_version }}" | |
| echo "Generating release notes for $CURRENT_TAG" | |
| # Last 50 commits on the current branch | |
| HASHES=$(git log --pretty=format:"%H" -n 50) | |
| FEATURES="" | |
| FIXES="" | |
| DOCS="" | |
| CHORES="" | |
| BREAKING="" | |
| OTHERS="" | |
| while read -r hash; do | |
| message=$(git log --format=%s -n 1 "$hash") | |
| short_hash=$(git log --format=%h -n 1 "$hash") | |
| message=$(echo "$message" | xargs) | |
| short_hash=$(echo "$short_hash" | xargs) | |
| echo "Processing: '$message' ($short_hash)" | |
| clean_message="$message" | |
| if [[ "$message" =~ ^[a-z]+: ]]; then | |
| clean_message="${message#*: }" | |
| fi | |
| case "$message" in | |
| feat:*|feat\(*|feature:*) | |
| FEATURES="${FEATURES}- feat: [${clean_message}](https://github.com/${{ github.repository }}/commit/${short_hash})\\n" | |
| ;; | |
| fix:*|fix\(*) | |
| FIXES="${FIXES}- fix: [${clean_message}](https://github.com/${{ github.repository }}/commit/${short_hash})\\n" | |
| ;; | |
| docs:*|docs\(*) | |
| DOCS="${DOCS}- docs: [${clean_message}](https://github.com/${{ github.repository }}/commit/${short_hash})\\n" | |
| ;; | |
| chore:*|chore\(*|ci:*|ci\(*|build:*|build\(*) | |
| CHORES="${CHORES}- chore: [${clean_message}](https://github.com/${{ github.repository }}/commit/${short_hash})\\n" | |
| ;; | |
| *BREAKING*|*breaking*|*!:*) | |
| BREAKING="${BREAKING}- breaking change: [${message}](https://github.com/${{ github.repository }}/commit/${short_hash})\\n" | |
| ;; | |
| *) | |
| OTHERS="${OTHERS}- [${message}](https://github.com/${{ github.repository }}/commit/${short_hash})\\n" | |
| ;; | |
| esac | |
| done <<< "$HASHES" | |
| NOTES="## Release $CURRENT_TAG"$'\\n\\n' | |
| if [ -n "$BREAKING" ]; then | |
| NOTES="${NOTES}### ⚠️ Breaking Changes"$'\\n'"$(echo -e "$BREAKING")"$'\\n' | |
| fi | |
| if [ -n "$FEATURES" ]; then | |
| NOTES="${NOTES}### ✨ Features"$'\\n'"$(echo -e "$FEATURES")"$'\\n' | |
| fi | |
| if [ -n "$FIXES" ]; then | |
| NOTES="${NOTES}### 🐛 Bug Fixes"$'\\n'"$(echo -e "$FIXES")"$'\\n' | |
| fi | |
| if [ -n "$DOCS" ]; then | |
| NOTES="${NOTES}### 📚 Documentation"$'\\n'"$(echo -e "$DOCS")"$'\\n' | |
| fi | |
| if [ -n "$CHORES" ]; then | |
| NOTES="${NOTES}### 🔧 Maintenance"$'\\n'"$(echo -e "$CHORES")"$'\\n' | |
| fi | |
| if [ -n "$OTHERS" ]; then | |
| NOTES="${NOTES}### 📦 Other Changes"$'\\n'"$(echo -e "$OTHERS")"$'\\n' | |
| fi | |
| # Append your Docker image info + quick start | |
| NOTES="${NOTES}"$'\\n'"## Docker images"$'\\n\\n' | |
| NOTES="${NOTES}The following multi-arch images (linux/amd64, linux/arm64) were published to GitHub Container Registry:"$'\\n\\n' | |
| NOTES="${NOTES}- ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:${{ needs.prepare.outputs.app_version }}"$'\\n' | |
| NOTES="${NOTES}- ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:main"$'\\n' | |
| NOTES="${NOTES}- ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:latest"$'\\n\\n' | |
| NOTES="${NOTES}## Quick start"$'\\n\\n' | |
| NOTES="${NOTES}Pull the latest image:"$'\\n\\n' | |
| NOTES="${NOTES}\`\`\`bash"$'\\n' | |
| NOTES="${NOTES}docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:latest"$'\\n' | |
| NOTES="${NOTES}\`\`\`"$'\\n\\n' | |
| NOTES="${NOTES}Run the API locally (example):"$'\\n\\n' | |
| NOTES="${NOTES}\`\`\`bash"$'\\n' | |
| NOTES="${NOTES}docker run -p 3000:3000 \\"$'\\n' | |
| NOTES="${NOTES} -e TMDB_API_KEY=your-tmdb-key \\"$'\\n' | |
| NOTES="${NOTES} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}:latest"$'\\n' | |
| NOTES="${NOTES}\`\`\`"$'\\n' | |
| { | |
| echo "notes<<EOF" | |
| echo "$NOTES" | |
| echo "EOF" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2.5.0 | |
| with: | |
| name: Release ${{ needs.prepare.outputs.app_version }} | |
| body: ${{ steps.release_notes.outputs.notes }} | |
| draft: false | |
| generate_release_notes: false | |
| tag_name: ${{ needs.prepare.outputs.app_version }} | |
| prerelease: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |