chore: improve actions performance and security practices (#5970)

* chore: bump actions and pin versions

* build: switch to blacksmith

* fix: use rust-toolchain stable

* build: improve pnpm store caching

* chore: remove emoji from workflows

* fix: run prepare job on blacksmith

* chore: kebab case id

* build: add concurrency groups to limit duplicate jobs

* build: switch around node setup and pnpm setup task

* chore: bump to nodejs 24, fix pnpm caching

* fix: enable corepack

* fix: concurrency deadlock in frontend preview

* fix: approve build scripts

* fix: just don't cancel concurrent previews

* build: remove pnpm setup action everywhere

* build: cache apt packages

* build: yet another attempt at fixing concurrency

* build: lower runner type for frontend deploy

* fix: eslint not existing

* build: add sccache to turbo-ci

* fix: correct nextest pkg

* fix: turbo ignoring sccache

* revert me: test labrinth tests

* Revert "revert me: test labrinth tests"

This reverts commit def5cc19183d5c0fe3b6f3c03635d73bb59bd312.

* build: compile app before docker build

* build: lower runner types

* build: remove docker inline caching

* build: try mold on labrinth

* build: tweak labrinth prod build profile

* fix: app windows builds and caching

* fix: tombi format cargo.toml

* fix: swap ping test to cubecraft to avoid CI flakiness

* typos fix

---------

Co-authored-by: aecsocket <aecsocket@tutanota.com>
This commit is contained in:
Michael H.
2026-05-03 14:18:31 +02:00
committed by GitHub
parent 9015ff0971
commit 5b59e39a8a
29 changed files with 976 additions and 382 deletions

View File

@@ -16,8 +16,8 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: 💬 Post or update changelog comment - name: Post or update changelog comment
uses: actions/github-script@v7 uses: actions/github-script@d746ffe35508b1917358783b479e04febd2b8f71 # v9.0.0
with: with:
github-token: ${{ secrets.CROWDIN_GH_TOKEN }} github-token: ${{ secrets.CROWDIN_GH_TOKEN }}
script: | script: |

View File

@@ -12,15 +12,15 @@ jobs:
typos: typos:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: crate-ci/typos@v1.43.1 - uses: crate-ci/typos@6ac2ebd1b93eade61faf7e12688ad87a073fea59 # v1.46.0
# see <https://github.com/influxdata/datafusion-udf-wasm/pull/275> # see <https://github.com/influxdata/datafusion-udf-wasm/pull/275>
tombi: tombi:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: taiki-e/install-action@v2 - uses: taiki-e/install-action@b5fddbb5361bce8a06fb168c9d403a6cc552b084 # v2.75.29
with: with:
tool: tombi tool: tombi
- run: tombi lint - run: tombi lint

View File

@@ -12,8 +12,8 @@ jobs:
shear: shear:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: dtolnay/rust-toolchain@stable - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
- uses: cargo-bins/cargo-binstall@main - uses: cargo-bins/cargo-binstall@dc19f1e48450eefe5a29b8da6c6b00a87d730b37 # v1.18.1
- run: cargo binstall --no-confirm cargo-shear - run: cargo binstall --no-confirm cargo-shear
- run: cargo shear - run: cargo shear

View File

@@ -8,28 +8,79 @@ on:
- .github/workflows/daedalus-docker.yml - .github/workflows/daedalus-docker.yml
- 'apps/daedalus_client/**' - 'apps/daedalus_client/**'
- 'packages/daedalus/**' - 'packages/daedalus/**'
- Cargo.toml
- Cargo.lock
pull_request: pull_request:
types: [opened, synchronize] types: [opened, synchronize]
paths: paths:
- .github/workflows/daedalus-docker.yml - .github/workflows/daedalus-docker.yml
- 'apps/daedalus_client/**' - 'apps/daedalus_client/**'
- 'packages/daedalus/**' - 'packages/daedalus/**'
- Cargo.toml
- Cargo.lock
merge_group: merge_group:
types: [checks_requested] types: [checks_requested]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/prod' }}
jobs: jobs:
docker: docker:
runs-on: ubuntu-latest runs-on: blacksmith-4vcpu-ubuntu-2404
env:
SCCACHE_DIR: '/mnt/sccache'
SCCACHE_CACHE_SIZE: '10G'
SCCACHE_MULTILEVEL_CHAIN: 'disk,s3'
SCCACHE_S3_KEY_PREFIX: '${{ github.repository }}/'
SCCACHE_BUCKET: ${{ secrets.SCCACHE_BUCKET }}
SCCACHE_REGION: ${{ secrets.SCCACHE_REGION }}
SCCACHE_ENDPOINT: ${{ secrets.SCCACHE_ENDPOINT }}
AWS_ACCESS_KEY_ID: ${{ secrets.SCCACHE_S3_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.SCCACHE_S3_SECRET_ACCESS_KEY }}
RUSTC_WRAPPER: 'sccache'
steps: steps:
- name: 📥 Check out code - name: Check out code
uses: actions/checkout@v4 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: 🧰 Set up Docker Buildx - name: Setup Rust toolchain
uses: docker/setup-buildx-action@v2 uses: actions-rust-lang/setup-rust-toolchain@2b1f5e9b395427c92ee4e3331786ca3c37afe2d7 # v1.16.0
with:
rustflags: ''
cache: false
- name: ⚙️ Generate Docker image metadata - name: Cache Cargo registry and index
id: docker_meta uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: docker/metadata-action@v5 with:
path: |
~/.cargo/registry
~/.cargo/git
~/.cargo/bin
key: ${{ runner.os }}-${{ runner.arch }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Mount sccache disk cache
uses: useblacksmith/stickydisk@13af8883542ca949a717e70fef89d15edbb29d88 # v1.2.0
with:
key: ${{ github.repository }}-daedalus-sccache
path: /mnt/sccache
- name: Setup sccache
uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
- name: Build daedalus_client
run: cargo build --release --package daedalus_client
- name: Stage Docker context
run: |
mkdir -p apps/daedalus_client/docker-stage
cp target/release/daedalus_client apps/daedalus_client/docker-stage/daedalus_client
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Generate Docker image metadata
id: docker-meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
env: env:
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
with: with:
@@ -43,20 +94,19 @@ jobs:
org.opencontainers.image.description=Modrinth game metadata query client org.opencontainers.image.description=Modrinth game metadata query client
org.opencontainers.image.licenses=MIT org.opencontainers.image.licenses=MIT
- name: 🔑 Login to GitHub Packages - name: Login to GitHub Packages
uses: docker/login-action@v3 uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: 🔨 Build and push - name: Build and push
uses: docker/build-push-action@v6 uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with: with:
context: ./apps/daedalus_client/docker-stage
file: ./apps/daedalus_client/Dockerfile file: ./apps/daedalus_client/Dockerfile
push: ${{ github.event_name != 'pull_request' }} push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.docker_meta.outputs.tags }} tags: ${{ steps.docker-meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }} labels: ${{ steps.docker-meta.outputs.labels }}
annotations: ${{ steps.docker_meta.outputs.annotations }} annotations: ${{ steps.docker-meta.outputs.annotations }}
cache-from: type=registry,ref=ghcr.io/modrinth/daedalus:main
cache-to: type=inline

