diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml index c39b90e0..375d86a7 100644 --- a/.github/workflows/build-and-release.yml +++ b/.github/workflows/build-and-release.yml @@ -19,6 +19,8 @@ concurrency: env: RETENTION_INTERMEDIATE_ASSETS: 1 RETENTION_RELEASE_ASSETS: 30 + FLATPAK_REPOSITORY: MindWorkAI/Flatpak + FLATPAK_WORKFLOW: flatpak.yml jobs: determine_run_mode: @@ -165,6 +167,8 @@ jobs: formatted_build_time: ${{ steps.format_metadata.outputs.formatted_build_time }} changelog: ${{ steps.read_changelog.outputs.changelog }} version: ${{ steps.format_metadata.outputs.version }} + source_commit: ${{ steps.format_metadata.outputs.source_commit }} + pdfium_chromium_revision: ${{ steps.format_metadata.outputs.pdfium_chromium_revision }} steps: - name: Checkout repository @@ -176,6 +180,9 @@ jobs: # Read the first two lines of the metadata file: version=$(sed -n '1p' metadata.txt) build_time=$(sed -n '2p' metadata.txt) + pdfium_full_version=$(sed -n '11p' metadata.txt) + pdfium_chromium_revision=$(echo "$pdfium_full_version" | cut -d'.' -f3) + source_commit=$(git rev-parse HEAD) # Format the version: formatted_version="v${version}" @@ -186,12 +193,16 @@ jobs: # Log the formatted metadata: echo "Formatted version: '${formatted_version}'" echo "Formatted build time: '${formatted_build_time}'" + echo "Source commit: '${source_commit}'" + echo "PDFium Chromium revision: '${pdfium_chromium_revision}'" # Set the outputs: echo "formatted_version=${formatted_version}" >> "$GITHUB_OUTPUT" echo "FORMATTED_VERSION=${formatted_version}" >> $GITHUB_ENV echo "formatted_build_time=${formatted_build_time}" >> "$GITHUB_OUTPUT" echo "version=${version}" >> "$GITHUB_OUTPUT" + echo "source_commit=${source_commit}" >> "$GITHUB_OUTPUT" + echo "pdfium_chromium_revision=${pdfium_chromium_revision}" >> "$GITHUB_OUTPUT" - name: Check tag vs. metadata version if: startsWith(github.ref, 'refs/tags/v') @@ -224,6 +235,219 @@ jobs: echo "${changelog}" >> "$GITHUB_OUTPUT" echo "EOOOF" >> "$GITHUB_OUTPUT" + sync_flatpak_repo: + name: Sync Flatpak repo + runs-on: ubuntu-latest + needs: [determine_run_mode, read_metadata] + if: needs.determine_run_mode.outputs.is_release == 'true' + permissions: + contents: read + outputs: + flatpak_commit: ${{ steps.sync.outputs.flatpak_commit }} + + env: + GH_TOKEN: ${{ secrets.FLATPAK_WORKFLOW_TOKEN }} + AI_STUDIO_TAG: ${{ needs.read_metadata.outputs.formatted_version }} + AI_STUDIO_COMMIT: ${{ needs.read_metadata.outputs.source_commit }} + PDFIUM_CHROMIUM_REVISION: ${{ needs.read_metadata.outputs.pdfium_chromium_revision }} + + steps: + - name: Checkout Flatpak repository + uses: actions/checkout@v4 + with: + repository: ${{ env.FLATPAK_REPOSITORY }} + token: ${{ secrets.FLATPAK_WORKFLOW_TOKEN }} + ref: main + path: flatpak + fetch-depth: 0 + + - name: Install Flatpak sync tools + run: | + set -euo pipefail + + sudo curl -fsSL -o /usr/local/bin/yq https://github.com/mikefarah/yq/releases/download/v4.44.6/yq_linux_amd64 + sudo chmod +x /usr/local/bin/yq + + curl -LsSf https://astral.sh/uv/install.sh | sh + echo "$HOME/.local/bin" >> "$GITHUB_PATH" + "$HOME/.local/bin/uv" --version + yq --version + + - name: Update Flatpak release sources + working-directory: flatpak + env: + PDFIUM_X64_ARCHIVE: ${{ runner.temp }}/pdfium-linux-x64.tgz + PDFIUM_ARM64_ARCHIVE: ${{ runner.temp }}/pdfium-linux-arm64.tgz + run: | + set -euo pipefail + + pdfium_base_url="https://github.com/bblanchon/pdfium-binaries/releases/download/chromium%2F${PDFIUM_CHROMIUM_REVISION}" + pdfium_x64_url="${pdfium_base_url}/pdfium-linux-x64.tgz" + pdfium_arm64_url="${pdfium_base_url}/pdfium-linux-arm64.tgz" + + curl -fsSL -o "$PDFIUM_X64_ARCHIVE" "$pdfium_x64_url" + curl -fsSL -o "$PDFIUM_ARM64_ARCHIVE" "$pdfium_arm64_url" + + export PDFIUM_X64_URL="$pdfium_x64_url" + export PDFIUM_ARM64_URL="$pdfium_arm64_url" + export PDFIUM_X64_SHA256 + export PDFIUM_ARM64_SHA256 + PDFIUM_X64_SHA256=$(sha256sum "$PDFIUM_X64_ARCHIVE" | awk '{print $1}') + PDFIUM_ARM64_SHA256=$(sha256sum "$PDFIUM_ARM64_ARCHIVE" | awk '{print $1}') + + yq -i ' + (.modules[] | select(.name == "mind-work-ai-studio").sources[0].tag) = strenv(AI_STUDIO_TAG) | + (.modules[] | select(.name == "mind-work-ai-studio").sources[0].commit) = strenv(AI_STUDIO_COMMIT) | + (.modules[] | select(.name == "mind-work-ai-studio").sources[] | select(.type == "archive" and .only-arches[0] == "x86_64").url) = strenv(PDFIUM_X64_URL) | + (.modules[] | select(.name == "mind-work-ai-studio").sources[] | select(.type == "archive" and .only-arches[0] == "x86_64").sha256) = strenv(PDFIUM_X64_SHA256) | + (.modules[] | select(.name == "mind-work-ai-studio").sources[] | select(.type == "archive" and .only-arches[0] == "aarch64").url) = strenv(PDFIUM_ARM64_URL) | + (.modules[] | select(.name == "mind-work-ai-studio").sources[] | select(.type == "archive" and .only-arches[0] == "aarch64").sha256) = strenv(PDFIUM_ARM64_SHA256) + ' org.MindWorkAI.AIStudio.yml + + ./update-dependencies + git diff --stat + + - name: Commit and merge Flatpak sync + id: sync + working-directory: flatpak + run: | + set -euo pipefail + + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + branch="sync/ai-studio-${AI_STUDIO_TAG}" + git checkout -B "$branch" + git add org.MindWorkAI.AIStudio.yml cargo-sources.json dotnet-sources.json tauri-cli-sources.json + + if git diff --cached --quiet; then + echo "Flatpak repository is already synced for ${AI_STUDIO_TAG}." + flatpak_commit=$(git rev-parse origin/main) + echo "flatpak_commit=${flatpak_commit}" >> "$GITHUB_OUTPUT" + exit 0 + fi + + git commit -m "Sync AI Studio ${AI_STUDIO_TAG}" + + remote_branch_sha=$(git ls-remote --heads origin "$branch" | awk '{print $1}') + if [ -n "$remote_branch_sha" ]; then + git push --force-with-lease="refs/heads/${branch}:${remote_branch_sha}" origin "HEAD:${branch}" + else + git push origin "HEAD:${branch}" + fi + + pr_number=$(gh pr list \ + --repo "$FLATPAK_REPOSITORY" \ + --head "$branch" \ + --state open \ + --json number \ + --jq '.[0].number // empty') + + if [ -z "$pr_number" ]; then + pr_url=$(gh pr create \ + --repo "$FLATPAK_REPOSITORY" \ + --base main \ + --head "$branch" \ + --title "Sync AI Studio ${AI_STUDIO_TAG}" \ + --body "Synchronizes the Flatpak manifest and generated dependency sources for MindWork AI Studio ${AI_STUDIO_TAG}.") + pr_number="${pr_url##*/}" + fi + + for attempt in {1..30}; do + pr_state=$(gh pr view "$pr_number" --repo "$FLATPAK_REPOSITORY" --json mergeable,mergeStateStatus) + mergeable=$(echo "$pr_state" | jq -r '.mergeable') + merge_state_status=$(echo "$pr_state" | jq -r '.mergeStateStatus') + + echo "PR #${pr_number}: mergeable=${mergeable}, mergeStateStatus=${merge_state_status}" + + if [ "$mergeable" != "UNKNOWN" ]; then + break + fi + + sleep 5 + done + + gh pr merge "$pr_number" --repo "$FLATPAK_REPOSITORY" --merge --delete-branch + + flatpak_commit=$(gh api "repos/${FLATPAK_REPOSITORY}/commits/main" --jq .sha) + echo "flatpak_commit=${flatpak_commit}" >> "$GITHUB_OUTPUT" + + collect_flatpak_artifacts: + name: Collect Flatpak artifacts + runs-on: ubuntu-latest + needs: [determine_run_mode, read_metadata, sync_flatpak_repo] + if: needs.determine_run_mode.outputs.is_release == 'true' + permissions: + contents: read + + env: + GH_TOKEN: ${{ secrets.FLATPAK_WORKFLOW_TOKEN }} + FLATPAK_COMMIT: ${{ needs.sync_flatpak_repo.outputs.flatpak_commit }} + + steps: + - name: Wait for Flatpak main build + id: flatpak_run + run: | + set -euo pipefail + + run_id="" + + for attempt in {1..180}; do + run_json=$(gh run list \ + --repo "$FLATPAK_REPOSITORY" \ + --workflow "$FLATPAK_WORKFLOW" \ + --branch main \ + --commit "$FLATPAK_COMMIT" \ + --event push \ + --limit 1 \ + --json databaseId,status,conclusion,url,headSha) + + run_id=$(echo "$run_json" | jq -r '.[0].databaseId // empty') + + if [ -n "$run_id" ]; then + status=$(echo "$run_json" | jq -r '.[0].status') + conclusion=$(echo "$run_json" | jq -r '.[0].conclusion') + url=$(echo "$run_json" | jq -r '.[0].url') + + echo "Flatpak run ${run_id}: status=${status}, conclusion=${conclusion}, url=${url}" + + if [ "$status" = "completed" ]; then + if [ "$conclusion" != "success" ]; then + echo "Flatpak workflow failed with conclusion '${conclusion}'." + exit 1 + fi + + echo "run_id=${run_id}" >> "$GITHUB_OUTPUT" + exit 0 + fi + else + echo "Waiting for Flatpak workflow on commit ${FLATPAK_COMMIT}..." + fi + + sleep 20 + done + + echo "Timed out waiting for the Flatpak workflow on commit ${FLATPAK_COMMIT}." + exit 1 + + - name: Download Flatpak artifacts + env: + RUN_ID: ${{ steps.flatpak_run.outputs.run_id }} + run: | + set -euo pipefail + + mkdir -p flatpak-artifacts + gh run download "$RUN_ID" --repo "$FLATPAK_REPOSITORY" --dir flatpak-artifacts + find flatpak-artifacts -type f -name '*.flatpak' -print + + - name: Upload Flatpak artifacts + uses: actions/upload-artifact@v4 + with: + name: MindWork AI Studio Flatpak Release + path: flatpak-artifacts/**/*.flatpak + if-no-files-found: error + retention-days: ${{ env.RETENTION_INTERMEDIATE_ASSETS }} + build_main: name: Build app (${{ matrix.dotnet_runtime }}) needs: [determine_run_mode, read_metadata] @@ -789,7 +1013,7 @@ jobs: create_release: name: Prepare & create release runs-on: ubuntu-latest - needs: [build_main, read_metadata] + needs: [build_main, collect_flatpak_artifacts, read_metadata] if: startsWith(github.ref, 'refs/tags/v') permissions: {} steps: