mirror of
https://github.com/modrinth/code.git
synced 2026-07-31 13:16:38 +00:00
Compare commits
6
Commits
7abe6f8c73
...
8b753a52ad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b753a52ad | ||
|
|
a53c9c3771 | ||
|
|
919b235621 | ||
|
|
18b0b2848d | ||
|
|
65a3ac4b34 | ||
|
|
295db3fb7a |
@@ -34,13 +34,13 @@ runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Extract PR Number and Commit ID
|
||||
id: extract-pr-info
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
|
||||
with:
|
||||
script: |
|
||||
const githubRef = process.env.GITHUB_REF;
|
||||
@@ -90,20 +90,26 @@ runs:
|
||||
- name: Print PR Branch
|
||||
if: env.CAN_SKIP_CHECKS != 'false'
|
||||
shell: bash
|
||||
env:
|
||||
PR_BRANCH: ${{ steps.get-pr-branch.outputs.prBranch }}
|
||||
run: |
|
||||
echo "PR Branch: ${{ steps.get-pr-branch.outputs.prBranch }}"
|
||||
echo "PR Branch: $PR_BRANCH"
|
||||
|
||||
- name: Check if PR branch contains the Merge Queue target commit ID
|
||||
if: env.CAN_SKIP_CHECKS != 'false'
|
||||
shell: bash
|
||||
env:
|
||||
PR_BRANCH: ${{ steps.get-pr-branch.outputs.prBranch }}
|
||||
COMMIT_ID: ${{ steps.extract-pr-info.outputs.commitId }}
|
||||
TARGET_BRANCH: ${{ steps.extract-pr-info.outputs.targetBranchName }}
|
||||
run: |
|
||||
# Get the branch name from previous steps
|
||||
branch_name="origin/${{ steps.get-pr-branch.outputs.prBranch }}"
|
||||
commit_id="${{ steps.extract-pr-info.outputs.commitId }}"
|
||||
branch_name="origin/$PR_BRANCH"
|
||||
commit_id="$COMMIT_ID"
|
||||
|
||||
# Check if the branch history contains the commit
|
||||
if git branch -r --contains "$commit_id" | grep -q "$branch_name"; then
|
||||
echo "Branch '$branch_name' contains commit '$commit_id'. It is up to date with ${{ steps.extract-pr-info.outputs.targetBranchName }}."
|
||||
if git branch -r --contains "$commit_id" | grep -qF "$branch_name"; then
|
||||
echo "Branch '$branch_name' contains commit '$commit_id'. It is up to date with $TARGET_BRANCH."
|
||||
else
|
||||
echo "Branch '$branch_name' does not contain commit '$commit_id'. It is outdated. Setting CAN_SKIP_CHECKS to false."
|
||||
echo "CAN_SKIP_CHECKS=false" >> "$GITHUB_ENV"
|
||||
@@ -112,8 +118,10 @@ runs:
|
||||
- name: Compare PR Branch with Current Branch
|
||||
if: env.CAN_SKIP_CHECKS != 'false'
|
||||
shell: bash
|
||||
env:
|
||||
PR_BRANCH: ${{ steps.get-pr-branch.outputs.prBranch }}
|
||||
run: |
|
||||
if git diff --quiet "origin/${{ steps.get-pr-branch.outputs.prBranch }}"; then
|
||||
if git diff --quiet "origin/$PR_BRANCH"; then
|
||||
echo "No differences found. PR branch is identical with this merge queue branch."
|
||||
else
|
||||
echo "Differences detected. PR branch has been updated after PR was added to merge queue. Setting CAN_SKIP_CHECKS to false."
|
||||
@@ -122,9 +130,11 @@ runs:
|
||||
|
||||
- name: Compute/publish skip result
|
||||
id: passed-checks
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
|
||||
env:
|
||||
SECRET: ${{ inputs.secret }}
|
||||
PR_BRANCH: ${{ steps.get-pr-branch.outputs.prBranch }}
|
||||
TARGET_BRANCH: ${{ steps.extract-pr-info.outputs.targetBranchName }}
|
||||
with:
|
||||
github-token: ${{ inputs.secret != '' && inputs.secret || github.token }}
|
||||
script: |
|
||||
@@ -144,7 +154,7 @@ runs:
|
||||
const { data: branchProtection } = await github.rest.repos.getBranchProtection({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
branch: "${{ steps.extract-pr-info.outputs.targetBranchName }}",
|
||||
branch: process.env.TARGET_BRANCH,
|
||||
});
|
||||
const requiredCheckNames = branchProtection.required_status_checks.contexts;
|
||||
console.log(`requiredCheckNames = ${requiredCheckNames}`);
|
||||
@@ -152,7 +162,7 @@ runs:
|
||||
const { data: checks } = await github.rest.checks.listForRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: "refs/heads/${{ steps.get-pr-branch.outputs.prBranch }}",
|
||||
ref: `refs/heads/${process.env.PR_BRANCH}`,
|
||||
});
|
||||
|
||||
console.log(`checks.check_runs = ${checks.check_runs.map(check => `${check.status},${check.conclusion},${check.name};`)}`);
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
name: Deploy Command
|
||||
run-name: Deploy PR #${{ github.event.client_payload.github.payload.issue.number }}
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [deploy-command]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
if: ${{ github.event.client_payload.pull_request.head.repo.full_name == github.repository }}
|
||||
uses: SparkUniverse/workflows/.github/workflows/deploy-command.yaml@main
|
||||
secrets:
|
||||
ARGOCD_DEPLOY_KEY: ${{ secrets.ARGOCD_DEPLOY_KEY }}
|
||||
CMD_DISPATCH_GH_TOKEN: ${{ secrets.SLASH_CMD_GH_TOKEN }}
|
||||
with:
|
||||
application-set: labrinth
|
||||
build-workflow: labrinth-build.yml
|
||||
branch: ${{ github.event.client_payload.pull_request.head.ref }}
|
||||
issue-number: ${{ github.event.client_payload.github.payload.issue.number }}
|
||||
head-sha: ${{ github.event.client_payload.pull_request.head.sha }}
|
||||
@@ -1,18 +1,19 @@
|
||||
name: docker-build
|
||||
name: Labrinth Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
- 'prod'
|
||||
paths:
|
||||
- .github/workflows/labrinth-docker.yml
|
||||
- .github/workflows/labrinth-build.yml
|
||||
- 'apps/labrinth/**'
|
||||
- Cargo.toml
|
||||
- Cargo.lock
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
paths:
|
||||
- .github/workflows/labrinth-docker.yml
|
||||
- .github/workflows/labrinth-build.yml
|
||||
- 'apps/labrinth/**'
|
||||
- Cargo.toml
|
||||
- Cargo.lock
|
||||
@@ -69,7 +70,8 @@ jobs:
|
||||
echo "skip=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
docker:
|
||||
build:
|
||||
name: Build Labrinth
|
||||
runs-on: ${{ needs.skip-if-clean.outputs.internal == 'true' && 'namespace-profile-modrinth-labrinth' || 'ubuntu-latest' }}
|
||||
needs: [skip-if-clean]
|
||||
if: ${{ needs.skip-if-clean.outputs.skip != 'true' }}
|
||||
@@ -120,42 +122,30 @@ jobs:
|
||||
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@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
|
||||
|
||||
- name: Generate Docker image metadata
|
||||
id: docker-meta
|
||||
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
|
||||
env:
|
||||
# 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
|
||||
# image manifest only. See:
|
||||
# https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#adding-a-description-to-multi-arch-images
|
||||
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
|
||||
- name: Upload Docker context
|
||||
if: needs.skip-if-clean.outputs.internal == 'true'
|
||||
uses: namespace-actions/upload-artifact@f6ccaacc655aec41b93af180d1d7eef21af862d2 # v1.0.3
|
||||
with:
|
||||
images: ghcr.io/modrinth/labrinth
|
||||
labels: |
|
||||
org.opencontainers.image.title=labrinth
|
||||
org.opencontainers.image.description=Modrinth API
|
||||
org.opencontainers.image.licenses=AGPL-3.0-only
|
||||
annotations: |
|
||||
org.opencontainers.image.title=labrinth
|
||||
org.opencontainers.image.description=Modrinth API
|
||||
org.opencontainers.image.licenses=AGPL-3.0-only
|
||||
name: labrinth-docker-context
|
||||
retention-days: 1
|
||||
path: apps/labrinth/docker-stage
|
||||
|
||||
- name: Login to GitHub Packages
|
||||
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
docker-build:
|
||||
needs: [skip-if-clean, build]
|
||||
if: ${{ needs.skip-if-clean.outputs.internal == 'true' }}
|
||||
uses: SparkUniverse/workflows/.github/workflows/docker-build.yaml@main
|
||||
with:
|
||||
image-name: labrinth
|
||||
dockerfile-path: apps/labrinth/Dockerfile
|
||||
artifacts-name: labrinth-docker-context
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
||||
with:
|
||||
context: ./apps/labrinth/docker-stage
|
||||
file: ./apps/labrinth/Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.docker-meta.outputs.tags }}
|
||||
labels: ${{ steps.docker-meta.outputs.labels }}
|
||||
annotations: ${{ steps.docker-meta.outputs.annotations }}
|
||||
deploy:
|
||||
needs: [skip-if-clean, docker-build]
|
||||
if: ${{ needs.skip-if-clean.outputs.internal == 'true' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/prod') }}
|
||||
uses: SparkUniverse/workflows/.github/workflows/argo-update.yaml@main
|
||||
secrets:
|
||||
ARGOCD_DEPLOY_KEY: ${{ secrets.ARGOCD_DEPLOY_KEY }}
|
||||
with:
|
||||
application-set: labrinth
|
||||
branch: ${{ github.ref == 'refs/heads/prod' && 'main' || 'develop' }}
|
||||
environment-name: ${{ github.ref == 'refs/heads/prod' && 'production' || 'staging' }}
|
||||
@@ -0,0 +1,20 @@
|
||||
name: Slash Command Dispatch
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
dispatch-command:
|
||||
if: ${{ github.event.sender.type == 'User' && contains(fromJSON('["OWNER", "MEMBER"]'), github.event.comment.author_association) }}
|
||||
runs-on: namespace-profile-tiny-arm64
|
||||
steps:
|
||||
- name: Slash Command Dispatch
|
||||
uses: peter-evans/slash-command-dispatch@9bdcd7914ec1b75590b790b844aa3b8eee7c683a # v5.0.2
|
||||
with:
|
||||
token: ${{ secrets.SLASH_CMD_GH_TOKEN }}
|
||||
issue-type: pull-request
|
||||
commands: |
|
||||
deploy
|
||||
@@ -30,6 +30,29 @@ const normalizeAuthToken = (value: unknown) => {
|
||||
return ''
|
||||
}
|
||||
|
||||
const getErrorStatus = (error: unknown): number | undefined => {
|
||||
if (!error || typeof error !== 'object') {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const typedError = error as { statusCode?: unknown; status?: unknown }
|
||||
const status = typedError.statusCode ?? typedError.status
|
||||
|
||||
return typeof status === 'number' ? status : undefined
|
||||
}
|
||||
|
||||
// only when labrinth actually gives us an auth error
|
||||
const isAuthFailure = (error: unknown): boolean => {
|
||||
const status = getErrorStatus(error)
|
||||
return status === 401 || status === 403
|
||||
}
|
||||
|
||||
const clearAuthCookie = (auth: AuthState, authCookie: { value: string | null }) => {
|
||||
authCookie.value = null
|
||||
auth.token = ''
|
||||
auth.user = null
|
||||
}
|
||||
|
||||
const getQueryString = (value: QueryValue) => {
|
||||
if (Array.isArray(value)) {
|
||||
return value[0] ?? null
|
||||
@@ -90,6 +113,7 @@ export const initAuth = async (oldToken: string | null | undefined = null) => {
|
||||
}
|
||||
|
||||
const tokenStr = normalizeAuthToken(authCookie.value)
|
||||
let shouldRefresh = false
|
||||
|
||||
if (authCookie.value != null && tokenStr === '') {
|
||||
authCookie.value = null
|
||||
@@ -111,12 +135,13 @@ export const initAuth = async (oldToken: string | null | undefined = null) => {
|
||||
},
|
||||
true,
|
||||
)) as Labrinth.Users.v2.User
|
||||
} catch {
|
||||
/* empty */
|
||||
} catch (error) {
|
||||
// only refresh when the token was rejected. not on timeouts or other errors (think this was the cause of random logouts)
|
||||
shouldRefresh = isAuthFailure(error)
|
||||
}
|
||||
}
|
||||
|
||||
if (!auth.user && auth.token) {
|
||||
if (!auth.user && auth.token && shouldRefresh) {
|
||||
try {
|
||||
const session = (await useBaseFetch(
|
||||
'session/refresh',
|
||||
@@ -132,22 +157,29 @@ export const initAuth = async (oldToken: string | null | undefined = null) => {
|
||||
auth.token = normalizeAuthToken(session.session)
|
||||
if (auth.token) {
|
||||
authCookie.value = auth.token
|
||||
auth.user = (await useBaseFetch(
|
||||
'user',
|
||||
{
|
||||
apiVersion: 3,
|
||||
headers: {
|
||||
Authorization: auth.token,
|
||||
try {
|
||||
auth.user = (await useBaseFetch(
|
||||
'user',
|
||||
{
|
||||
apiVersion: 3,
|
||||
headers: {
|
||||
Authorization: auth.token,
|
||||
},
|
||||
},
|
||||
},
|
||||
true,
|
||||
)) as Labrinth.Users.v2.User
|
||||
true,
|
||||
)) as Labrinth.Users.v2.User
|
||||
} catch (error) {
|
||||
if (isAuthFailure(error)) {
|
||||
clearAuthCookie(auth, authCookie)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
authCookie.value = null
|
||||
auth.token = ''
|
||||
clearAuthCookie(auth, authCookie)
|
||||
}
|
||||
} catch (error) {
|
||||
if (isAuthFailure(error)) {
|
||||
clearAuthCookie(auth, authCookie)
|
||||
}
|
||||
} catch {
|
||||
authCookie.value = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends ca-certificates dumb-init curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY labrinth /labrinth/labrinth
|
||||
COPY --chmod=0755 labrinth /labrinth/labrinth
|
||||
COPY migrations /labrinth/migrations
|
||||
COPY assets /labrinth/assets
|
||||
|
||||
|
||||
@@ -10,6 +10,12 @@ export type VersionEntry = {
|
||||
}
|
||||
|
||||
const VERSIONS: VersionEntry[] = [
|
||||
{
|
||||
date: `2026-07-31T06:10:23+00:00`,
|
||||
product: 'web',
|
||||
body: `## Fixed
|
||||
- Fixed randomly getting signed out of Modrinth account due to random non-auth related errors.`,
|
||||
},
|
||||
{
|
||||
date: `2026-07-29T21:32:06+00:00`,
|
||||
product: 'app',
|
||||
|
||||
Reference in New Issue
Block a user