View File

@@ -12,10 +12,10 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Log in to GitHub Container Registry - name: Log in to GitHub Container Registry
uses: docker/login-action@v2 uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}

View File

@@ -21,16 +21,20 @@ on:
type: string type: string
description: 'The environment to deploy to (staging-preview or production-preview)' description: 'The environment to deploy to (staging-preview or production-preview)'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.environment || 'push' }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/prod' }}
jobs: jobs:
deploy: deploy:
runs-on: ubuntu-latest runs-on: blacksmith-2vcpu-ubuntu-2404
permissions: permissions:
contents: read contents: read
deployments: write deployments: write
pull-requests: write pull-requests: write
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
fetch-depth: 0 fetch-depth: 0
@@ -63,14 +67,25 @@ jobs:
echo "url=https://modrinth.com" >> $GITHUB_OUTPUT echo "url=https://modrinth.com" >> $GITHUB_OUTPUT
fi fi
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v4 uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: pnpm
- name: Enable Corepack
run: corepack enable
- name: Get pnpm store path
id: pnpm-store
run: echo "store-path=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
- name: Restore pnpm cache
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ steps.pnpm-store.outputs.store-path }}
key: pnpm-cache-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
pnpm-cache-
- name: Inject build variables - name: Inject build variables
working-directory: ./apps/frontend working-directory: ./apps/frontend
@@ -99,7 +114,7 @@ jobs:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
- name: Create Sentry release and upload sourcemaps - name: Create Sentry release and upload sourcemaps
uses: getsentry/action-release@v3 uses: getsentry/action-release@5657c9e888b4e2cc85f4d29143ea4131fde4a73a # v3.6.0
env: env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: modrinth SENTRY_ORG: modrinth
@@ -111,7 +126,7 @@ jobs:
- name: Deploy Cloudflare Worker - name: Deploy Cloudflare Worker
id: wrangler id: wrangler
uses: cloudflare/wrangler-action@v3 uses: cloudflare/wrangler-action@9acf94ace14e7dc412b076f2c5c20b8ce93c79cd # v3.15.0
with: with:
apiToken: ${{ secrets.CF_API_TOKEN }} apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }} accountId: ${{ secrets.CF_ACCOUNT_ID }}
@@ -137,7 +152,7 @@ jobs:
- name: Upload deployment URL - name: Upload deployment URL
if: ${{ inputs.environment != '' }} if: ${{ inputs.environment != '' }}
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: deployment-url-${{ inputs.environment }} name: deployment-url-${{ inputs.environment }}
path: deployment-url-${{ inputs.environment }}.txt path: deployment-url-${{ inputs.environment }}.txt

View File

@@ -16,6 +16,9 @@ jobs:
if: github.repository_owner == 'modrinth' && github.event.pull_request.head.repo.full_name == github.repository if: github.repository_owner == 'modrinth' && github.event.pull_request.head.repo.full_name == github.repository
uses: ./.github/workflows/frontend-deploy.yml uses: ./.github/workflows/frontend-deploy.yml
secrets: inherit secrets: inherit
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.environment }}
cancel-in-progress: true
strategy: strategy:
matrix: matrix:
environment: [staging-preview, production-preview] environment: [staging-preview, production-preview]
@@ -24,22 +27,36 @@ jobs:
deploy-storybook: deploy-storybook:
if: github.repository_owner == 'modrinth' && github.event.pull_request.head.repo.full_name == github.repository if: github.repository_owner == 'modrinth' && github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest runs-on: blacksmith-2vcpu-ubuntu-2404
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-storybook
cancel-in-progress: true
permissions: permissions:
contents: read contents: read
deployments: write deployments: write
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v4 uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: pnpm
- name: Enable Corepack
run: corepack enable
- name: Get pnpm store path
id: pnpm-store
run: echo "store-path=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
- name: Restore pnpm cache
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ steps.pnpm-store.outputs.store-path }}
key: pnpm-cache-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
pnpm-cache-
- name: Install dependencies - name: Install dependencies
working-directory: ./packages/ui working-directory: ./packages/ui
@@ -54,7 +71,7 @@ jobs:
run: echo "sha_short=${GITHUB_SHA::8}" >> $GITHUB_OUTPUT run: echo "sha_short=${GITHUB_SHA::8}" >> $GITHUB_OUTPUT
- name: Deploy Storybook preview - name: Deploy Storybook preview
uses: cloudflare/wrangler-action@v3 uses: cloudflare/wrangler-action@9acf94ace14e7dc412b076f2c5c20b8ce93c79cd # v3.15.0
with: with:
apiToken: ${{ secrets.CF_API_TOKEN }} apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }} accountId: ${{ secrets.CF_ACCOUNT_ID }}
@@ -69,7 +86,7 @@ jobs:
needs: [deploy, deploy-storybook] needs: [deploy, deploy-storybook]
steps: steps:
- name: Download deployment URLs - name: Download deployment URLs
uses: actions/download-artifact@v7 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with: with:
pattern: deployment-url-* pattern: deployment-url-*
merge-multiple: true merge-multiple: true
@@ -89,7 +106,7 @@ jobs:
- name: Find comment - name: Find comment
if: github.event_name == 'pull_request' if: github.event_name == 'pull_request'
uses: peter-evans/find-comment@v3 uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad # v4.0.0
id: fc id: fc
with: with:
token: ${{ secrets.CROWDIN_GH_TOKEN }} token: ${{ secrets.CROWDIN_GH_TOKEN }}
@@ -98,7 +115,7 @@ jobs:
- name: Comment deploy URL on PR - name: Comment deploy URL on PR
if: github.event_name == 'pull_request' if: github.event_name == 'pull_request'
uses: peter-evans/create-or-update-comment@v5 uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
with: with:
token: ${{ secrets.CROWDIN_GH_TOKEN }} token: ${{ secrets.CROWDIN_GH_TOKEN }}
issue-number: ${{ github.event.pull_request.number }} issue-number: ${{ github.event.pull_request.number }}

View File

