diff options
Diffstat (limited to 'meshmc/.github/workflows')
| -rw-r--r-- | meshmc/.github/workflows/backport.yml | 30 | ||||
| -rw-r--r-- | meshmc/.github/workflows/blocked-prs.yml | 257 | ||||
| -rw-r--r-- | meshmc/.github/workflows/build.yml | 185 | ||||
| -rw-r--r-- | meshmc/.github/workflows/codeql.yml | 52 | ||||
| -rw-r--r-- | meshmc/.github/workflows/container.yml | 177 | ||||
| -rw-r--r-- | meshmc/.github/workflows/merge-blocking-pr.yml | 64 | ||||
| -rw-r--r-- | meshmc/.github/workflows/nix.yml | 138 | ||||
| -rw-r--r-- | meshmc/.github/workflows/publish.yml | 25 | ||||
| -rw-r--r-- | meshmc/.github/workflows/release.yml | 124 | ||||
| -rw-r--r-- | meshmc/.github/workflows/update-flake.yml | 35 |
10 files changed, 1087 insertions, 0 deletions
diff --git a/meshmc/.github/workflows/backport.yml b/meshmc/.github/workflows/backport.yml new file mode 100644 index 0000000000..0ca52b37cc --- /dev/null +++ b/meshmc/.github/workflows/backport.yml @@ -0,0 +1,30 @@ +name: Backport +on: + pull_request_target: + types: [closed, labeled] + +permissions: {} + +jobs: + backport: + permissions: + contents: write + pull-requests: write + actions: write + + name: Backport Pull Request + if: github.repository_owner == 'Project-Tick' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name)) + runs-on: ubuntu-slim + steps: + + - uses: actions/checkout@v6 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Create backport PRs + uses: korthout/backport-action@v4.3.0 + with: + # Config README: https://github.com/korthout/backport-action#backport-action + pull_description: |- + Bot-based backport to `${target_branch}`, triggered by a label in #${pull_number}. + diff --git a/meshmc/.github/workflows/blocked-prs.yml b/meshmc/.github/workflows/blocked-prs.yml new file mode 100644 index 0000000000..0010801540 --- /dev/null +++ b/meshmc/.github/workflows/blocked-prs.yml @@ -0,0 +1,257 @@ +name: Blocked/Stacked Pull Requests Automation + +on: + pull_request_target: + types: + - opened + - reopened + - edited + - synchronize + workflow_dispatch: + inputs: + pr_id: + description: Local Pull Request number to work on + required: true + type: number + +permissions: {} + +jobs: + blocked_status: + name: Check Blocked Status + runs-on: ubuntu-slim + + steps: + - name: Generate token + id: generate-token + uses: actions/create-github-app-token@v3 + with: + app-id: ${{ vars.PULL_REQUEST_APP_ID }} + private-key: ${{ secrets.PULL_REQUEST_APP_PRIVATE_KEY }} + + - name: Setup From Dispatch Event + if: github.event_name == 'workflow_dispatch' + id: dispatch_event_setup + env: + GH_TOKEN: ${{ steps.generate-token.outputs.token }} + PR_NUMBER: ${{ inputs.pr_id }} + run: | + # setup env for the rest of the workflow + OWNER=$(dirname "${{ github.repository }}") + REPO=$(basename "${{ github.repository }}") + PR_JSON=$( + gh api \ + -H "Accept: application/vnd.github.raw+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "/repos/$OWNER/$REPO/pulls/$PR_NUMBER" + ) + echo "PR_JSON=$PR_JSON" >> "$GITHUB_ENV" + + - name: Setup Environment + id: env_setup + env: + EVENT_PR_JSON: ${{ toJSON(github.event.pull_request) }} + run: | + # setup env for the rest of the workflow + PR_JSON=${PR_JSON:-"$EVENT_PR_JSON"} + { + echo "REPO=$(jq -r '.base.repo.name' <<< "$PR_JSON")" + echo "OWNER=$(jq -r '.base.repo.owner.login' <<< "$PR_JSON")" + echo "PR_NUMBER=$(jq -r '.number' <<< "$PR_JSON")" + echo "JOB_DATA=$(jq -c ' + { + "repo": .base.repo.name, + "owner": .base.repo.owner.login, + "repoUrl": .base.repo.html_url, + "prNumber": .number, + "prHeadSha": .head.sha, + "prHeadLabel": .head.label, + "prBody": (.body // ""), + "prLabels": (reduce .labels[].name as $l ([]; . + [$l])) + } + ' <<< "$PR_JSON")" + } >> "$GITHUB_ENV" + + + - name: Find Blocked/Stacked PRs in body + id: pr_ids + run: | + prs=$( + jq -c ' + .prBody as $body + | ( + $body | + reduce ( + . | scan("[Bb]locked (?:[Bb]y|[Oo]n):? #([0-9]+)") + | map({ + "type": "Blocked on", + "number": ( . | tonumber ) + }) + ) as $i ([]; . + [$i[]]) + ) as $bprs + | ( + $body | + reduce ( + . | scan("[Ss]tacked [Oo]n:? #([0-9]+)") + | map({ + "type": "Stacked on", + "number": ( . | tonumber ) + }) + ) as $i ([]; . + [$i[]]) + ) as $sprs + | ($bprs + $sprs) as $prs + | { + "blocking": $prs, + "numBlocking": ( $prs | length), + } + ' <<< "$JOB_DATA" + ) + echo "prs=$prs" >> "$GITHUB_OUTPUT" + + - name: Collect Blocked PR Data + id: blocking_data + if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0 + env: + GH_TOKEN: ${{ steps.generate-token.outputs.token }} + BLOCKING_PRS: ${{ steps.pr_ids.outputs.prs }} + run: | + blocked_pr_data=$( + while read -r pr_data ; do + gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "/repos/$OWNER/$REPO/pulls/$(jq -r '.number' <<< "$pr_data")" \ + | jq -c --arg type "$(jq -r '.type' <<< "$pr_data")" \ + ' + . | { + "type": $type, + "number": .number, + "merged": .merged, + "state": (if .state == "open" then "Open" elif .merged then "Merged" else "Closed" end), + "labels": (reduce .labels[].name as $l ([]; . + [$l])), + "basePrUrl": .html_url, + "baseRepoName": .head.repo.name, + "baseRepoOwner": .head.repo.owner.login, + "baseRepoUrl": .head.repo.html_url, + "baseSha": .head.sha, + "baseRefName": .head.ref, + } + ' + done < <(jq -c '.blocking[]' <<< "$BLOCKING_PRS") | jq -c -s + ) + { + echo "data=$blocked_pr_data"; + echo "all_merged=$(jq -r 'all(.[] | (.type == "Stacked on" and .merged) or (.type == "Blocked on" and (.state != "Open")); .)' <<< "$blocked_pr_data")"; + echo "current_blocking=$(jq -c 'map( + select( + (.type == "Stacked on" and (.merged | not)) or + (.type == "Blocked on" and (.state == "Open")) + ) | .number + )' <<< "$blocked_pr_data" )"; + } >> "$GITHUB_OUTPUT" + + - name: Add 'blocked' Label if Missing + id: label_blocked + if: "(fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0) && !contains(fromJSON(env.JOB_DATA).prLabels, 'status: blocked') && !fromJSON(steps.blocking_data.outputs.all_merged)" + continue-on-error: true + env: + GH_TOKEN: ${{ steps.generate-token.outputs.token }} + run: | + gh -R ${{ github.repository }} issue edit --add-label 'status: blocked' "$PR_NUMBER" + + - name: Remove 'blocked' Label if All Dependencies Are Merged + id: unlabel_blocked + if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0 && fromJSON(steps.blocking_data.outputs.all_merged) + continue-on-error: true + env: + GH_TOKEN: ${{ steps.generate-token.outputs.token }} + run: | + gh -R ${{ github.repository }} issue edit --remove-label 'status: blocked' "$PR_NUMBER" + + - name: Apply 'blocking' Label to Unmerged Dependencies + id: label_blocking + if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0 + continue-on-error: true + env: + GH_TOKEN: ${{ steps.generate-token.outputs.token }} + BLOCKING_ISSUES: ${{ steps.blocking_data.outputs.current_blocking }} + run: | + while read -r pr ; do + gh -R ${{ github.repository }} issue edit --add-label 'status: blocking' "$pr" || true + done < <(jq -c '.[]' <<< "$BLOCKING_ISSUES") + + - name: Apply Blocking PR Status Check + id: blocked_check + if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0 + continue-on-error: true + env: + GH_TOKEN: ${{ steps.generate-token.outputs.token }} + BLOCKING_DATA: ${{ steps.blocking_data.outputs.data }} + run: | + pr_head_sha=$(jq -r '.prHeadSha' <<< "$JOB_DATA") + # create commit Status, overwrites previous identical context + while read -r pr_data ; do + DESC=$( + jq -r 'if .type == "Stacked on" then + "Stacked PR #" + (.number | tostring) + " is " + (if .merged then "" else "not yet " end) + "merged" + else + "Blocking PR #" + (.number | tostring) + " is " + (if .state == "Open" then "" else "not yet " end) + "merged or closed" + end ' <<< "$pr_data" + ) + gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "/repos/${OWNER}/${REPO}/statuses/${pr_head_sha}" \ + -f "state=$(jq -r 'if (.type == "Stacked on" and .merged) or (.type == "Blocked on" and (.state != "Open")) then "success" else "failure" end' <<< "$pr_data")" \ + -f "target_url=$(jq -r '.basePrUrl' <<< "$pr_data" )" \ + -f "description=$DESC" \ + -f "context=ci/blocking-pr-check:$(jq '.number' <<< "$pr_data")" + done < <(jq -c '.[]' <<< "$BLOCKING_DATA") + + - name: Context Comment + id: generate-comment + if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0 + continue-on-error: true + env: + BLOCKING_DATA: ${{ steps.blocking_data.outputs.data }} + run: | + COMMENT_PATH="$(pwd)/temp_comment_file.txt" + echo '<h3>PR Dependencies :pushpin:</h3>' > "$COMMENT_PATH" + echo >> "$COMMENT_PATH" + pr_head_label=$(jq -r '.prHeadLabel' <<< "$JOB_DATA") + while read -r pr_data ; do + base_pr=$(jq -r '.number' <<< "$pr_data") + base_ref_name=$(jq -r '.baseRefName' <<< "$pr_data") + base_repo_owner=$(jq -r '.baseRepoOwner' <<< "$pr_data") + base_repo_name=$(jq -r '.baseRepoName' <<< "$pr_data") + compare_url="https://github.com/$base_repo_owner/$base_repo_name/compare/$base_ref_name...$pr_head_label" + status=$(jq -r ' + if .type == "Stacked on" then + if .merged then ":heavy_check_mark: Merged" else ":x: Not Merged (" + .state + ")" end + else + if .state != "Open" then ":white_check_mark: " + .state else ":x: Open" end + end + ' <<< "$pr_data") + type=$(jq -r '.type' <<< "$pr_data") + echo " - $type #$base_pr $status [(compare)]($compare_url)" >> "$COMMENT_PATH" + done < <(jq -c '.[]' <<< "$BLOCKING_DATA") + + { + echo 'body<<EOF'; + cat "${COMMENT_PATH}"; + echo 'EOF'; + } >> "$GITHUB_OUTPUT" + + - name: 💬 PR Comment + if: fromJSON(steps.pr_ids.outputs.prs).numBlocking > 0 + continue-on-error: true + env: + GH_TOKEN: ${{ steps.generate-token.outputs.token }} + COMMENT_BODY: ${{ steps.generate-comment.outputs.body }} + run: | + gh -R ${{ github.repository }} issue comment "$PR_NUMBER" \ + --body "$COMMENT_BODY" \ + --create-if-none \ + --edit-last + diff --git a/meshmc/.github/workflows/build.yml b/meshmc/.github/workflows/build.yml new file mode 100644 index 0000000000..0ed6240b41 --- /dev/null +++ b/meshmc/.github/workflows/build.yml @@ -0,0 +1,185 @@ +name: Build + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + push: + branches: + - 'master' + merge_group: + types: [checks_requested] + pull_request: + workflow_call: + inputs: + build-type: + description: Type of build (Debug or Release) + type: string + default: Debug + environment: + description: Deployment environment to run under + type: string + workflow_dispatch: + inputs: + build-type: + description: Type of build (Debug or Release) + type: string + default: Debug + +permissions: {} + +jobs: + build: + name: Build (${{ matrix.artifact-name }}) + + environment: ${{ inputs.environment || '' }} + + permissions: + contents: read + id-token: write + packages: write + + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-24.04 + artifact-name: Linux + cmake-preset: linux + qt-version: 6.10.2 + + - os: ubuntu-24.04-arm + artifact-name: Linux-aarch64 + cmake-preset: linux + qt-version: 6.10.2 + + - os: windows-2022 + artifact-name: Windows-MinGW-w64 + cmake-preset: windows_mingw + msystem: CLANG64 + vcvars-arch: amd64_x86 + + - os: windows-11-arm + artifact-name: Windows-MinGW-arm64 + cmake-preset: windows_mingw + msystem: CLANGARM64 + vcvars-arch: arm64 + + - os: windows-2022 + artifact-name: Windows-MSVC + cmake-preset: windows_msvc + # TODO(@YongDo-Hyun): This is the default in setup-dependencies/windows. Why isn't it working?!?! + vcvars-arch: amd64 + qt-version: 6.10.2 + + - os: windows-11-arm + artifact-name: Windows-MSVC-arm64 + cmake-preset: windows_msvc + vcvars-arch: arm64 + qt-version: 6.10.2 + + - os: macos-26 + artifact-name: macOS + cmake-preset: macos_universal + macosx-deployment-target: 12.0 + qt-version: 6.9.3 + + runs-on: ${{ matrix.os }} + + defaults: + run: + shell: ${{ matrix.msystem != '' && 'msys2 {0}' || 'bash' }} + + env: + ARTIFACT_NAME: ${{ matrix.artifact-name }}-Qt6 + BUILD_PLATFORM: official + BUILD_TYPE: ${{ inputs.build-type || 'Debug' }} + CMAKE_PRESET: ${{ matrix.cmake-preset }} + + MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx-deployment-target }} + + steps: + ## + # SETUP + ## + + - name: Checkout + uses: actions/checkout@v6 + with: + submodules: true + + - name: Setup dependencies + id: setup-dependencies + uses: ./.github/actions/setup-dependencies + with: + build-type: ${{ env.BUILD_TYPE }} + artifact-name: ${{ matrix.artifact-name }} + msystem: ${{ matrix.msystem }} + vcvars-arch: ${{ matrix.vcvars-arch }} + qt-version: ${{ matrix.qt-version }} + + ## + # BUILD + ## + + - name: Configure project + run: | + cmake --preset "$CMAKE_PRESET" + + - name: Run build + run: | + cmake --build --preset "$CMAKE_PRESET" --config "$BUILD_TYPE" + + - name: Run tests + run: | + ctest --preset "$CMAKE_PRESET" --build-config "$BUILD_TYPE" + + ## + # PACKAGE + ## + + - name: Get short version + id: short-version + shell: bash + run: | + echo "version=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" + + - name: Package (Linux) + if: ${{ runner.os == 'Linux' }} + uses: ./.github/actions/package/linux + with: + version: ${{ steps.short-version.outputs.version }} + build-type: ${{ steps.setup-dependencies.outputs.build-type }} + artifact-name: ${{ matrix.artifact-name }} + qt-version: ${{ steps.setup-dependencies.outputs.qt-version }} + + gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} + gpg-private-key-id: ${{ secrets.GPG_PRIVATE_KEY_ID }} + + - name: Package (macOS) + if: ${{ runner.os == 'macOS' }} + uses: ./.github/actions/package/macos + with: + version: ${{ steps.short-version.outputs.version }} + build-type: ${{ steps.setup-dependencies.outputs.build-type }} + artifact-name: ${{ matrix.artifact-name }} + + apple-codesign-cert: ${{ secrets.APPLE_CODESIGN_CERT }} + apple-codesign-password: ${{ secrets.APPLE_CODESIGN_PASSWORD }} + apple-codesign-id: ${{ secrets.APPLE_CODESIGN_ID }} + apple-notarize-apple-id: ${{ secrets.APPLE_NOTARIZE_APPLE_ID }} + apple-notarize-team-id: ${{ secrets.APPLE_NOTARIZE_TEAM_ID }} + apple-notarize-password: ${{ secrets.APPLE_NOTARIZE_PASSWORD }} + sparkle-ed25519-key: ${{ secrets.SPARKLE_ED25519_KEY }} + + - name: Package (Windows) + if: ${{ runner.os == 'Windows' }} + uses: ./.github/actions/package/windows + with: + version: ${{ steps.short-version.outputs.version }} + build-type: ${{ env.BUILD_TYPE }} + artifact-name: ${{ matrix.artifact-name }} + windows-codesign-cert: ${{ secrets.WINDOWS_CODESIGN_CERT }} + windows-codesign-password: ${{ secrets.WINDOWS_CODESIGN_PASSWORD }} + msystem: ${{ matrix.msystem }} diff --git a/meshmc/.github/workflows/codeql.yml b/meshmc/.github/workflows/codeql.yml new file mode 100644 index 0000000000..436ae07eef --- /dev/null +++ b/meshmc/.github/workflows/codeql.yml @@ -0,0 +1,52 @@ +name: "CodeQL Code Scanning" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + merge_group: + types: [checks_requested] + pull_request: + workflow_dispatch: + +permissions: {} + +jobs: + CodeQL: + runs-on: ubuntu-latest + + permissions: + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: "true" + + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + config-file: ./.github/codeql/codeql-config.yml + queries: security-and-quality + languages: cpp, java + + - name: Setup dependencies + uses: ./.github/actions/setup-dependencies + with: + build-type: Debug + qt-version: 6.9.3 + + - name: Configure and Build + run: | + cmake --preset linux -DLauncher_USE_PCH=OFF + cmake --build --preset linux --config Debug + + - name: Run tests + run: | + ctest --preset linux --build-config Debug --extra-verbose --output-on-failure + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 diff --git a/meshmc/.github/workflows/container.yml b/meshmc/.github/workflows/container.yml new file mode 100644 index 0000000000..762eff6c82 --- /dev/null +++ b/meshmc/.github/workflows/container.yml @@ -0,0 +1,177 @@ +name: Development Container + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + push: + branches: + - 'master' + merge_group: + types: [checks_requested] + pull_request: + workflow_dispatch: + +permissions: {} + +env: + REGISTRY: ghcr.io + +jobs: + build: + name: Build (${{ matrix.arch }}) + + permissions: + contents: read + packages: write + + outputs: + image-name: ${{ steps.image-name.outputs.image-name }} + + strategy: + fail-fast: false + matrix: + include: + - arch: arm64 + os: ubuntu-24.04-arm + - arch: amd64 + os: ubuntu-24.04-arm + + runs-on: ${{ matrix.os }} + + steps: + - name: Set image name + id: image-name + run: | + echo "image-name=${REGISTRY}/${GITHUB_REPOSITORY_OWNER,,}/devcontainer" >> "$GITHUB_OUTPUT" + + - name: Install Podman + uses: redhat-actions/podman-install@main + # TODO(@YongDo-Hyun): Always use this when the action properly supports ARM + if: ${{ runner.arch == 'X64' || runner.arch == 'X86' }} + with: + github-token: ${{ github.token }} + + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Determine metadata for image + id: image-metadata + uses: docker/metadata-action@v6 + with: + images: | + ${{ steps.image-name.outputs.image-name }} + flavor: | + latest=false + tags: | + type=raw,value=latest,enable=${{ github.event.merge_group.base_ref == 'refs/heads/develop' }} + + type=sha + type=sha,format=long + type=ref,event=branch + type=ref,event=tag + + - name: Build image + id: build-image + uses: redhat-actions/buildah-build@v2 + with: + containerfiles: | + ./Containerfile + tags: ${{ steps.image-metadata.outputs.tags }} + labels: ${{ steps.image-metadata.outputs.labels }} + + - name: Push image + id: push-image + if: ${{ github.event_name != 'pull_request' }} + uses: redhat-actions/push-to-registry@v2 + with: + tags: ${{ steps.build-image.outputs.tags }} + username: ${{ github.repository_owner }} + password: ${{ github.token }} + tls-verify: true + + - name: Export image digest + if: ${{ github.event_name != 'pull_request' }} + env: + DIGEST: ${{ steps.push-image.outputs.digest }} + run: | + mkdir -p "$RUNNER_TEMP"/digests + touch "$RUNNER_TEMP"/digests/"${DIGEST#sha256:}" + + - name: Upload digest artifact + if: ${{ github.event_name != 'pull_request' }} + uses: actions/upload-artifact@v7 + with: + name: digests-${{ matrix.arch }} + path: ${{ runner.temp }}/digests/* + if-no-files-found: error + retention-days: 1 + + manifest: + name: Create manifest + + needs: [ build ] + if: ${{ github.event_name != 'pull_request' }} + + permissions: + contents: read + packages: write + + runs-on: ubuntu-24.04 + + steps: + - name: Download digests + uses: actions/download-artifact@v8 + with: + path: ${{ runner.temp }}/digests + pattern: digests-* + merge-multiple: true + + - name: Install Podman + # TODO(@YongDo-Hyun): Always use this when the action properly supports ARM + if: ${{ runner.arch == 'X64' || runner.arch == 'X86' }} + uses: redhat-actions/podman-install@main + with: + github-token: ${{ github.token }} + + - name: Login to registry + uses: redhat-actions/podman-login@v1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.repository_owner }} + password: ${{ github.token }} + + - name: Determine metadata for manifest + id: manifest-metadata + uses: docker/metadata-action@v6 + with: + images: | + ${{ needs.build.outputs.image-name }} + flavor: | + latest=false + tags: | + type=raw,value=latest,enable=${{ github.event.merge_group.base_ref == 'refs/heads/develop' }} + + type=sha + type=sha,format=long + type=ref,event=branch + type=ref,event=tag + + - name: Create manifest list + working-directory: ${{ runner.temp }}/digests + env: + IMAGE_NAME: ${{ needs.build.outputs.image-name }} + run: | + while read -r tag; do + podman manifest create "$tag" \ + $(printf "$IMAGE_NAME@sha256:%s " *) + done <<< "$DOCKER_METADATA_OUTPUT_TAGS" + + - name: Push manifest + uses: redhat-actions/push-to-registry@v2 + with: + tags: ${{ steps.manifest-metadata.outputs.tags }} + username: ${{ github.repository_owner }} + password: ${{ github.token }} + tls-verify: true diff --git a/meshmc/.github/workflows/merge-blocking-pr.yml b/meshmc/.github/workflows/merge-blocking-pr.yml new file mode 100644 index 0000000000..3542a470e0 --- /dev/null +++ b/meshmc/.github/workflows/merge-blocking-pr.yml @@ -0,0 +1,64 @@ +name: Merged Blocking Pull Request Automation + +on: + pull_request_target: + types: + - closed + workflow_dispatch: + inputs: + pr_id: + description: Local Pull Request number to work on + required: true + type: number + +permissions: {} + +jobs: + update-blocked-status: + name: Update Blocked Status + runs-on: ubuntu-slim + + # a pr that was a `blocking:<id>` label was merged. + # find the open pr's it was blocked by and trigger a refresh of their state + if: "${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'status: blocking') }}" + + steps: + - name: Generate token + id: generate-token + uses: actions/create-github-app-token@v3 + with: + app-id: ${{ vars.PULL_REQUEST_APP_ID }} + private-key: ${{ secrets.PULL_REQUEST_APP_PRIVATE_KEY }} + + - name: Gather Dependent PRs + id: gather_deps + env: + GH_TOKEN: ${{ steps.generate-token.outputs.token }} + PR_NUMBER: ${{ inputs.pr_id || github.event.pull_request.number }} + run: | + blocked_prs=$( + gh -R ${{ github.repository }} pr list --label 'status: blocked' --json 'number,body' \ + | jq -c --argjson pr "$PR_NUMBER" ' + reduce ( .[] | select( + .body | + scan("(?:blocked (?:by|on)|stacked on):? #([0-9]+)") | + map(tonumber) | + any(.[]; . == $pr) + )) as $i ([]; . + [$i]) + ' + ) + { + echo "deps=$blocked_prs" + echo "numdeps=$(jq -r '. | length' <<< "$blocked_prs")" + } >> "$GITHUB_OUTPUT" + + - name: Trigger Blocked PR Workflows for Dependants + if: fromJSON(steps.gather_deps.outputs.numdeps) > 0 + env: + GH_TOKEN: ${{ steps.generate-token.outputs.token }} + DEPS: ${{ steps.gather_deps.outputs.deps }} + run: | + while read -r pr ; do + gh -R ${{ github.repository }} workflow run 'blocked-prs.yml' -r "${{ github.ref_name }}" -f pr_id="$pr" + done < <(jq -c '.[].number' <<< "$DEPS") + diff --git a/meshmc/.github/workflows/nix.yml b/meshmc/.github/workflows/nix.yml new file mode 100644 index 0000000000..a62d9c0aff --- /dev/null +++ b/meshmc/.github/workflows/nix.yml @@ -0,0 +1,138 @@ +name: Nix + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + push: + branches: + - "master" + - "release-*" + tags: + - "*" + paths: + # File types + - "**.cpp" + - "**.h" + - "**.java" + - "**.ui" + - "**.md" + + # Build files + - "**.nix" + - "nix/**" + - "flake.lock" + + # Directories + - "buildconfig/**" + - "cmake/**" + - "launcher/**" + - "libraries/**" + - "branding/**" + - "tests/**" + + # Files + - "CMakeLists.txt" + + # Workflows + - ".github/workflows/nix.yml" + pull_request: + paths: + # File types + - "**.cpp" + - "**.h" + - "**.java" + - "**.ui" + - "**.md" + + # Build files + - "**.nix" + - "nix/**" + - "flake.lock" + + # Directories + - "buildconfig/**" + - "cmake/**" + - "launcher/**" + - "libraries/**" + - "branding/**" + - "tests/**" + + # Files + - "CMakeLists.txt" + + # Workflows + - ".github/workflows/nix.yml" + workflow_dispatch: + +permissions: {} + +env: + DEBUG: ${{ github.ref_type != 'tag' }} + +jobs: + build: + name: Build (${{ matrix.system }}) + + permissions: + contents: read + + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-22.04 + system: x86_64-linux + + - os: ubuntu-22.04-arm + system: aarch64-linux + + - os: macos-14 + system: aarch64-darwin + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Install Nix + uses: cachix/install-nix-action@v31 + + # For PRs + - name: Setup Nix Magic Cache + if: ${{ github.event_name == 'pull_request' }} + uses: DeterminateSystems/magic-nix-cache-action@v13 + with: + diagnostic-endpoint: "" + use-flakehub: false + + # For in-tree builds + - name: Setup Cachix + if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }} + uses: cachix/cachix-action@v17 + with: + name: meshmc + authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} + + - name: Run Flake checks + run: | + nix flake check --print-build-logs --show-trace + + - name: Build debug package + if: ${{ env.DEBUG == 'true' }} + run: | + nix build \ + --no-link --print-build-logs --print-out-paths \ + .#meshmc-debug >> "$GITHUB_STEP_SUMMARY" + + - name: Build release package + if: ${{ env.DEBUG == 'false' }} + env: + TAG: ${{ github.ref_name }} + SYSTEM: ${{ matrix.system }} + run: | + nix build --no-link --print-out-paths .#meshmc \ + | tee -a "$GITHUB_STEP_SUMMARY" \ + | xargs cachix pin meshmc "$TAG"-"$SYSTEM" diff --git a/meshmc/.github/workflows/publish.yml b/meshmc/.github/workflows/publish.yml new file mode 100644 index 0000000000..9d2b3e06b9 --- /dev/null +++ b/meshmc/.github/workflows/publish.yml @@ -0,0 +1,25 @@ +name: Publish + +on: + release: + types: [ released ] + +permissions: {} + +jobs: + winget: + name: Winget + + permissions: + contents: read + + runs-on: ubuntu-slim + + steps: + - name: Publish on Winget + uses: vedantmgoyal2009/winget-releaser@v2 + with: + identifier: ProjectTick.MeshMC + version: ${{ github.event.release.tag_name }} + installers-regex: 'MeshMC-Windows-MSVC(:?-arm64|-Legacy)?-Setup-.+\.exe$' + token: ${{ secrets.WINGET_TOKEN }} diff --git a/meshmc/.github/workflows/release.yml b/meshmc/.github/workflows/release.yml new file mode 100644 index 0000000000..8ce7409b2d --- /dev/null +++ b/meshmc/.github/workflows/release.yml @@ -0,0 +1,124 @@ +name: Build Application and Make Release + +on: + push: + tags: + - "*" + +permissions: {} + +jobs: + build_release: + name: Build Release + uses: ./.github/workflows/build.yml + permissions: + contents: read + id-token: write + packages: write + with: + build-type: Release + environment: Release + secrets: inherit + + create_release: + needs: build_release + permissions: + contents: write + runs-on: ubuntu-slim + outputs: + upload_url: ${{ steps.create_release.outputs.upload_url }} + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + submodules: "true" + path: "MeshMC-source" + - name: Download artifacts + uses: actions/download-artifact@v8 + - name: Grab and store version + run: | + tag_name=$(echo ${{ github.ref }} | grep -oE "[^/]+$") + echo "VERSION=$tag_name" >> $GITHUB_ENV + - name: Package artifacts properly + run: | + mv ${{ github.workspace }}/MeshMC-source MeshMC-${{ env.VERSION }} + mv MeshMC-Linux-Qt6-Portable*/MeshMC-portable.tar.gz MeshMC-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz + mv MeshMC-Linux-aarch64-Qt6-Portable*/MeshMC-portable.tar.gz MeshMC-Linux-aarch64-Qt6-Portable-${{ env.VERSION }}.tar.gz + mv MeshMC-*.AppImage/MeshMC-*-x86_64.AppImage MeshMC-Linux-x86_64.AppImage + mv MeshMC-*.AppImage.zsync/MeshMC-*-x86_64.AppImage.zsync MeshMC-Linux-x86_64.AppImage.zsync + mv MeshMC-*.AppImage/MeshMC-*-aarch64.AppImage MeshMC-Linux-aarch64.AppImage + mv MeshMC-*.AppImage.zsync/MeshMC-*-aarch64.AppImage.zsync MeshMC-Linux-aarch64.AppImage.zsync + mv MeshMC-macOS*/MeshMC.zip MeshMC-macOS-${{ env.VERSION }}.zip + mv MeshMC-macOS*/MeshMC.dmg MeshMC-macOS-${{ env.VERSION }}.dmg + + tar --exclude='.git' -czf MeshMC-${{ env.VERSION }}.tar.gz MeshMC-${{ env.VERSION }} + + for d in MeshMC-Windows-MSVC*; do + cd "${d}" || continue + LEGACY="$(echo -n ${d} | grep -o Legacy || true)" + ARM64="$(echo -n ${d} | grep -o arm64 || true)" + INST="$(echo -n ${d} | grep -o Setup || true)" + PORT="$(echo -n ${d} | grep -o Portable || true)" + NAME="MeshMC-Windows-MSVC" + test -z "${LEGACY}" || NAME="${NAME}-Legacy" + test -z "${ARM64}" || NAME="${NAME}-arm64" + test -z "${PORT}" || NAME="${NAME}-Portable" + test -z "${INST}" || mv MeshMC-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe + test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" * + cd .. + done + + for d in MeshMC-Windows-MinGW-w64*; do + cd "${d}" || continue + INST="$(echo -n ${d} | grep -o Setup || true)" + PORT="$(echo -n ${d} | grep -o Portable || true)" + NAME="MeshMC-Windows-MinGW-w64" + test -z "${PORT}" || NAME="${NAME}-Portable" + test -z "${INST}" || mv MeshMC-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe + test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" * + cd .. + done + + for d in MeshMC-Windows-MinGW-arm64*; do + cd "${d}" || continue + INST="$(echo -n ${d} | grep -o Setup || true)" + PORT="$(echo -n ${d} | grep -o Portable || true)" + NAME="MeshMC-Windows-MinGW-arm64" + test -z "${PORT}" || NAME="${NAME}-Portable" + test -z "${INST}" || mv MeshMC-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe + test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" * + cd .. + done + + - name: Create release + id: create_release + uses: softprops/action-gh-release@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + tag_name: ${{ github.ref }} + name: MeshMC ${{ env.VERSION }} + draft: true + prerelease: false + fail_on_unmatched_files: true + files: | + MeshMC-Linux-x86_64.AppImage + MeshMC-Linux-x86_64.AppImage.zsync + MeshMC-Linux-aarch64.AppImage + MeshMC-Linux-aarch64.AppImage.zsync + MeshMC-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz + MeshMC-Linux-aarch64-Qt6-Portable-${{ env.VERSION }}.tar.gz + MeshMC-Windows-MinGW-w64-${{ env.VERSION }}.zip + MeshMC-Windows-MinGW-w64-Portable-${{ env.VERSION }}.zip + MeshMC-Windows-MinGW-w64-Setup-${{ env.VERSION }}.exe + MeshMC-Windows-MinGW-arm64-${{ env.VERSION }}.zip + MeshMC-Windows-MinGW-arm64-Portable-${{ env.VERSION }}.zip + MeshMC-Windows-MinGW-arm64-Setup-${{ env.VERSION }}.exe + MeshMC-Windows-MSVC-arm64-${{ env.VERSION }}.zip + MeshMC-Windows-MSVC-arm64-Portable-${{ env.VERSION }}.zip + MeshMC-Windows-MSVC-arm64-Setup-${{ env.VERSION }}.exe + MeshMC-Windows-MSVC-${{ env.VERSION }}.zip + MeshMC-Windows-MSVC-Portable-${{ env.VERSION }}.zip + MeshMC-Windows-MSVC-Setup-${{ env.VERSION }}.exe + MeshMC-macOS-${{ env.VERSION }}.zip + MeshMC-macOS-${{ env.VERSION }}.dmg + MeshMC-${{ env.VERSION }}.tar.gz diff --git a/meshmc/.github/workflows/update-flake.yml b/meshmc/.github/workflows/update-flake.yml new file mode 100644 index 0000000000..9aa57ec2e4 --- /dev/null +++ b/meshmc/.github/workflows/update-flake.yml @@ -0,0 +1,35 @@ +name: Update Flake Lockfile + +on: + schedule: + # run weekly on sunday + - cron: "0 0 * * 0" + workflow_dispatch: + +permissions: {} + +jobs: + update-flake: + if: github.repository == 'Project-Tick/MeshMC' + + permissions: + contents: write + pull-requests: write + + runs-on: ubuntu-slim + + steps: + - uses: actions/checkout@v6 + - uses: cachix/install-nix-action@1ca7d21a94afc7c957383a2d217460d980de4934 # v31 + + - uses: DeterminateSystems/update-flake-lock@v28 + with: + commit-msg: "chore(nix): update lockfile" + pr-title: "chore(nix): update lockfile" + pr-labels: | + platform: Linux + area: packaging + complexity: low + priority: low + type: robot + changelog:omit |
