Skip to content

Build RetroDECK Components #459

Build RetroDECK Components

Build RetroDECK Components #459

name: "Build RetroDECK Components"
on:
push:
branches:
- cooker
pull_request:
types: [opened, synchronize, reopened]
workflow_dispatch:
schedule:
- cron: '00 17 * * *' # 2:00 AM JST (JST is UTC+9, so 17:00 UTC)
permissions:
contents: write
pull-requests: write
jobs:
setup-recipes:
runs-on: ubuntu-latest
if: (github.event_name != 'schedule' || github.ref == 'refs/heads/update/components')
outputs:
heavy-matrix: ${{ steps.set-matrix.outputs.heavy }}
light-matrix: ${{ steps.set-matrix.outputs.light }}
steps:
- uses: actions/checkout@v4
- name: Assignign recipes to different runners
id: set-matrix
run: |
heavy=()
light=()
for recipe in */recipe.sh; do
if grep -q "flatpak_id_CULO" "$recipe"; then #TODO: we might not need this anymore
heavy+=("$recipe")
else
light+=("$recipe")
fi
done
heavy_json=$(printf '%s\n' "${heavy[@]}" | jq -R . | jq -s -c .)
light_json=$(printf '%s\n' "${light[@]}" | jq -R . | jq -s -c .)
echo "heavy=$heavy_json" >> $GITHUB_OUTPUT
echo "light=$light_json" >> $GITHUB_OUTPUT
build-light:
needs: setup-recipes
runs-on: ubuntu-latest
if: github.event_name != 'schedule' || github.ref == 'refs/heads/update/components'
strategy:
matrix:
recipe: ${{ fromJson(needs.setup-recipes.outputs.light-matrix) }}
fail-fast: false
continue-on-error: true
steps:
- uses: actions/checkout@v4
# Remove Stuck Mounts
- name: Remove stuck mounts
run: |
if [ -d "/home/ubuntu/actions-runner/_work/RetroDECK/RetroDECK/.flatpak-builder/rofiles" ]; then sudo umount -f /home/ubuntu/actions-runner/_work/RetroDECK/RetroDECK/.flatpak-builder/rofiles/*; fi
if [ -d "$HOME/actions-run/_work/RetroDECK/RetroDECK/.flatpak-builder/rofiles" ]; then sudo umount -f $HOME/actions-run/_work/RetroDECK/RetroDECK/.flatpak-builder/rofiles/*; fi
# Install Dependencies
- name: Install dependencies
run: curl "https://raw.githubusercontent.com/RetroDECK/components-template/main/automation_tools/install_dependencies.sh" | bash
# Clone Repository (pull_request_target)
- name: Clone Target Branch
if: github.event_name == 'pull_request_target'
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.base.ref }}
submodules: true
# Clone Repository (normal)
- name: Clone Components repo
if: github.event_name != 'pull_request_target'
uses: actions/checkout@v4
with:
submodules: true
# Merge PR for validation
- name: Merge and Validate PR Code
if: github.event_name == 'pull_request_target'
run: |
echo "Fetching PR..."
git fetch origin pull/${{ github.event.pull_request.number }}/head:pr
git merge --no-ff pr || {
echo "Merge conflict detected.";
exit 1;
}
git log -1 --oneline
# Run Build
- name: Run Build Artifacts
run: |
source automation-tools/utils.sh
artifact_name=$(basename $(dirname "${{ matrix.recipe }}"))
echo "artifact_name=$artifact_name" >> $GITHUB_ENV
bash "${{ matrix.recipe }}"
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ env.artifact_name }}
path: ${{ env.artifact_name }}/artifacts/*
build-heavy:
needs: setup-recipes
runs-on: retrodeck
if: (github.event_name != 'schedule' || github.ref == 'refs/heads/update/components') && fromJSON(needs.setup-recipes.outputs.heavy-matrix).length > 0
strategy:
matrix:
recipe: ${{ fromJson(needs.setup-recipes.outputs.heavy-matrix) }}
fail-fast: false
continue-on-error: true
steps:
- uses: actions/checkout@v4
# Remove Stuck Mounts
- name: Remove stuck mounts
run: |
if [ -d "/home/ubuntu/actions-runner/_work/RetroDECK/RetroDECK/.flatpak-builder/rofiles" ]; then sudo umount -f /home/ubuntu/actions-runner/_work/RetroDECK/RetroDECK/.flatpak-builder/rofiles/*; fi
if [ -d "$HOME/actions-run/_work/RetroDECK/RetroDECK/.flatpak-builder/rofiles" ]; then sudo umount -f $HOME/actions-run/_work/RetroDECK/RetroDECK/.flatpak-builder/rofiles/*; fi
# Clone Repository (pull_request_target)
- name: Clone Target Branch
if: github.event_name == 'pull_request_target'
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.base.ref }}
submodules: true
# Clone Repository (normal)
- name: Clone Components repo
if: github.event_name != 'pull_request_target'
uses: actions/checkout@v4
with:
submodules: true
# Merge PR for validation
- name: Merge and Validate PR Code
if: github.event_name == 'pull_request_target'
run: |
echo "Fetching PR..."
git fetch origin pull/${{ github.event.pull_request.number }}/head:pr
git merge --no-ff pr || {
echo "Merge conflict detected.";
exit 1;
}
git log -1 --oneline
# Run Build
- name: Run Build Artifacts
run: |
source automation-tools/utils.sh
artifact_name=$(basename $(dirname "${{ matrix.recipe }}"))
echo "artifact_name=$artifact_name" >> $GITHUB_ENV
bash "${{ matrix.recipe }}"
Release_RetroDECK_Components:
needs: [build-light, build-heavy]
runs-on: ubuntu-latest
if: always() && (github.event_name != 'schedule' || github.ref == 'refs/heads/update/components')
continue-on-error: true
steps:
# Clone Repository (pull_request_target)
- name: Clone Target Branch
if: github.event_name == 'pull_request_target'
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.base.ref }}
submodules: true
# Clone Repository (normal)
- name: Clone Components repo
if: github.event_name != 'pull_request_target'
uses: actions/checkout@v4
with:
submodules: true
- name: Download All Artifacts
uses: actions/download-artifact@v4
with:
path: downloaded-artifacts
- name: Move Downloaded Artifacts
run: |
for dir in downloaded-artifacts/*; do
if [ -d "$dir" ]; then
component_name=$(basename "$dir")
mkdir -p "$component_name/artifacts"
mv -v "$dir"/* "$component_name/artifacts/"
fi
done
- name: Generate components_version.md
run: |
source automation-tools/utils.sh
write_components_version
echo "Components version file generated."
cat components_version.md
- name: Generate a token for Rekku
id: generate-rekku-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.REKKU_APP_ID }}
private-key: ${{ secrets.REKKU_PRIVATE_KEY }}
repositories: "components"
owner: "RetroDECK"
- name: Get Branch Name
run: |
if [[ "$GITHUB_EVENT_NAME" == "pull_request" || "$GITHUB_EVENT_NAME" == "pull_request_target" ]]; then
branch_name="$GITHUB_HEAD_REF"
else
branch_name="$GITHUB_REF_NAME"
fi
echo "Branch name: $branch_name"
echo "BRANCH_NAME=$branch_name" >> $GITHUB_ENV
- name: Get commits since last published main release
id: get-commits
run: |
# If this is a Pull Request
if [[ "$GITHUB_EVENT_NAME" == "pull_request" ]]; then
echo "[INFO] Pull Request detected."
BASE_REF=${GITHUB_BASE_REF}
echo "[INFO] Base ref: $BASE_REF"
git fetch origin $BASE_REF
git log origin/$BASE_REF..HEAD --pretty=format:"- %s" > commits_list.txt
cp commits_list.txt commits_since_main.txt
else
# Get the latest published release tag
LATEST_TAG=$(git describe --tags $(git rev-list --tags --max-count=1) 2>/dev/null || echo "")
if [ -z "$LATEST_TAG" ]; then
echo "[INFO] No previous tag found."
echo "- No previous release." > commits_list.txt
else
echo "[INFO] Latest tag: $LATEST_TAG"
git log ${LATEST_TAG}..HEAD --pretty=format:"- %s" > commits_list.txt
fi
# Get the latest tag on the main branch
LATEST_MAIN_REF=$(git tag --merged origin/main --sort=-creatordate | head -n 1 || echo "")
if [ -z "$LATEST_MAIN_REF" ]; then
echo "[INFO] No tag found on main branch."
echo "- No main release found." > commits_since_main.txt
else
echo "[INFO] Latest tag on main: $LATEST_MAIN_REF"
git log ${LATEST_MAIN_REF}..HEAD --pretty=format:"- %s" > commits_since_main.txt
fi
fi
echo "COMMITS_FILE=commits_list.txt" >> $GITHUB_ENV
echo "COMMITS_MAIN_FILE=commits_since_main.txt" >> $GITHUB_ENV
- name: Generate release body text
id: generate-body
run: |
set -e
RELEASE_BODY_FILE="release_body.md"
echo "# Release Notes" > "$RELEASE_BODY_FILE"
echo "This is a RetroDECK Components Artifacts release from [this commit](https://github.com/${{ github.repository }}/commit/${{ github.sha }}), from branch [${{ env.BRANCH_NAME }}](https://github.com/RetroDECK/RetroDECK/tree/feat/${{ env.BRANCH_NAME }})." >> "$RELEASE_BODY_FILE"
echo "" >> "$RELEASE_BODY_FILE"
# Append the contents of components_version.md to the release body
cat components_version.md >> "$RELEASE_BODY_FILE"
echo "" >> "$RELEASE_BODY_FILE"
# Prepare array
MISSING_ARTIFACTS=()
# Iterate through folders in the repo root
for folder in $(find . -maxdepth 1 -mindepth 1 -type d -not -name '.*' -not -name 'automation-tools' -not -name 'downloaded-artifacts' -exec basename {} \;); do
if [ ! -d "$folder/artifacts" ] || ! find "$folder/artifacts" -maxdepth 1 -type f \( -name "*.tar.gz" -o -name "*.zip" -o -name "*.gz" -o -name "*.tar" -o -name "*.7z" -o -name "*.appimage" \) | grep -q .; then
MISSING_ARTIFACTS+=("$folder")
fi
done
# Add warnings for missing artifacts
if [ ${#MISSING_ARTIFACTS[@]} -ne 0 ]; then
echo "[WARNING] The following components are missing from this release:" >> "$RELEASE_BODY_FILE"
for folder in "${MISSING_ARTIFACTS[@]}"; do
echo "- $folder" >> "$RELEASE_BODY_FILE"
done
else
echo "No missing components detected!" >> "$RELEASE_BODY_FILE"
fi
echo "" >> "$RELEASE_BODY_FILE"
# Fetch latest main to compare against
git fetch origin main
# Build comparison link
COMPARE_URL="https://github.com/${{ github.repository }}/compare/main...${{ github.sha }}"
echo "" >> "$RELEASE_BODY_FILE"
echo "---" >> "$RELEASE_BODY_FILE"
echo "" >> "$RELEASE_BODY_FILE"
echo "[Check changes since latest main release](${COMPARE_URL})" >> "$RELEASE_BODY_FILE"
echo "" >> "$RELEASE_BODY_FILE"
# Output the final body
echo "RELEASE_BODY<<EOF" >> $GITHUB_OUTPUT
cat "$RELEASE_BODY_FILE" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Set Make Latest
run: |
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
MAKE_LATEST=true
else
MAKE_LATEST=false
fi
echo "MAKE_LATEST=$MAKE_LATEST" >> $GITHUB_ENV
- name: Generate Version Tag
id: version-tag
run: |
# Get the current date and time in GMT
CURRENT_DATE=$(date -u +"%Y%m%d-%H%M")
# Check if the branch is main or not
if [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then
TAG="${CURRENT_DATE}"
else
TAG="cooker-${CURRENT_DATE}"
fi
echo "TAG=$TAG" >> $GITHUB_ENV
echo "TAG=$TAG" >> $GITHUB_OUTPUT
- name: Publish release
uses: ncipollo/release-action@v1
with:
tag: "${{ env.TAG }}"
name: "RetroDECK Components ${{ env.TAG }}"
body: ${{ steps.generate-body.outputs.RELEASE_BODY }}
artifacts: "*/artifacts/*,!*/artifacts/version,components_version.md"
allowUpdates: true
omitBodyDuringUpdate: true
makeLatest: ${{ env.MAKE_LATEST }}
repo: ${{ env.REPO_NAME }}
token: ${{ steps.generate-rekku-token.outputs.token }}
- name: Create diff between target branch and PR components_version.md
run: |
if [[ "${GITHUB_BASE_REF}" == "cooker" ]]; then
TARGET_BRANCH="main"
else
TARGET_BRANCH="cooker"
fi
git fetch origin $TARGET_BRANCH
if [ -f "components_version.md" ]; then
if git show origin/$TARGET_BRANCH:components_version.md > target_components_version.md 2>/dev/null; then
echo "Generating diff between $TARGET_BRANCH and PR components_version.md..."
diff -u target_components_version.md components_version.md > components_version_diff.txt || true
echo "Diff saved to components_version_diff.txt"
else
echo "components_version.md does not exist on $TARGET_BRANCH branch. Skipping diff."
echo "No components_version.md on $TARGET_BRANCH branch." > components_version_diff.txt
fi
else
echo "components_version.md not found in PR. Skipping diff."
echo "No components_version.md in PR." > components_version_diff.txt
fi
- name: Write PR body
if: github.event_name == 'pull_request_target' || github.event_name == 'pull_request' || github.event_name != 'schedule' || github.ref == 'refs/heads/update/components'
run: |
echo "## RetroDECK Components Artifacts" > pr_body.md
echo "" >> pr_body.md
echo "This pull request updates the RetroDECK components artifacts to version ${{ env.TAG }}." >> pr_body.md
echo "## Changes:" >> pr_body.md
echo "$(cat commits_list.txt)" >> pr_body.md
echo "" >> pr_body.md
echo "## Diff between main and PR components_version.md:" >> pr_body.md
echo "```diff" >> pr_body.md
echo "$(cat components_version_diff.txt)" >> pr_body.md
echo "```" >> pr_body.md
- name: Open Pull Request
uses: peter-evans/create-pull-request@v7
if: github.event_name != 'schedule' || github.ref == 'refs/heads/update/components' && github.head_ref != github.base_ref
with:
token: ${{ steps.generate-rekku-token.outputs.token }}
commit-message: "Update RetroDECK Components Artifacts"
branch: ${{ env.BRANCH_NAME }}
title: "Update RetroDECK Components Artifacts"
body-path: pr_body.md
base: "cooker"
- name: Post PR comment with artifacts
uses: marocchino/sticky-pull-request-comment@v2
if: github.event_name == 'pull_request_target' || github.event_name == 'pull_request' || github.event_name != 'schedule' || github.ref == 'refs/heads/update/components'
with:
GITHUB_TOKEN: ${{ steps.generate-rekku-token.outputs.token }}
header: "RetroDECK Build Artifacts"
path: pr_body.md
- name: Rewrite Tag
if: github.ref == 'refs/heads/main'
run: |
git submodule deinit -f --all
git fetch --tags
if git rev-parse --verify "${{ env.TAG }}" >/dev/null 2>&1; then
git tag -d "${{ env.TAG }}"
git push --delete origin "${{ env.TAG }}"
fi
git tag "${{ env.TAG }}"
git push origin "${{ env.TAG }}"
env:
GITHUB_TOKEN: ${{ steps.generate-rekku-token.outputs.token }}