@@ -51,14 +51,14 @@ jobs:
CROWDIN_GH_TOKEN_DEFINED: ${{ secrets.CROWDIN_GH_TOKEN != '' }} CROWDIN_GH_TOKEN_DEFINED: ${{ secrets.CROWDIN_GH_TOKEN != '' }}
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
ref: ${{ github.ref }} ref: ${{ github.ref }}
token: ${{ secrets.CROWDIN_GH_TOKEN }} token: ${{ secrets.CROWDIN_GH_TOKEN }}
- name: Configure Git author - name: Configure Git author
id: git-author id: git-author
uses: MarcoIeni/git-config@v0.1 uses: MarcoIeni/git-config@59144859caf016f8b817a2ac9b051578729173c4 # v0.1.2
env: env:
GITHUB_TOKEN: ${{ secrets.CROWDIN_GH_TOKEN }} GITHUB_TOKEN: ${{ secrets.CROWDIN_GH_TOKEN }}
@@ -79,7 +79,7 @@ jobs:
echo "safe_branch_name=$SAFE_BRANCH_NAME" >> "$GITHUB_OUTPUT" echo "safe_branch_name=$SAFE_BRANCH_NAME" >> "$GITHUB_OUTPUT"
- name: Download translations from Crowdin - name: Download translations from Crowdin
uses: crowdin/github-action@v2 uses: crowdin/github-action@8868a33591d21088edfc398968173a3b98d51706 # v2.16.2
with: with:
upload_sources: false upload_sources: false
upload_translations: false upload_translations: false
@@ -96,7 +96,7 @@ jobs:
run: sudo chown -R $USER:$USER . run: sudo chown -R $USER:$USER .
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@v7 uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with: with:
title: 'New translations from Crowdin (${{ steps.branch-name.outputs.branch_name }})' title: 'New translations from Crowdin (${{ steps.branch-name.outputs.branch_name }})'
body-path: .github/templates/crowdin-pr.md body-path: .github/templates/crowdin-pr.md

View File

@@ -53,7 +53,7 @@ jobs:
CROWDIN_PERSONAL_TOKEN_DEFINED: ${{ secrets.CROWDIN_PERSONAL_TOKEN != '' }} CROWDIN_PERSONAL_TOKEN_DEFINED: ${{ secrets.CROWDIN_PERSONAL_TOKEN != '' }}
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
ref: ${{ github.ref }} ref: ${{ github.ref }}
@@ -68,7 +68,7 @@ jobs:
echo "safe_branch_name=$SAFE_BRANCH_NAME" >> "$GITHUB_OUTPUT" echo "safe_branch_name=$SAFE_BRANCH_NAME" >> "$GITHUB_OUTPUT"
- name: Upload translations to Crowdin - name: Upload translations to Crowdin
uses: crowdin/github-action@v1 uses: crowdin/github-action@8868a33591d21088edfc398968173a3b98d51706 # v2.16.2
with: with:
upload_sources: true upload_sources: true
upload_translations: false upload_translations: false

View File

@@ -19,19 +19,73 @@ on:
merge_group: merge_group:
types: [checks_requested] types: [checks_requested]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/prod' }}
jobs: jobs:
docker: docker:
runs-on: ubuntu-latest runs-on: blacksmith-4vcpu-ubuntu-2404
env:
SQLX_OFFLINE: 'true'
GIT_HASH: ${{ github.sha }}
SCCACHE_DIR: '/mnt/sccache'
SCCACHE_CACHE_SIZE: '10G'
SCCACHE_MULTILEVEL_CHAIN: 'disk,s3'
SCCACHE_S3_KEY_PREFIX: '${{ github.repository }}/'
SCCACHE_BUCKET: ${{ secrets.SCCACHE_BUCKET }}
SCCACHE_REGION: ${{ secrets.SCCACHE_REGION }}
SCCACHE_ENDPOINT: ${{ secrets.SCCACHE_ENDPOINT }}
AWS_ACCESS_KEY_ID: ${{ secrets.SCCACHE_S3_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.SCCACHE_S3_SECRET_ACCESS_KEY }}
RUSTC_WRAPPER: 'sccache'
steps: steps:
- name: 📥 Check out code - name: Check out code
uses: actions/checkout@v4 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: 🧰 Set up Docker Buildx - name: Setup Rust toolchain
uses: docker/setup-buildx-action@v2 uses: actions-rust-lang/setup-rust-toolchain@2b1f5e9b395427c92ee4e3331786ca3c37afe2d7 # v1.16.0
with:
rustflags: ''
cache: false
- name: ⚙️ Generate Docker image metadata - name: Setup mold
id: docker_meta uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1 / Mold 2.41.0
uses: docker/metadata-action@v5
- name: Cache Cargo registry and index
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: |
~/.cargo/registry
~/.cargo/git
~/.cargo/bin
key: ${{ runner.os }}-${{ runner.arch }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Mount sccache disk cache
uses: useblacksmith/stickydisk@13af8883542ca949a717e70fef89d15edbb29d88 # v1.2.0
with:
key: ${{ github.repository }}-labrinth-sccache
path: /mnt/sccache
- name: Setup sccache
uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
- name: Build labrinth
run: cargo build --profile release-labrinth --package labrinth
- name: Stage Docker context
run: |
mkdir -p apps/labrinth/docker-stage
cp target/release-labrinth/labrinth apps/labrinth/docker-stage/labrinth
cp -r apps/labrinth/migrations apps/labrinth/docker-stage/migrations
cp -r apps/labrinth/assets apps/labrinth/docker-stage/assets
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Generate Docker image metadata
id: docker-meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
env: env:
# GitHub Packages requires annotations metadata in at least the index descriptor to show them # GitHub Packages requires annotations metadata in at least the index descriptor to show them
# up properly in its UI it seems, but it's not clear about it, because the docs refer to the # up properly in its UI it seems, but it's not clear about it, because the docs refer to the
@@ -49,22 +103,19 @@ jobs:
org.opencontainers.image.description=Modrinth API org.opencontainers.image.description=Modrinth API
org.opencontainers.image.licenses=AGPL-3.0-only org.opencontainers.image.licenses=AGPL-3.0-only
- name: 🔑 Login to GitHub Packages - name: Login to GitHub Packages
uses: docker/login-action@v3 uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: 🔨 Build and push - name: Build and push
uses: docker/build-push-action@v6 uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with: with:
context: ./apps/labrinth/docker-stage
file: ./apps/labrinth/Dockerfile file: ./apps/labrinth/Dockerfile
push: ${{ github.event_name != 'pull_request' }} push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.docker_meta.outputs.tags }} tags: ${{ steps.docker-meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }} labels: ${{ steps.docker-meta.outputs.labels }}
annotations: ${{ steps.docker_meta.outputs.annotations }} annotations: ${{ steps.docker-meta.outputs.annotations }}
build-args: |
GIT_HASH=${{ fromJSON(steps.docker_meta.outputs.json).labels['org.opencontainers.image.revision'] }}
cache-from: type=registry,ref=ghcr.io/modrinth/labrinth:main
cache-to: type=inline

View File

@@ -0,0 +1,40 @@
name: Prepare pnpm cache
on:
push:
paths:
- .github/workflows/prepare-pnpm-cache.yml
- package.json
- pnpm-lock.yaml
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/prod' }}
jobs:
prepare:
runs-on: blacksmith-2vcpu-ubuntu-2404
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .nvmrc
- name: Enable Corepack
run: corepack enable
- name: Get pnpm store path
id: pnpm-store
run: echo "store-path=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
- name: Cache pnpm
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ steps.pnpm-store.outputs.store-path }}
key: pnpm-cache-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('**/pnpm-lock.yaml') }}
- name: Install dependencies
run: pnpm recursive install --frozen-lockfile

View File

@@ -31,45 +31,67 @@ on:
default: prod default: prod
required: false required: false
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/prod' }}
jobs: jobs:
build: build:
name: Build name: Build
env: env:
VITE_STRIPE_PUBLISHABLE_KEY: pk_live_51JbFxJJygY5LJFfKLVVldb10HlLt24p421OWRsTOWc5sXYFOnFUXWieSc6HD3PHo25ktx8db1WcHr36XGFvZFVUz00V9ixrCs5 VITE_STRIPE_PUBLISHABLE_KEY: pk_live_51JbFxJJygY5LJFfKLVVldb10HlLt24p421OWRsTOWc5sXYFOnFUXWieSc6HD3PHo25ktx8db1WcHr36XGFvZFVUz00V9ixrCs5
# SCCACHE_DIR: '/mnt/sccache'
# SCCACHE_CACHE_SIZE: '10G'
# SCCACHE_MULTILEVEL_CHAIN: 'disk,s3'
SCCACHE_S3_KEY_PREFIX: '${{ github.repository }}/'
SCCACHE_BUCKET: ${{ secrets.SCCACHE_BUCKET }}
SCCACHE_REGION: ${{ secrets.SCCACHE_REGION }}
SCCACHE_ENDPOINT: ${{ secrets.SCCACHE_ENDPOINT }}
AWS_ACCESS_KEY_ID: ${{ secrets.SCCACHE_S3_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.SCCACHE_S3_SECRET_ACCESS_KEY }}
RUSTC_WRAPPER: 'sccache'
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
platform: [macos-latest, windows-latest, ubuntu-latest] platform:
[
blacksmith-6vcpu-macos-26,
blacksmith-8vcpu-windows-2025,
blacksmith-8vcpu-ubuntu-2404,
]
include: include:
- platform: macos-latest - platform: blacksmith-6vcpu-macos-26
artifact-target-name: universal-apple-darwin artifact-target-name: universal-apple-darwin
- platform: windows-latest - platform: blacksmith-8vcpu-windows-2025
artifact-target-name: x86_64-pc-windows-msvc artifact-target-name: x86_64-pc-windows-msvc
- platform: ubuntu-latest - platform: blacksmith-8vcpu-ubuntu-2404
artifact-target-name: x86_64-unknown-linux-gnu artifact-target-name: x86_64-unknown-linux-gnu
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
- name: Check out code - name: Check out code
uses: actions/checkout@v4 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup Rust toolchain - name: Setup Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1 uses: actions-rust-lang/setup-rust-toolchain@2b1f5e9b395427c92ee4e3331786ca3c37afe2d7 # v1.16.0
with: with:
rustflags: '' rustflags: ''
target: ${{ startsWith(matrix.platform, 'macos') && 'x86_64-apple-darwin' || '' }} target: ${{ contains(matrix.platform, 'macos') && 'x86_64-apple-darwin' || '' }}
- name: Install pnpm - name: Setup sccache
uses: pnpm/action-setup@v4 uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
- name: Setup Node.js - name: Enable Corepack
uses: actions/setup-node@v4 run: corepack enable
- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: pnpm cache: 'pnpm'
- name: Generate tauri-dev.conf.json - name: Generate tauri-dev.conf.json
shell: bash shell: bash
@@ -87,18 +109,19 @@ jobs:
EOF EOF
- name: Install Linux build dependencies - name: Install Linux build dependencies
if: startsWith(matrix.platform, 'ubuntu') if: contains(matrix.platform, 'ubuntu')
run: | uses: awalsh128/cache-apt-pkgs-action@acb598e5ddbc6f68a970c5da0688d2f3a9f04d05 # v1.6.0
sudo apt-get update with:
sudo apt-get install -yq libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev packages: libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev
version: v1 # cache key
- name: Setup Dasel - name: Setup Dasel
uses: jaxxstorm/action-install-gh-release@v2.1.0 uses: jaxxstorm/action-install-gh-release@25e24d2d23ae098373794ef1d6faecb48ee52da8 # v3.0.0
with: with:
repo: TomWright/dasel repo: TomWright/dasel
tag: v2.8.1 tag: v2.8.1
extension-matching: disable extension-matching: disable
rename-to: ${{ startsWith(matrix.platform, 'windows') && 'dasel.exe' || 'dasel' }} rename-to: ${{ contains(matrix.platform, 'windows') && 'dasel.exe' || 'dasel' }}
chmod: 0755 chmod: 0755
- name: Set application version and environment - name: Set application version and environment
@@ -115,13 +138,13 @@ jobs:
cp "packages/app-lib/.env.${BUILD_ENVIRONMENT}" packages/app-lib/.env cp "packages/app-lib/.env.${BUILD_ENVIRONMENT}" packages/app-lib/.env
- name: Setup Turbo cache - name: Setup Turbo cache
uses: rharkor/caching-for-turbo@v1.8 uses: rharkor/caching-for-turbo@56219402aacc0d06b650d898c222996dbc1191ec # v2.3.14
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
- name: Set up Windows code signing - name: Set up Windows code signing
if: startsWith(matrix.platform, 'windows') if: contains(matrix.platform, 'windows')
shell: bash shell: bash
run: | run: |
if [ '${{ startsWith(github.ref, 'refs/tags/v') || inputs.sign-windows-binaries }}' = 'true' ]; then if [ '${{ startsWith(github.ref, 'refs/tags/v') || inputs.sign-windows-binaries }}' = 'true' ]; then
@@ -132,7 +155,7 @@ jobs:
- name: Build macOS app - name: Build macOS app
run: ${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && 'pnpm --filter=@modrinth/app run tauri build --target universal-apple-darwin --config tauri-release.conf.json' || 'pnpm --filter=@modrinth/app run tauri build --target universal-apple-darwin --config tauri-dev.conf.json' }} run: ${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && 'pnpm --filter=@modrinth/app run tauri build --target universal-apple-darwin --config tauri-release.conf.json' || 'pnpm --filter=@modrinth/app run tauri build --target universal-apple-darwin --config tauri-dev.conf.json' }}
if: startsWith(matrix.platform, 'macos') if: contains(matrix.platform, 'macos')
env: env:
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
@@ -146,7 +169,7 @@ jobs:
- name: Build Linux app - name: Build Linux app
run: ${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && 'pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json' || 'pnpm --filter=@modrinth/app run tauri build --config tauri-dev.conf.json' }} run: ${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && 'pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json' || 'pnpm --filter=@modrinth/app run tauri build --config tauri-dev.conf.json' }}
if: startsWith(matrix.platform, 'ubuntu') if: contains(matrix.platform, 'ubuntu')
env: env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
@@ -158,7 +181,7 @@ jobs:
$env:JAVA_HOME = "$env:JAVA_HOME_17_X64" $env:JAVA_HOME = "$env:JAVA_HOME_17_X64"
${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && 'pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json --verbose --bundles "nsis,updater"' || 'pnpm --filter=@modrinth/app run tauri build --config tauri-dev.conf.json --verbose --bundles "nsis,updater"' }} ${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && 'pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json --verbose --bundles "nsis,updater"' || 'pnpm --filter=@modrinth/app run tauri build --config tauri-dev.conf.json --verbose --bundles "nsis,updater"' }}
Remove-Item -Path signer-client-cert.p12 -ErrorAction SilentlyContinue Remove-Item -Path signer-client-cert.p12 -ErrorAction SilentlyContinue
if: startsWith(matrix.platform, 'windows') if: contains(matrix.platform, 'windows')
env: env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
@@ -167,7 +190,7 @@ jobs:
DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_PASSWORD: ${{ secrets.DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_PASSWORD }} DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_PASSWORD: ${{ secrets.DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_PASSWORD }}
- name: Upload app bundles - name: Upload app bundles
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: App bundle (${{ matrix.artifact-target-name }}) name: App bundle (${{ matrix.artifact-target-name }})
path: | path: |

View File

@@ -4,6 +4,10 @@ on:
workflows: ['Modrinth App build'] workflows: ['Modrinth App build']
types: [completed] types: [completed]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/prod' }}
jobs: jobs:
release: release:
name: Release Modrinth App name: Release Modrinth App
@@ -11,8 +15,7 @@ jobs:
github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'push' && github.event.workflow_run.event == 'push' &&
startsWith(github.event.workflow_run.head_branch, 'v') startsWith(github.event.workflow_run.head_branch, 'v')
runs-on: ubuntu-latest runs-on: blacksmith-8vcpu-ubuntu-2404
env: env:
VERSION_TAG: ${{ github.event.workflow_run.head_branch }} VERSION_TAG: ${{ github.event.workflow_run.head_branch }}
LINUX_X64_BUNDLE_ARTIFACT_NAME: App bundle (x86_64-unknown-linux-gnu) LINUX_X64_BUNDLE_ARTIFACT_NAME: App bundle (x86_64-unknown-linux-gnu)
@@ -21,10 +24,10 @@ jobs:
LAUNCHER_FILES_BUCKET_BASE_URL: https://launcher-files.modrinth.com LAUNCHER_FILES_BUCKET_BASE_URL: https://launcher-files.modrinth.com
steps: steps:
- name: 📥 Check out code - name: Check out code
uses: actions/checkout@v4 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: 🔒 Verify ref is a tag - name: Verify ref is a tag
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
HEAD_SHA: ${{ github.event.workflow_run.head_sha }} HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
@@ -43,8 +46,8 @@ jobs:
fi fi
echo "Verified ${VERSION_TAG} is a tag pointing at ${HEAD_SHA}" echo "Verified ${VERSION_TAG} is a tag pointing at ${HEAD_SHA}"
- name: 📥 Download Modrinth App artifacts - name: Download Modrinth App artifacts
uses: dawidd6/action-download-artifact@v11 uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21
with: with:
workflow: theseus-build.yml workflow: theseus-build.yml
workflow_conclusion: success workflow_conclusion: success
@@ -52,12 +55,12 @@ jobs:
branch: ${{ env.VERSION_TAG }} branch: ${{ env.VERSION_TAG }}
use_unzip: true use_unzip: true
- name: 📝 Extract app changelog - name: Extract app changelog
env: env:
VERSION: ${{ env.VERSION_TAG }} VERSION: ${{ env.VERSION_TAG }}
run: npx --yes tsx scripts/build-theseus-release-notes.ts run: npx --yes tsx scripts/build-theseus-release-notes.ts
- name: 🛠️ Generate version manifest - name: Generate version manifest
run: | run: |
# Reference: https://tauri.app/plugin/updater/#server-support # Reference: https://tauri.app/plugin/updater/#server-support
jq -nc \ jq -nc \
@@ -102,7 +105,7 @@ jobs:
echo "Generated manifest for version ${VERSION_TAG}:" echo "Generated manifest for version ${VERSION_TAG}:"
cat updates.json cat updates.json
- name: 📤 Upload release artifacts - name: Upload release artifacts
env: env:
AWS_ACCESS_KEY_ID: ${{ secrets.LAUNCHER_FILES_BUCKET_ACCESS_KEY_ID }} AWS_ACCESS_KEY_ID: ${{ secrets.LAUNCHER_FILES_BUCKET_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.LAUNCHER_FILES_BUCKET_SECRET_ACCESS_KEY }} AWS_SECRET_ACCESS_KEY: ${{ secrets.LAUNCHER_FILES_BUCKET_SECRET_ACCESS_KEY }}
@@ -137,7 +140,7 @@ jobs:
aws s3 cp updates.json "s3://${AWS_BUCKET}" aws s3 cp updates.json "s3://${AWS_BUCKET}"
- name: 🏷️ Create GitHub release - name: Create GitHub release
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
run: | run: |

View File

@@ -8,10 +8,14 @@ on:
merge_group: merge_group:
types: [checks_requested] types: [checks_requested]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/prod' }}
jobs: jobs:
build: build:
name: Lint and Test name: Lint and Test
runs-on: ubuntu-latest runs-on: blacksmith-4vcpu-ubuntu-2404
env: env:
# Ensure pnpm output is colored in GitHub Actions logs # Ensure pnpm output is colored in GitHub Actions logs
@@ -23,59 +27,103 @@ jobs:
# since we don't want warnings to become errors # since we don't want warnings to become errors
# while developing) # while developing)
RUSTFLAGS: -Dwarnings RUSTFLAGS: -Dwarnings
# sccache config
SCCACHE_DIR: '/mnt/sccache'
SCCACHE_CACHE_SIZE: '10G'
SCCACHE_MULTILEVEL_CHAIN: 'disk,s3'
SCCACHE_S3_KEY_PREFIX: '${{ github.repository }}/'
SCCACHE_BUCKET: ${{ secrets.SCCACHE_BUCKET }}
SCCACHE_REGION: ${{ secrets.SCCACHE_REGION }}
SCCACHE_ENDPOINT: ${{ secrets.SCCACHE_ENDPOINT }}
AWS_ACCESS_KEY_ID: ${{ secrets.SCCACHE_S3_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.SCCACHE_S3_SECRET_ACCESS_KEY }}
RUSTC_WRAPPER: 'sccache'
steps: steps:
- name: 📥 Check out code - name: Check out code
uses: actions/checkout@v4 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
fetch-depth: 2 fetch-depth: 2
- name: 🧰 Install build dependencies - name: Install build dependencies
run: | uses: awalsh128/cache-apt-pkgs-action@acb598e5ddbc6f68a970c5da0688d2f3a9f04d05 # v1.6.0
sudo apt-get update with:
sudo apt-get install -yq libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev packages: libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev
version: v1 # cache key
- name: 🧰 Install pnpm - name: Setup Node
uses: pnpm/action-setup@v4 uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- name: 🧰 Setup Node.js
uses: actions/setup-node@v4
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: pnpm
- name: 🧰 Setup Rust toolchain - name: Enable Corepack
uses: actions-rust-lang/setup-rust-toolchain@v1 run: corepack enable
- name: Get pnpm store path
id: pnpm-store
run: echo "store-path=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
- name: Restore pnpm cache
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ steps.pnpm-store.outputs.store-path }}
key: pnpm-cache-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
pnpm-cache-
- name: Setup Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@2b1f5e9b395427c92ee4e3331786ca3c37afe2d7 # v1.16.0
with: with:
rustflags: '' rustflags: ''
components: clippy, rustfmt components: clippy, rustfmt
cache: false cache: false
- name: 🧰 Setup nextest - name: Cache Cargo registry and index
uses: taiki-e/install-action@nextest uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
with:
path: |
~/.cargo/registry
~/.cargo/git
~/.cargo/bin
key: ${{ runner.os }}-${{ runner.arch }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Mount sccache disk cache
uses: useblacksmith/stickydisk@13af8883542ca949a717e70fef89d15edbb29d88 # v1.2.0
with:
key: ${{ github.repository }}-turbo-sccache
path: /mnt/sccache
- name: Setup sccache
uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
- name: Setup binstall
uses: cargo-bins/cargo-binstall@dc19f1e48450eefe5a29b8da6c6b00a87d730b37 # v1.18.1
- name: Setup nextest
run: cargo binstall --no-confirm --secure cargo-nextest@0.9.133
# cargo-binstall does not have pre-built binaries for sqlx-cli, so we fall # cargo-binstall does not have pre-built binaries for sqlx-cli, so we fall
# back to a cached cargo install # back to a cached cargo install
- name: 🧰 Setup cargo-sqlx - name: Setup cargo-sqlx
uses: taiki-e/cache-cargo-install-action@v2 uses: taiki-e/cache-cargo-install-action@f9eed3e4680f27610dc6d8c67be1b88593f7dade # v3.0.6
with: with:
tool: sqlx-cli tool: sqlx-cli@0.8.6
locked: false locked: false
no-default-features: true no-default-features: true
features: rustls,postgres features: rustls,postgres
- name: 💨 Setup Turbo cache - name: Setup Turbo cache
uses: rharkor/caching-for-turbo@v1.8 uses: rharkor/caching-for-turbo@56219402aacc0d06b650d898c222996dbc1191ec # v2.3.14
- name: 🧰 Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
- name: ⚙️ Set app environment - name: Set app environment
working-directory: packages/app-lib working-directory: packages/app-lib
run: cp .env.staging .env run: cp .env.staging .env
# check if labrinth tests will actually run (cache miss) # check if labrinth tests will actually run (cache miss)
- name: 🔍 Check if labrinth tests need to run - name: Check if labrinth tests need to run
id: check-labrinth id: check-labrinth
run: | run: |
LABRINTH_TEST_STATUS=$(pnpm turbo run test --filter=@modrinth/labrinth --dry-run=json | jq -r '.tasks[] | select(.task == "test") | .cache.status') LABRINTH_TEST_STATUS=$(pnpm turbo run test --filter=@modrinth/labrinth --dry-run=json | jq -r '.tasks[] | select(.task == "test") | .cache.status')
@@ -86,21 +134,21 @@ jobs:
echo "needs_services=true" >> $GITHUB_OUTPUT echo "needs_services=true" >> $GITHUB_OUTPUT
fi fi
- name: ⚙️ Start services - name: Start services
if: steps.check-labrinth.outputs.needs_services == 'true' if: steps.check-labrinth.outputs.needs_services == 'true'
run: docker compose up --wait run: docker compose up --wait
- name: ⚙️ Setup labrinth environment and database - name: Setup labrinth environment and database
if: steps.check-labrinth.outputs.needs_services == 'true' if: steps.check-labrinth.outputs.needs_services == 'true'
working-directory: apps/labrinth working-directory: apps/labrinth
run: | run: |
cp .env.local .env cp .env.local .env
sqlx database setup sqlx database setup
- name: 🔍 Lint and test - name: Lint and test
run: pnpm run ci run: pnpm run ci
- name: 🔍 Verify intl:extract has been run - name: Verify intl:extract has been run
run: | run: |
pnpm turbo run intl:extract --force pnpm turbo run intl:extract --force
git diff --exit-code --color */*/src/locales/en-US/index.json git diff --exit-code --color */*/src/locales/en-US/index.json

9
.npmrc
View File

@@ -1,2 +1,11 @@
strict-peer-dependencies=false strict-peer-dependencies=false
auto-install-peers=true auto-install-peers=true
public-hoist-pattern[]=prettier-plugin-*
public-hoist-pattern[]=@prettier/plugin-*
public-hoist-pattern[]=eslint
public-hoist-pattern[]=@eslint/*
public-hoist-pattern[]=eslint-plugin-*
public-hoist-pattern[]=@nuxt/eslint-config
public-hoist-pattern[]=typescript-eslint
public-hoist-pattern[]=vue-eslint-parser
public-hoist-pattern[]=globals

2
.nvmrc
View File

@@ -1 +1 @@
20.19.2 24.15.0

View File

@@ -279,10 +279,11 @@ opt-level = "s" # Optimize for binary size
strip = true # Remove debug symbols strip = true # Remove debug symbols
lto = true # Enables link to optimizations lto = true # Enables link to optimizations
panic = "abort" # Strip expensive panic clean-up logic panic = "abort" # Strip expensive panic clean-up logic
codegen-units = 1 # Compile crates one after another so the compiler can optimize better
# Specific profile for labrinth production builds # Specific profile for labrinth production builds
[profile.release-labrinth] [profile.release-labrinth]
inherits = "release" inherits = "release"
opt-level = 2
strip = false # Keep debug symbols for Sentry strip = false # Keep debug symbols for Sentry
lto = "thin" # Enable LTO but keep compile times reasonable
panic = "unwind" # Don't exit the whole app on panic in production panic = "unwind" # Don't exit the whole app on panic in production

View File

@@ -61,7 +61,7 @@ defineExpose({
errorType.value = 'directory_move' errorType.value = 'directory_move'
supportLink.value = 'https://support.modrinth.com' supportLink.value = 'https://support.modrinth.com'
if (errorVal.message.includes('directory is not writeable')) { if (errorVal.message.includes('directory is not writable')) {
metadata.value.readOnly = true metadata.value.readOnly = true
} }

View File

@@ -1,19 +1,5 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
FROM rust:1.90.0 AS build
WORKDIR /usr/src/daedalus
COPY . .
RUN --mount=type=cache,target=/usr/src/daedalus/target \
--mount=type=cache,target=/usr/local/cargo,from=rust:1.89.0,source=/usr/local/cargo \
cargo build --release --package daedalus_client
FROM build AS artifacts
RUN --mount=type=cache,target=/usr/src/daedalus/target \
mkdir /daedalus \
&& cp /usr/src/daedalus/target/release/daedalus_client /daedalus/daedalus_client
FROM debian:trixie-slim FROM debian:trixie-slim
LABEL org.opencontainers.image.source=https://github.com/modrinth/code LABEL org.opencontainers.image.source=https://github.com/modrinth/code
@@ -25,7 +11,7 @@ RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates openssl \ && apt-get install -y --no-install-recommends ca-certificates openssl \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
COPY --from=artifacts /daedalus /daedalus COPY daedalus_client /daedalus/daedalus_client
WORKDIR /daedalus_client WORKDIR /daedalus_client
CMD ["/daedalus/daedalus_client"] CMD ["/daedalus/daedalus_client"]

View File

@@ -21,7 +21,7 @@
"@types/dompurify": "^3.0.5", "@types/dompurify": "^3.0.5",
"@types/iso-3166-2": "^1.0.4", "@types/iso-3166-2": "^1.0.4",
"@types/js-yaml": "^4.0.9", "@types/js-yaml": "^4.0.9",
"@types/node": "^20.1.0", "@types/node": "^24",
"@types/semver": "^7.7.1", "@types/semver": "^7.7.1",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"glob": "^10.2.7", "glob": "^10.2.7",

View File

@@ -1,22 +1,5 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
FROM rust:1.90.0 AS build
WORKDIR /usr/src/labrinth
COPY . .
ARG GIT_HASH
RUN --mount=type=cache,target=/usr/src/labrinth/target \
--mount=type=cache,target=/usr/local/cargo,from=rust:1.89.0,source=/usr/local/cargo \
SQLX_OFFLINE=true cargo build --profile release-labrinth --package labrinth
FROM build AS artifacts
RUN --mount=type=cache,target=/usr/src/labrinth/target \
mkdir /labrinth \
&& cp /usr/src/labrinth/target/release-labrinth/labrinth /labrinth/labrinth \
&& cp -r /usr/src/labrinth/apps/labrinth/migrations /labrinth \
&& cp -r /usr/src/labrinth/apps/labrinth/assets /labrinth
FROM debian:trixie-slim FROM debian:trixie-slim
LABEL org.opencontainers.image.source=https://github.com/modrinth/code LABEL org.opencontainers.image.source=https://github.com/modrinth/code
@@ -28,7 +11,9 @@ RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates dumb-init curl \ && apt-get install -y --no-install-recommends ca-certificates dumb-init curl \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
COPY --from=artifacts /labrinth /labrinth COPY labrinth /labrinth/labrinth
COPY migrations /labrinth/migrations
COPY assets /labrinth/assets
WORKDIR /labrinth WORKDIR /labrinth
ENTRYPOINT ["dumb-init", "--"] ENTRYPOINT ["dumb-init", "--"]

View File

@@ -355,12 +355,12 @@ mod tests {
#[actix_rt::test] #[actix_rt::test]
async fn test_ping_server_success() { async fn test_ping_server_success() {
let _status = ping_server("mc.hypixel.net", None).await.unwrap(); let _status = ping_server("play.cubecraft.net", None).await.unwrap();
} }
#[actix_rt::test] #[actix_rt::test]
async fn test_follow_srv_record() { async fn test_follow_srv_record() {
_ = ping_server("hypixel.net", None).await.unwrap(); _ = ping_server("cubecraft.net", None).await.unwrap();
} }
#[actix_rt::test] #[actix_rt::test]
@@ -370,7 +370,7 @@ mod tests {
#[actix_rt::test] #[actix_rt::test]
async fn test_ping_zero_timeout() { async fn test_ping_zero_timeout() {
_ = ping_server("mc.hypixel.net", Some(Duration::ZERO)) _ = ping_server("play.cubecraft.net", Some(Duration::ZERO))
.await .await
.unwrap_err(); .unwrap_err();
} }

View File

@@ -1,59 +1,73 @@
{ {
"name": "@modrinth/monorepo", "name": "@modrinth/monorepo",
"version": "0.0.0", "version": "0.0.0",
"private": true, "private": true,
"scripts": { "scripts": {
"web:dev": "turbo run dev --filter=@modrinth/frontend", "web:dev": "turbo run dev --filter=@modrinth/frontend",
"web:build": "turbo run build --filter=@modrinth/frontend", "web:build": "turbo run build --filter=@modrinth/frontend",
"app:dev": "turbo run dev --filter=@modrinth/app", "app:dev": "turbo run dev --filter=@modrinth/app",
"app:build": "turbo run build --filter=@modrinth/app", "app:build": "turbo run build --filter=@modrinth/app",
"docs:dev": "turbo run dev --filter=@modrinth/docs", "docs:dev": "turbo run dev --filter=@modrinth/docs",
"pages:build": "NITRO_PRESET=cloudflare-pages pnpm --filter frontend run build", "pages:build": "NITRO_PRESET=cloudflare-pages pnpm --filter frontend run build",
"build": "turbo run build --continue", "build": "turbo run build --continue",
"lint": "turbo run lint lint:ancillary --continue", "lint": "turbo run lint lint:ancillary --continue",
"lint:ancillary": "prettier --check .github *.*", "lint:ancillary": "prettier --check .github *.*",
"test": "turbo run test --continue", "test": "turbo run test --continue",
"fix": "turbo run fix fix:ancillary --continue", "fix": "turbo run fix fix:ancillary --continue",
"fix:ancillary": "prettier --write .github *.*", "fix:ancillary": "prettier --write .github *.*",
"ci": "turbo run lint test --continue", "ci": "turbo run lint test --continue",
"prepr": "turbo run prepr --continue", "prepr": "turbo run prepr --continue",
"prepr:frontend": "turbo run prepr --filter=@modrinth/frontend --filter=@modrinth/app-frontend", "prepr:frontend": "turbo run prepr --filter=@modrinth/frontend --filter=@modrinth/app-frontend",
"prepr:frontend:lib": "turbo run prepr --filter=@modrinth/ui --filter=@modrinth/moderation --filter=@modrinth/assets --filter=@modrinth/blog --filter=@modrinth/api-client --filter=@modrinth/utils --filter=@modrinth/tooling-config", "prepr:frontend:lib": "turbo run prepr --filter=@modrinth/ui --filter=@modrinth/moderation --filter=@modrinth/assets --filter=@modrinth/blog --filter=@modrinth/api-client --filter=@modrinth/utils --filter=@modrinth/tooling-config",
"prepr:frontend:web": "turbo run prepr --filter=@modrinth/frontend", "prepr:frontend:web": "turbo run prepr --filter=@modrinth/frontend",
"prepr:frontend:app": "turbo run prepr --filter=@modrinth/app-frontend", "prepr:frontend:app": "turbo run prepr --filter=@modrinth/app-frontend",
"storybook": "pnpm --filter @modrinth/ui storybook", "storybook": "pnpm --filter @modrinth/ui storybook",
"build-storybook": "pnpm --filter @modrinth/ui build-storybook", "build-storybook": "pnpm --filter @modrinth/ui build-storybook",
"icons:add": "pnpm --filter @modrinth/assets icons:add", "icons:add": "pnpm --filter @modrinth/assets icons:add",
"changelog:collect": "node scripts/run.mjs collect-changelog", "changelog:collect": "node scripts/run.mjs collect-changelog",
"changelog:combine-for-app": "node scripts/run.mjs build-theseus-release-notes", "changelog:combine-for-app": "node scripts/run.mjs build-theseus-release-notes",
"scripts": "node scripts/run.mjs" "scripts": "node scripts/run.mjs"
}, },
"devDependencies": { "devDependencies": {
"@clack/prompts": "^1.0.0", "@clack/prompts": "^1.0.0",
"@modrinth/tooling-config": "workspace:*", "@modrinth/tooling-config": "workspace:*",
"@tailwindcss/container-queries": "^0.1.1", "@tailwindcss/container-queries": "^0.1.1",
"@types/node": "^20.1.0", "@types/node": "^24",
"@vue/compiler-dom": "^3.5.26", "@vue/compiler-dom": "^3.5.26",
"@vue/compiler-sfc": "^3.5.26", "@vue/compiler-sfc": "^3.5.26",
"chalk": "^5.6.2", "chalk": "^5.6.2",
"if-ci": "^3.0.0", "if-ci": "^3.0.0",
"keep-a-changelog": "^3.0.2", "keep-a-changelog": "^3.0.2",
"prettier": "^3.3.2", "prettier": "^3.3.2",
"turbo": "^2.5.4", "turbo": "^2.5.4",
"vue": "^3.5.13", "vue": "^3.5.13",
"yaml": "^2.8.2" "yaml": "^2.8.2"
}, },
"packageManager": "pnpm@9.15.0", "packageManager": "pnpm@10.33.2",
"pnpm": { "engines": {
"patchedDependencies": { "node": ">=24.15.0"
"readable-stream@2.3.8": "patches/readable-stream@2.3.8.patch" },
}, "pnpm": {
"peerDependencyRules": { "patchedDependencies": {
"allowedVersions": { "readable-stream@2.3.8": "patches/readable-stream@2.3.8.patch"
"vite": "8", },
"esbuild": "0" "peerDependencyRules": {
} "allowedVersions": {
} "vite": "8",
}, "esbuild": "0"
"prettier": "@modrinth/tooling-config/prettier.config.cjs" }
},
"onlyBuiltDependencies": [
"@parcel/watcher",
"@sentry/cli",
"core-js",
"esbuild",
"protobufjs",
"sharp",
"unrs-resolver",
"vue-demi",
"workerd"
]
},
"prettier": "@modrinth/tooling-config/prettier.config.cjs"
} }

View File

@@ -213,7 +213,7 @@ impl DirectoryInfo {
.as_ref() .as_ref()
.map_or_else(|| app_dir.clone(), PathBuf::from); .map_or_else(|| app_dir.clone(), PathBuf::from);
async fn is_dir_writeable( async fn is_dir_writable(
new_config_dir: &Path, new_config_dir: &Path,
) -> crate::Result<bool> { ) -> crate::Result<bool> {
let temp_path = new_config_dir.join(".tmp"); let temp_path = new_config_dir.join(".tmp");
@@ -259,8 +259,8 @@ impl DirectoryInfo {
) )
.await?; .await?;
if !is_dir_writeable(&move_dir).await? { if !is_dir_writable(&move_dir).await? {
return Err(crate::ErrorKind::DirectoryMoveError(format!("Cannot move directory to {}: directory is not writeable", move_dir.display())).into()); return Err(crate::ErrorKind::DirectoryMoveError(format!("Cannot move directory to {}: directory is not writable", move_dir.display())).into());
} }
const MOVE_DIRS: &[&str] = &[ const MOVE_DIRS: &[&str] = &[

View File

@@ -14,7 +14,7 @@
}, },
"devDependencies": { "devDependencies": {
"@modrinth/tooling-config": "workspace:*", "@modrinth/tooling-config": "workspace:*",
"@types/node": "^20.1.0", "@types/node": "^24",
"jiti": "^2.4.2", "jiti": "^2.4.2",
"lucide-static": "^0.562.0", "lucide-static": "^0.562.0",
"vue": "^3.5.13" "vue": "^3.5.13"

View File

@@ -31,19 +31,24 @@
"prettier": "^3.6.2", "prettier": "^3.6.2",
"typescript": ">=5.0.0" "typescript": ">=5.0.0"
}, },
"devDependencies": { "dependencies": {
"@eslint/js": "^9.32.0",
"@prettier/plugin-xml": "^3.4.2", "@prettier/plugin-xml": "^3.4.2",
"prettier-plugin-sql-cst": "^0.13.0",
"prettier-plugin-toml": "^2.0.6"
},
"devDependencies": {
"@eslint/compat": "^1.4.1",
"@eslint/js": "^9.32.0",
"@nuxt/eslint-config": "^0.5.7",
"@vue/tsconfig": "^0.7.0", "@vue/tsconfig": "^0.7.0",
"eslint": "^9.32.0", "eslint": "^9.32.0",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.3", "eslint-plugin-prettier": "^5.5.3",
"eslint-plugin-simple-import-sort": "^12.1.1", "eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-turbo": "^2.5.4",
"eslint-plugin-vue": "^10.4.0", "eslint-plugin-vue": "^10.4.0",
"vue-eslint-parser": "^10.1.3", "vue-eslint-parser": "^10.1.3",
"globals": "^16.3.0", "globals": "^16.3.0",
"prettier-plugin-sql-cst": "^0.13.0",
"prettier-plugin-toml": "^2.0.6",
"typescript-eslint": "^8.38.0" "typescript-eslint": "^8.38.0"
} }
} }

606
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,4 @@
packages: packages:
- 'apps/*' - 'apps/*'
- 'packages/*' - 'packages/*'
minimumReleaseAge: 4320 # 3 days

View File

@@ -46,6 +46,12 @@
"NEXTEST_*", "NEXTEST_*",
"BUILD_ENV", "BUILD_ENV",
"PREVIEW" "PREVIEW"
],
"passThroughEnv": [
"SCCACHE_*",
"RUSTC_WRAPPER",
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY"
] ]
}, },
"lint": { "lint": {
@@ -57,6 +63,12 @@
"RUSTFLAGS", "RUSTFLAGS",
"FORCE_COLOR", "FORCE_COLOR",
"NEXTEST_*" "NEXTEST_*"
],
"passThroughEnv": [
"SCCACHE_*",
"RUSTC_WRAPPER",
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY"
] ]
}, },
"lint:ancillary": {}, "lint:ancillary": {},
@@ -76,6 +88,12 @@
"RUSTFLAGS", "RUSTFLAGS",
"FORCE_COLOR", "FORCE_COLOR",
"NEXTEST_*" "NEXTEST_*"
],
"passThroughEnv": [
"SCCACHE_*",
"RUSTC_WRAPPER",
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY"
] ]
}, },
"fix": {}, "fix": {},