committed by
GitHub
72 changed files with 1957 additions and 325 deletions
@ -0,0 +1,29 @@ |
|||||
|
--- |
||||
|
title: "LinuxGSM PR Review Guidance" |
||||
|
applyTo: "**" |
||||
|
description: "Use when reviewing pull requests in LinuxGSM; prioritize regressions, behavior changes, shell safety, and missing tests over style-only feedback." |
||||
|
--- |
||||
|
|
||||
|
Focus review effort on correctness and operational safety first. |
||||
|
|
||||
|
Primary priorities: |
||||
|
|
||||
|
- Identify behavior regressions and compatibility risks. |
||||
|
- Flag unsafe shell patterns (`rm -rf`, unquoted vars, unchecked command failures). |
||||
|
- Verify workflow changes do not weaken permissions or secret handling. |
||||
|
- Check for missing tests/validation when logic changes. |
||||
|
- Confirm labels, templates, and automation rules stay internally consistent. |
||||
|
|
||||
|
Feedback expectations: |
||||
|
|
||||
|
- Give concrete, actionable findings with file and reason. |
||||
|
- Prefer high-signal issues over style nits. |
||||
|
- If no defects are found, state that clearly and mention residual risk areas. |
||||
|
- Suggest minimal, low-risk fixes before proposing broad refactors. |
||||
|
|
||||
|
LinuxGSM-specific checks: |
||||
|
|
||||
|
- Shell scripts should preserve robust defaults (`set -euo pipefail` where appropriate). |
||||
|
- Label/workflow updates should avoid duplicate or stale taxonomy. |
||||
|
- Automation should fail safe (log and continue for advisory AI; block on true CI errors). |
||||
|
- Keep issue/PR automation rules aligned with templates and existing labels. |
||||
@ -0,0 +1,50 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
ref="${LGSM_REF:-${GITHUB_REF#refs/heads/}}" |
||||
|
curl "https://raw.githubusercontent.com/GameServerManagers/LinuxGSM/${ref}/lgsm/data/serverlist.csv" | grep -v '^[[:blank:]]*$' > serverlist.csv |
||||
|
|
||||
|
echo -n "{" > "shortnamearray.json" |
||||
|
echo -n "\"include\":[" >> "shortnamearray.json" |
||||
|
|
||||
|
while read -r line; do |
||||
|
shortname=$(echo "$line" | awk -F, '{ print $1 }') |
||||
|
# If TARGETED_SHORTNAMES is set, skip servers not in the list |
||||
|
if [ -n "${TARGETED_SHORTNAMES:-}" ]; then |
||||
|
if ! echo "${TARGETED_SHORTNAMES}" | grep -qw "${shortname}"; then |
||||
|
continue |
||||
|
fi |
||||
|
fi |
||||
|
export shortname |
||||
|
servername=$(echo "$line" | awk -F, '{ print $2 }') |
||||
|
export servername |
||||
|
gamename=$(echo "$line" | awk -F, '{ print $3 }') |
||||
|
export gamename |
||||
|
distro=$(echo "$line" | awk -F, '{ print $4 }') |
||||
|
export distro |
||||
|
# Legacy servers that require older Ubuntu/Debian versions due to glibc compatibility |
||||
|
case "${shortname}" in |
||||
|
bfv | bf1942) |
||||
|
# Requires Ubuntu <= 22.04 or Debian <= 12 (glibc 2.31 compatible) |
||||
|
runner="ubuntu-22.04" |
||||
|
;; |
||||
|
btl | onset) |
||||
|
# Requires Ubuntu <= 20.04 or Debian <= 11 (glibc 2.31 compatible) |
||||
|
runner="ubuntu-20.04" |
||||
|
;; |
||||
|
*) |
||||
|
runner="ubuntu-latest" |
||||
|
;; |
||||
|
esac |
||||
|
{ |
||||
|
echo -n "{" |
||||
|
echo -n "\"shortname\":" |
||||
|
echo -n "\"${shortname}\"" |
||||
|
echo -n ",\"runner\":" |
||||
|
echo -n "\"${runner}\"" |
||||
|
echo -n "}," |
||||
|
} >> "shortnamearray.json" |
||||
|
done < <(tail -n +2 serverlist.csv) |
||||
|
sed -i '$ s/.$//' "shortnamearray.json" |
||||
|
echo -n "]" >> "shortnamearray.json" |
||||
|
echo -n "}" >> "shortnamearray.json" |
||||
|
rm serverlist.csv |
||||
@ -0,0 +1,87 @@ |
|||||
|
#!/usr/bin/env bash |
||||
|
# sync-game-labels.sh |
||||
|
# Reads lgsm/data/serverlist.csv and ensures a "game: <name>" label exists in |
||||
|
# the GitHub repo for every unique game name. Safe to run multiple times. |
||||
|
# |
||||
|
# Requires: gh CLI authenticated with issues:write scope. |
||||
|
# Usage: .github/scripts/sync-game-labels.sh [OWNER/REPO] |
||||
|
# |
||||
|
# The OWNER/REPO argument is optional; if omitted gh uses the current repo. |
||||
|
|
||||
|
set -euo pipefail |
||||
|
|
||||
|
REPO="${1:-}" |
||||
|
SERVERLIST="lgsm/data/serverlist.csv" |
||||
|
LABEL_COLOR="5b21b6" |
||||
|
LABEL_PREFIX="game: " |
||||
|
|
||||
|
normalize_label() { |
||||
|
printf '%s' "$1" | tr '[:upper:]' '[:lower:]' |
||||
|
} |
||||
|
|
||||
|
if [[ ! -f "${SERVERLIST}" ]]; then |
||||
|
echo "ERROR: ${SERVERLIST} not found. Run from the repository root." |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
declare -A EXISTING_COLORS=() |
||||
|
declare -A EXISTING_DESCRIPTIONS=() |
||||
|
declare -A EXISTING_NAMES=() |
||||
|
|
||||
|
# Fetch all existing game label metadata once (up to 1000) and cache locally. |
||||
|
echo "Fetching existing labels..." |
||||
|
while IFS=$'\t' read -r NAME COLOR DESCRIPTION; do |
||||
|
[[ -n "${NAME}" ]] || continue |
||||
|
EXISTING_COLORS["${NAME}"]="${COLOR}" |
||||
|
EXISTING_DESCRIPTIONS["${NAME}"]="${DESCRIPTION}" |
||||
|
EXISTING_NAMES["$(normalize_label "${NAME}")"]="${NAME}" |
||||
|
done < <( |
||||
|
gh label list --limit 1000 --json name,color,description ${REPO:+--repo "$REPO"} \ |
||||
|
| jq -r '.[] | select(.name | startswith("game: ")) | [.name, .color, (.description // "")] | @tsv' |
||||
|
) |
||||
|
|
||||
|
# Parse unique game names from the CSV (column 3, skip header). |
||||
|
mapfile -t GAMES < <( |
||||
|
tail -n +2 "${SERVERLIST}" \ |
||||
|
| cut -d',' -f3 \ |
||||
|
| sort -u |
||||
|
) |
||||
|
|
||||
|
CREATED=0 |
||||
|
UPDATED=0 |
||||
|
UNCHANGED=0 |
||||
|
|
||||
|
for GAME in "${GAMES[@]}"; do |
||||
|
LABEL="${LABEL_PREFIX}${GAME}" |
||||
|
DESCRIPTION="Issues related to ${GAME}" |
||||
|
NORMALIZED_LABEL="$(normalize_label "${LABEL}")" |
||||
|
|
||||
|
if [[ -v EXISTING_NAMES["${NORMALIZED_LABEL}"] ]]; then |
||||
|
CURRENT_LABEL="${EXISTING_NAMES["${NORMALIZED_LABEL}"]}" |
||||
|
CURRENT_COLOR="${EXISTING_COLORS["${CURRENT_LABEL}"]}" |
||||
|
CURRENT_DESCRIPTION="${EXISTING_DESCRIPTIONS["${CURRENT_LABEL}"]}" |
||||
|
|
||||
|
if [[ "${CURRENT_LABEL}" != "${LABEL}" || "${CURRENT_COLOR}" != "${LABEL_COLOR}" || "${CURRENT_DESCRIPTION}" != "${DESCRIPTION}" ]]; then |
||||
|
echo " update ${LABEL}" |
||||
|
gh label edit "${CURRENT_LABEL}" \ |
||||
|
--name "${LABEL}" \ |
||||
|
--color "${LABEL_COLOR}" \ |
||||
|
--description "${DESCRIPTION}" \ |
||||
|
${REPO:+--repo "$REPO"} |
||||
|
((UPDATED++)) || true |
||||
|
else |
||||
|
echo " ok ${LABEL}" |
||||
|
((UNCHANGED++)) || true |
||||
|
fi |
||||
|
else |
||||
|
echo " create ${LABEL}" |
||||
|
gh label create "${LABEL}" \ |
||||
|
--color "${LABEL_COLOR}" \ |
||||
|
--description "${DESCRIPTION}" \ |
||||
|
${REPO:+--repo "$REPO"} |
||||
|
((CREATED++)) || true |
||||
|
fi |
||||
|
done |
||||
|
|
||||
|
echo "" |
||||
|
echo "Done. Created: ${CREATED} Updated: ${UPDATED} Unchanged: ${UNCHANGED}" |
||||
@ -1,29 +0,0 @@ |
|||||
name: Update copyright year(s) in license file |
|
||||
|
|
||||
on: |
|
||||
workflow_dispatch: |
|
||||
schedule: |
|
||||
- cron: "0 3 1 1 *" # 03:00 AM on January 1 |
|
||||
|
|
||||
permissions: |
|
||||
contents: write |
|
||||
|
|
||||
jobs: |
|
||||
update-license-year: |
|
||||
runs-on: ubuntu-latest |
|
||||
steps: |
|
||||
- name: Checkout |
|
||||
uses: actions/checkout@v6 |
|
||||
with: |
|
||||
fetch-depth: 0 |
|
||||
persist-credentials: false |
|
||||
- name: Action Update License Year |
|
||||
uses: FantasticFiasco/action-update-license-year@v3 |
|
||||
with: |
|
||||
token: ${{ secrets.GITHUB_TOKEN }} |
|
||||
path: LICENSE.md |
|
||||
- name: Merge pull request |
|
||||
env: |
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
||||
run: | |
|
||||
gh pr merge --merge --delete-branch |
|
||||
@ -0,0 +1,243 @@ |
|||||
|
name: AI Issue Triage |
||||
|
on: |
||||
|
issues: |
||||
|
types: |
||||
|
- opened |
||||
|
- edited |
||||
|
|
||||
|
# Note: This workflow uses GitHub Models which may not be available |
||||
|
# in all environments. If GitHub Models API returns 401 or is unavailable, |
||||
|
# the workflow will skip gracefully and the issue will still be processed |
||||
|
# by other automation (labeler, etc.) |
||||
|
|
||||
|
permissions: |
||||
|
issues: write |
||||
|
contents: read |
||||
|
models: read |
||||
|
|
||||
|
jobs: |
||||
|
ai-triage: |
||||
|
if: github.repository_owner == 'GameServerManagers' |
||||
|
runs-on: ubuntu-latest |
||||
|
steps: |
||||
|
- name: Triage issue with GitHub Models |
||||
|
uses: actions/github-script@v7 |
||||
|
env: |
||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
||||
|
with: |
||||
|
script: | |
||||
|
const title = context.payload.issue.title || ''; |
||||
|
const body = context.payload.issue.body || ''; |
||||
|
const number = context.payload.issue.number; |
||||
|
const owner = context.repo.owner; |
||||
|
const repo = context.repo.repo; |
||||
|
const AI_MARKER = '<!-- ai-triage -->'; |
||||
|
|
||||
|
function parseTriageResponse(raw) { |
||||
|
const input = (raw || '').trim(); |
||||
|
if (!input) return {}; |
||||
|
|
||||
|
const candidates = [input]; |
||||
|
const fenced = input.match(/```(?:json)?\s*([\s\S]*?)```/i); |
||||
|
if (fenced?.[1]) candidates.push(fenced[1].trim()); |
||||
|
|
||||
|
const firstBrace = input.indexOf('{'); |
||||
|
const lastBrace = input.lastIndexOf('}'); |
||||
|
if (firstBrace !== -1 && lastBrace > firstBrace) { |
||||
|
candidates.push(input.slice(firstBrace, lastBrace + 1)); |
||||
|
} |
||||
|
|
||||
|
for (const candidate of candidates) { |
||||
|
try { |
||||
|
return JSON.parse(candidate); |
||||
|
} catch (_err) { |
||||
|
// Continue trying fallbacks. |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return {}; |
||||
|
} |
||||
|
|
||||
|
// For short bodies, apply "needs: more info" label directly. |
||||
|
// Skip the AI call but still label the issue. |
||||
|
const isShortBody = body.trim().length < 80; |
||||
|
if (isShortBody) { |
||||
|
try { |
||||
|
await github.rest.issues.addLabels({ |
||||
|
owner, repo, issue_number: number, |
||||
|
labels: ['needs: more info'], |
||||
|
}); |
||||
|
} catch (err) { |
||||
|
console.log('Could not apply label for short body:', err.message); |
||||
|
} |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// ── Call GitHub Models ──────────────────────────────────────── |
||||
|
// Note: GitHub Models access may not be available in all environments. |
||||
|
// If the API returns 401 (Unauthorized), it means GitHub Models is not |
||||
|
// enabled for this repository or the current token lacks access. |
||||
|
// The workflow will gracefully skip AI triage and continue. |
||||
|
let triage; |
||||
|
try { |
||||
|
const res = await fetch( |
||||
|
`https://models.github.ai/orgs/${owner}/inference/chat/completions`, |
||||
|
{ |
||||
|
method: 'POST', |
||||
|
headers: { |
||||
|
'Accept': 'application/vnd.github+json', |
||||
|
'Authorization': `Bearer ${process.env.GITHUB_TOKEN}`, |
||||
|
'X-GitHub-Api-Version': '2026-03-10', |
||||
|
'Content-Type': 'application/json', |
||||
|
}, |
||||
|
body: JSON.stringify({ |
||||
|
model: 'openai/gpt-4.1-mini', |
||||
|
temperature: 0.1, |
||||
|
max_tokens: 400, |
||||
|
messages: [ |
||||
|
{ |
||||
|
role: 'system', |
||||
|
content: |
||||
|
'You are a triage assistant for LinuxGSM, an open-source ' + |
||||
|
'Linux game server manager. Your role is to:\n' + |
||||
|
'1. Analyze issue quality (completeness, clarity)\n' + |
||||
|
'2. Extract game names mentioned in the issue, even if misspelled or abbreviated\n' + |
||||
|
'3. Suggest corrections for likely typos using fuzzy matching\n' + |
||||
|
'4. Respond ONLY with a valid JSON object — no markdown fences.\n\n' + |
||||
|
'Common game name variations and typos you should recognize:\n' + |
||||
|
'- "Valhiem" → "Valheim"\n' + |
||||
|
'- "Rrust" → "Rust"\n' + |
||||
|
'- "Conterstrike" / "CS" / "CSGO" → "Counter-Strike: Global Offensive"\n' + |
||||
|
'- "Garrys" / "GMod" → "Garrys Mod"\n' + |
||||
|
'- "ARK" / "Ark" → "ARK: Survival Evolved"\n' + |
||||
|
'- "DayZ" / "Dayz" → "DayZ"\n' + |
||||
|
'- "Insurgency Sandstorm" / "Insurgency 2" → "Insurgency: Sandstorm"', |
||||
|
}, |
||||
|
{ |
||||
|
role: 'user', |
||||
|
content: |
||||
|
`Title: ${title}\n\nBody:\n${body.slice(0, 3000)}\n\n` + |
||||
|
'Respond with this JSON schema:\n' + |
||||
|
'{\n' + |
||||
|
' "quality": "good" | "ok" | "poor",\n' + |
||||
|
' "missing_info": ["list of specific missing fields"],\n' + |
||||
|
' "detected_game": "canonical game name if one is mentioned, or null",\n' + |
||||
|
' "game_confidence": "high" | "medium" | "low" | null,\n' + |
||||
|
' "game_note": "correction suggestion if the user misspelled a game name, or empty string",\n' + |
||||
|
' "comment": "one or two sentence note to the reporter, or empty string"\n' + |
||||
|
'}', |
||||
|
}, |
||||
|
], |
||||
|
}), |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
// GitHub Models may return 401 if not available for this repository. |
||||
|
// This is expected and not an error — the workflow simply skips AI triage. |
||||
|
if (!res.ok) { |
||||
|
console.log(`GitHub Models returned ${res.status} — skipping AI triage.`); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
const data = await res.json(); |
||||
|
const raw = data.choices?.[0]?.message?.content || '{}'; |
||||
|
triage = parseTriageResponse(raw); |
||||
|
} catch (err) { |
||||
|
// Never fail the workflow if the AI call errors — it's advisory only. |
||||
|
console.log('AI triage skipped:', err.message); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (!triage || typeof triage !== 'object') { |
||||
|
triage = {}; |
||||
|
} |
||||
|
|
||||
|
// ── Act on the result ──────────────────────────────────────── |
||||
|
const isPoor = triage.quality === 'poor'; |
||||
|
const missing = Array.isArray(triage.missing_info) ? triage.missing_info : []; |
||||
|
const hasIssues = isPoor || missing.length > 0; |
||||
|
|
||||
|
// Prepare labels to apply |
||||
|
const labelsToApply = []; |
||||
|
|
||||
|
// Check if a game was detected with high confidence |
||||
|
const detectedGame = triage.detected_game; |
||||
|
const gameConfidence = triage.game_confidence; |
||||
|
|
||||
|
if (detectedGame && gameConfidence === 'high') { |
||||
|
labelsToApply.push(`game: ${detectedGame}`); |
||||
|
} |
||||
|
|
||||
|
// Apply "needs: more info" label if quality issues detected |
||||
|
if (hasIssues) { |
||||
|
labelsToApply.push('needs: more info'); |
||||
|
} |
||||
|
|
||||
|
// Apply labels one-by-one so a single failure does not block all labels. |
||||
|
const uniqueLabels = [...new Set(labelsToApply)]; |
||||
|
for (const label of uniqueLabels) { |
||||
|
try { |
||||
|
await github.rest.issues.addLabels({ |
||||
|
owner, |
||||
|
repo, |
||||
|
issue_number: number, |
||||
|
labels: [label], |
||||
|
}); |
||||
|
} catch (err) { |
||||
|
console.log(`Could not apply label "${label}":`, err.message); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Post a comment only when there is something specific to say |
||||
|
const gameNote = triage.game_note || ''; |
||||
|
const reporterComment = triage.comment || ''; |
||||
|
|
||||
|
if (!hasIssues && !gameNote) return; |
||||
|
|
||||
|
const missingBlock = missing.length > 0 |
||||
|
? `\n\n**Missing information:**\n${missing.map(m => `- ${m}`).join('\n')}` |
||||
|
: ''; |
||||
|
|
||||
|
const gameBlock = gameNote |
||||
|
? `\n\n**Game name note:** ${gameNote}` |
||||
|
: ''; |
||||
|
|
||||
|
const triageCommentBody = |
||||
|
`${AI_MARKER}\n` + |
||||
|
`Thanks for opening this issue! 👋\n\n` + |
||||
|
`${reporterComment}` + |
||||
|
`${missingBlock}` + |
||||
|
`${gameBlock}\n\n` + |
||||
|
`_This note was generated automatically by AI triage and may not be perfect. ` + |
||||
|
`A maintainer will review shortly._`; |
||||
|
|
||||
|
try { |
||||
|
const comments = await github.rest.issues.listComments({ |
||||
|
owner, |
||||
|
repo, |
||||
|
issue_number: number, |
||||
|
per_page: 100, |
||||
|
}); |
||||
|
|
||||
|
const existingAiComment = comments.data.find( |
||||
|
(comment) => comment.user?.type === 'Bot' && comment.body?.includes(AI_MARKER) |
||||
|
); |
||||
|
|
||||
|
if (existingAiComment) { |
||||
|
await github.rest.issues.updateComment({ |
||||
|
owner, |
||||
|
repo, |
||||
|
comment_id: existingAiComment.id, |
||||
|
body: triageCommentBody, |
||||
|
}); |
||||
|
} else { |
||||
|
await github.rest.issues.createComment({ |
||||
|
owner, |
||||
|
repo, |
||||
|
issue_number: number, |
||||
|
body: triageCommentBody, |
||||
|
}); |
||||
|
} |
||||
|
} catch (err) { |
||||
|
console.log('Could not post comment:', err.message); |
||||
|
} |
||||
@ -1,27 +0,0 @@ |
|||||
#!/bin/bash |
|
||||
|
|
||||
curl "https://raw.githubusercontent.com/GameServerManagers/LinuxGSM/${GITHUB_REF#refs/heads/}/lgsm/data/serverlist.csv" | grep -v '^[[:blank:]]*$' > serverlist.csv |
|
||||
|
|
||||
echo -n "{" > "shortnamearray.json" |
|
||||
echo -n "\"include\":[" >> "shortnamearray.json" |
|
||||
|
|
||||
while read -r line; do |
|
||||
shortname=$(echo "$line" | awk -F, '{ print $1 }') |
|
||||
export shortname |
|
||||
servername=$(echo "$line" | awk -F, '{ print $2 }') |
|
||||
export servername |
|
||||
gamename=$(echo "$line" | awk -F, '{ print $3 }') |
|
||||
export gamename |
|
||||
distro=$(echo "$line" | awk -F, '{ print $4 }') |
|
||||
export distro |
|
||||
{ |
|
||||
echo -n "{"; |
|
||||
echo -n "\"shortname\":"; |
|
||||
echo -n "\"${shortname}\""; |
|
||||
echo -n "},"; |
|
||||
} >> "shortnamearray.json" |
|
||||
done < <(tail -n +2 serverlist.csv) |
|
||||
sed -i '$ s/.$//' "shortnamearray.json" |
|
||||
echo -n "]" >> "shortnamearray.json" |
|
||||
echo -n "}" >> "shortnamearray.json" |
|
||||
rm serverlist.csv |
|
||||
@ -4,14 +4,24 @@ on: |
|||||
types: |
types: |
||||
- opened |
- opened |
||||
- edited |
- edited |
||||
|
pull_request: |
||||
|
types: |
||||
|
- opened |
||||
|
- edited |
||||
|
- synchronize |
||||
|
- reopened |
||||
|
|
||||
permissions: |
permissions: |
||||
issues: write |
issues: write |
||||
|
pull-requests: write |
||||
contents: read |
contents: read |
||||
|
|
||||
|
env: |
||||
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" |
||||
|
|
||||
jobs: |
jobs: |
||||
issue-labeler: |
issue-labeler: |
||||
if: github.repository_owner == 'GameServerManagers' |
if: github.repository_owner == 'GameServerManagers' && github.event_name == 'issues' |
||||
runs-on: ubuntu-latest |
runs-on: ubuntu-latest |
||||
steps: |
steps: |
||||
- name: Issue Labeler |
- name: Issue Labeler |
||||
@ -21,12 +31,28 @@ jobs: |
|||||
configuration-path: .github/labeler.yml |
configuration-path: .github/labeler.yml |
||||
enable-versioned-regex: 0 |
enable-versioned-regex: 0 |
||||
include-title: 1 |
include-title: 1 |
||||
|
sync-labels: 1 |
||||
|
|
||||
|
pr-labeler: |
||||
|
if: github.repository_owner == 'GameServerManagers' && github.event_name == 'pull_request' |
||||
|
runs-on: ubuntu-latest |
||||
|
steps: |
||||
|
- name: PR Labeler |
||||
|
uses: github/[email protected] |
||||
|
with: |
||||
|
repo-token: "${{ secrets.GITHUB_TOKEN }}" |
||||
|
configuration-path: .github/labeler.yml |
||||
|
enable-versioned-regex: 0 |
||||
|
include-title: 1 |
||||
|
include-body: 0 |
||||
|
sync-labels: 1 |
||||
|
|
||||
is-sponsor-label: |
is-sponsor-label: |
||||
if: github.repository_owner == 'GameServerManagers' |
if: github.repository_owner == 'GameServerManagers' && github.event_name == 'issues' |
||||
runs-on: ubuntu-latest |
runs-on: ubuntu-latest |
||||
steps: |
steps: |
||||
- name: Is Sponsor Label |
- name: Is Sponsor Label |
||||
|
if: github.event.action == 'opened' |
||||
uses: JasonEtco/is-sponsor-label-action@v2 |
uses: JasonEtco/is-sponsor-label-action@v2 |
||||
env: |
env: |
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
||||
|
|||||
@ -0,0 +1,28 @@ |
|||||
|
name: Sync Game Labels |
||||
|
on: |
||||
|
push: |
||||
|
branches: |
||||
|
- master |
||||
|
- develop |
||||
|
paths: |
||||
|
- "lgsm/data/serverlist.csv" |
||||
|
workflow_dispatch: {} |
||||
|
|
||||
|
permissions: |
||||
|
issues: write |
||||
|
contents: read |
||||
|
|
||||
|
jobs: |
||||
|
sync-game-labels: |
||||
|
if: github.repository_owner == 'GameServerManagers' |
||||
|
runs-on: ubuntu-latest |
||||
|
steps: |
||||
|
- name: Checkout |
||||
|
uses: actions/checkout@v5 |
||||
|
|
||||
|
- name: Sync game labels from serverlist |
||||
|
env: |
||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
||||
|
run: | |
||||
|
chmod +x .github/scripts/sync-game-labels.sh |
||||
|
.github/scripts/sync-game-labels.sh |
||||
@ -15,12 +15,22 @@ jobs: |
|||||
runs-on: ubuntu-latest |
runs-on: ubuntu-latest |
||||
steps: |
steps: |
||||
- name: Trigger Workflow and Wait (linuxgsm) |
- name: Trigger Workflow and Wait (linuxgsm) |
||||
uses: convictional/[email protected] |
env: |
||||
with: |
GH_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} |
||||
owner: GameServerManagers |
run: | |
||||
repo: docker-linuxgsm |
before=$(date -u +%Y-%m-%dT%H:%M:%SZ) |
||||
github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} |
gh workflow run action-docker-publish.yml --repo GameServerManagers/docker-linuxgsm |
||||
workflow_file_name: action-docker-publish.yml |
sleep 10 |
||||
|
run_id=$(gh run list \ |
||||
|
--workflow action-docker-publish.yml \ |
||||
|
--repo GameServerManagers/docker-linuxgsm \ |
||||
|
--created ">=${before}" \ |
||||
|
--limit 1 \ |
||||
|
--json databaseId \ |
||||
|
--jq '.[0].databaseId') |
||||
|
gh run watch "${run_id}" \ |
||||
|
--repo GameServerManagers/docker-linuxgsm \ |
||||
|
--exit-status |
||||
|
|
||||
trigger_build_docker-gameserver: |
trigger_build_docker-gameserver: |
||||
if: github.repository_owner == 'GameServerManagers' |
if: github.repository_owner == 'GameServerManagers' |
||||
@ -29,9 +39,19 @@ jobs: |
|||||
runs-on: ubuntu-latest |
runs-on: ubuntu-latest |
||||
steps: |
steps: |
||||
- name: Trigger Workflow and Wait (gameserver) |
- name: Trigger Workflow and Wait (gameserver) |
||||
uses: convictional/[email protected] |
env: |
||||
with: |
GH_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} |
||||
owner: GameServerManagers |
run: | |
||||
repo: docker-gameserver |
before=$(date -u +%Y-%m-%dT%H:%M:%SZ) |
||||
github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} |
gh workflow run action-docker-publish.yml --repo GameServerManagers/docker-gameserver |
||||
workflow_file_name: action-docker-publish.yml |
sleep 10 |
||||
|
run_id=$(gh run list \ |
||||
|
--workflow action-docker-publish.yml \ |
||||
|
--repo GameServerManagers/docker-gameserver \ |
||||
|
--created ">=${before}" \ |
||||
|
--limit 1 \ |
||||
|
--json databaseId \ |
||||
|
--jq '.[0].databaseId') |
||||
|
gh run watch "${run_id}" \ |
||||
|
--repo GameServerManagers/docker-gameserver \ |
||||
|
--exit-status |
||||
|
|||||
@ -0,0 +1,198 @@ |
|||||
|
################################## |
||||
|
######## Default Settings ######## |
||||
|
################################## |
||||
|
# DO NOT EDIT, ANY CHANGES WILL BE OVERWRITTEN! |
||||
|
# Copy settings from here and use them in either: |
||||
|
# common.cfg - applies settings to every instance. |
||||
|
# [instance].cfg - applies settings to a specific instance. |
||||
|
|
||||
|
#### Game Server Settings #### |
||||
|
|
||||
|
## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters |
||||
|
ip="0.0.0.0" |
||||
|
port="27015" |
||||
|
clientport="27005" |
||||
|
sourcetvport="27020" |
||||
|
defaultmap="crossfire" |
||||
|
maxplayers="24" |
||||
|
|
||||
|
## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters |
||||
|
startparameters="-game jbep3 -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers ${maxplayers}" |
||||
|
|
||||
|
#### LinuxGSM Settings #### |
||||
|
|
||||
|
## LinuxGSM Stats |
||||
|
# Send useful stats to LinuxGSM developers. |
||||
|
# https://docs.linuxgsm.com/configuration/linuxgsm-stats |
||||
|
# (on|off) |
||||
|
stats="off" |
||||
|
|
||||
|
## Notification Alerts |
||||
|
# (on|off) |
||||
|
|
||||
|
# Display IP | https://docs.linuxgsm.com/alerts#display-ip |
||||
|
displayip="" |
||||
|
|
||||
|
# More info | https://docs.linuxgsm.com/alerts#more-info |
||||
|
postalert="off" |
||||
|
|
||||
|
# Alert on Start/Stop/Restart |
||||
|
statusalert="off" |
||||
|
|
||||
|
# Discord Alerts | https://docs.linuxgsm.com/alerts/discord |
||||
|
discordalert="off" |
||||
|
discordwebhook="webhook" |
||||
|
|
||||
|
# Email Alerts | https://docs.linuxgsm.com/alerts/email |
||||
|
emailalert="off" |
||||
|
email="[email protected]" |
||||
|
emailfrom="" |
||||
|
|
||||
|
# Gotify Alerts | https://docs.linuxgsm.com/alerts/gotify |
||||
|
gotifyalert="off" |
||||
|
gotifytoken="token" |
||||
|
gotifywebhook="webhook" |
||||
|
|
||||
|
# IFTTT Alerts | https://docs.linuxgsm.com/alerts/ifttt |
||||
|
iftttalert="off" |
||||
|
ifttttoken="accesstoken" |
||||
|
iftttevent="linuxgsm_alert" |
||||
|
|
||||
|
# ntfy Alerts | https://docs.linuxgsm.com/alerts/ntfy |
||||
|
ntfyalert="off" |
||||
|
ntfytopic="LinuxGSM" |
||||
|
ntfyserver="https://ntfy.sh" |
||||
|
ntfytoken="" |
||||
|
ntfyusername="" |
||||
|
ntfypassword="" |
||||
|
ntfypriority="" |
||||
|
ntfytags="" |
||||
|
|
||||
|
# Pushbullet Alerts | https://docs.linuxgsm.com/alerts/pushbullet |
||||
|
pushbulletalert="off" |
||||
|
pushbullettoken="accesstoken" |
||||
|
channeltag="" |
||||
|
|
||||
|
# Pushover Alerts | https://docs.linuxgsm.com/alerts/pushover |
||||
|
pushoveralert="off" |
||||
|
pushovertoken="accesstoken" |
||||
|
pushoveruserkey="userkey" |
||||
|
|
||||
|
# Rocket.Chat Alerts | https://docs.linuxgsm.com/alerts/rocket.chat |
||||
|
rocketchatalert="off" |
||||
|
rocketchatwebhook="webhook" |
||||
|
|
||||
|
# Slack Alerts | https://docs.linuxgsm.com/alerts/slack |
||||
|
slackalert="off" |
||||
|
slackwebhook="webhook" |
||||
|
|
||||
|
# Telegram Alerts | https://docs.linuxgsm.com/alerts/telegram |
||||
|
# You can add a custom cURL string eg proxy (useful in Russia) in "curlcustomstring". |
||||
|
# For example "--socks5 ipaddr:port" for socks5 proxy see more in "curl --help all". |
||||
|
telegramapi="api.telegram.org" |
||||
|
telegramalert="off" |
||||
|
telegramtoken="accesstoken" |
||||
|
telegramchatid="" |
||||
|
telegramthreadid="" |
||||
|
telegramsilentnotification="false" |
||||
|
curlcustomstring="" |
||||
|
|
||||
|
## Updating | https://docs.linuxgsm.com/commands/update |
||||
|
updateonstart="off" |
||||
|
|
||||
|
## Backup | https://docs.linuxgsm.com/commands/backup |
||||
|
maxbackups="4" |
||||
|
maxbackupdays="30" |
||||
|
stoponbackup="on" |
||||
|
|
||||
|
## Logging | https://docs.linuxgsm.com/features/logging |
||||
|
consolelogging="on" |
||||
|
logdays="7" |
||||
|
|
||||
|
## Monitor | https://docs.linuxgsm.com/commands/monitor |
||||
|
# Query delay time |
||||
|
querydelay="1" |
||||
|
|
||||
|
## ANSI Colors | https://docs.linuxgsm.com/features/ansi-colors |
||||
|
ansi="on" |
||||
|
|
||||
|
#### Advanced Settings #### |
||||
|
|
||||
|
## Message Display Time | https://docs.linuxgsm.com/features/message-display-time |
||||
|
sleeptime="0.5" |
||||
|
|
||||
|
## SteamCMD Settings | https://docs.linuxgsm.com/steamcmd |
||||
|
# Server appid |
||||
|
appid="869800" |
||||
|
steamcmdforcewindows="no" |
||||
|
# SteamCMD Branch | https://docs.linuxgsm.com/steamcmd/branch |
||||
|
branch="" |
||||
|
betapassword="" |
||||
|
# Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server |
||||
|
steammaster="true" |
||||
|
|
||||
|
## Stop Mode | https://docs.linuxgsm.com/features/stop-mode |
||||
|
# 1: tmux kill |
||||
|
# 2: CTRL+c |
||||
|
# 3: quit |
||||
|
# 4: quit 120s |
||||
|
# 5: stop |
||||
|
# 6: q |
||||
|
# 7: exit |
||||
|
# 8: 7 Days to Die |
||||
|
# 9: GoldSrc |
||||
|
# 10: Avorion |
||||
|
# 11: end |
||||
|
stopmode="3" |
||||
|
|
||||
|
## Query mode |
||||
|
# 1: session only |
||||
|
# 2: gamedig (gsquery fallback) |
||||
|
# 3: gamedig |
||||
|
# 4: gsquery |
||||
|
# 5: tcp |
||||
|
querymode="2" |
||||
|
querytype="protocol-valve" |
||||
|
|
||||
|
## Console type |
||||
|
consoleverbose="yes" |
||||
|
consoleinteract="yes" |
||||
|
|
||||
|
## Game Server Details |
||||
|
# Do not edit |
||||
|
gamename="Jabroni Brawl: Episode 3" |
||||
|
engine="source" |
||||
|
glibc="2.3.6" |
||||
|
|
||||
|
#### Directories #### |
||||
|
# Edit with care |
||||
|
|
||||
|
## Game Server Directories |
||||
|
systemdir="${serverfiles}/jbep3" |
||||
|
executabledir="${serverfiles}" |
||||
|
executable="./srcds_run.sh" |
||||
|
servercfgdir="${systemdir}/cfg" |
||||
|
servercfg="${selfname}.cfg" |
||||
|
servercfgdefault="server.sample.cfg" |
||||
|
servercfgfullpath="${servercfgdir}/${servercfg}" |
||||
|
|
||||
|
## Backup Directory |
||||
|
backupdir="${lgsmdir}/backup" |
||||
|
|
||||
|
## Logging Directories |
||||
|
[ -n "${LGSM_LOGDIR}" ] && logdir="${LGSM_LOGDIR}" || logdir="${rootdir}/log" |
||||
|
gamelogdir="${systemdir}/logs" |
||||
|
lgsmlogdir="${logdir}/script" |
||||
|
consolelogdir="${logdir}/console" |
||||
|
lgsmlog="${lgsmlogdir}/${selfname}-script.log" |
||||
|
consolelog="${consolelogdir}/${selfname}-console.log" |
||||
|
alertlog="${lgsmlogdir}/${selfname}-alert.log" |
||||
|
postdetailslog="${lgsmlogdir}/${selfname}-postdetails.log" |
||||
|
|
||||
|
## Logs Naming |
||||
|
lgsmlogdate="${lgsmlogdir}/${selfname}-script-$(date '+%Y-%m-%d-%H:%M:%S').log" |
||||
|
consolelogdate="${consolelogdir}/${selfname}-console-$(date '+%Y-%m-%d-%H:%M:%S').log" |
||||
|
|
||||
|
## Log Parameters |
||||
|
logtimestamp="off" |
||||
|
logtimestampformat="%Y-%m-%d %H:%M:%S" |
||||
@ -0,0 +1,189 @@ |
|||||
|
################################## |
||||
|
######## Default Settings ######## |
||||
|
################################## |
||||
|
# DO NOT EDIT, ANY CHANGES WILL BE OVERWRITTEN! |
||||
|
# Copy settings from here and use them in either: |
||||
|
# common.cfg - applies settings to every instance. |
||||
|
# [instance].cfg - applies settings to a specific instance. |
||||
|
|
||||
|
#### Game Server Settings #### |
||||
|
|
||||
|
game_type="0" |
||||
|
game_mode="0" |
||||
|
ip="0.0.0.0" |
||||
|
port="27015" |
||||
|
clientport="27005" |
||||
|
sourcetvport="27020" |
||||
|
steamport="26901" |
||||
|
defaultmap="mcv_siege" |
||||
|
maxplayers="32" |
||||
|
tickrate="64" |
||||
|
|
||||
|
## Server Parameters | https://docs.linuxgsm.com/configuration/start-parameters#additional-parameters |
||||
|
startparameters="-game vietnam -usercon -strictportbind -ip ${ip} -port ${port} +clientport ${clientport} +tv_port ${sourcetvport} -tickrate ${tickrate} +map ${defaultmap} +servercfgfile ${servercfg} -maxplayers_override ${maxplayers} +game_type ${game_type} +game_mode ${game_mode} -nobreakpad" |
||||
|
|
||||
|
#### LinuxGSM Settings #### |
||||
|
|
||||
|
## LinuxGSM Stats |
||||
|
# Send useful stats to LinuxGSM developers. |
||||
|
# https://docs.linuxgsm.com/configuration/linuxgsm-stats |
||||
|
# (on|off) |
||||
|
stats="off" |
||||
|
|
||||
|
## Notification Alerts |
||||
|
# (on|off) |
||||
|
|
||||
|
# Display IP | https://docs.linuxgsm.com/alerts#display-ip |
||||
|
displayip="" |
||||
|
|
||||
|
# More info | https://docs.linuxgsm.com/alerts#more-info |
||||
|
postalert="off" |
||||
|
|
||||
|
# Alert on Start/Stop/Restart |
||||
|
statusalert="off" |
||||
|
|
||||
|
# Discord Alerts | https://docs.linuxgsm.com/alerts/discord |
||||
|
discordalert="off" |
||||
|
discordwebhook="webhook" |
||||
|
|
||||
|
# Email Alerts | https://docs.linuxgsm.com/alerts/email |
||||
|
emailalert="off" |
||||
|
email="[email protected]" |
||||
|
emailfrom="" |
||||
|
|
||||
|
# Gotify Alerts | https://docs.linuxgsm.com/alerts/gotify |
||||
|
gotifyalert="off" |
||||
|
gotifytoken="token" |
||||
|
gotifywebhook="webhook" |
||||
|
|
||||
|
# IFTTT Alerts | https://docs.linuxgsm.com/alerts/ifttt |
||||
|
iftttalert="off" |
||||
|
ifttttoken="accesstoken" |
||||
|
iftttevent="linuxgsm_alert" |
||||
|
|
||||
|
# Pushbullet Alerts | https://docs.linuxgsm.com/alerts/pushbullet |
||||
|
pushbulletalert="off" |
||||
|
pushbullettoken="accesstoken" |
||||
|
channeltag="" |
||||
|
|
||||
|
# Pushover Alerts | https://docs.linuxgsm.com/alerts/pushover |
||||
|
pushoveralert="off" |
||||
|
pushovertoken="accesstoken" |
||||
|
pushoveruserkey="userkey" |
||||
|
|
||||
|
# Rocket.Chat Alerts | https://docs.linuxgsm.com/alerts/rocket.chat |
||||
|
rocketchatalert="off" |
||||
|
rocketchatwebhook="webhook" |
||||
|
|
||||
|
# Slack Alerts | https://docs.linuxgsm.com/alerts/slack |
||||
|
slackalert="off" |
||||
|
slackwebhook="webhook" |
||||
|
|
||||
|
# Telegram Alerts | https://docs.linuxgsm.com/alerts/telegram |
||||
|
# You can add a custom cURL string eg proxy (useful in Russia) in "curlcustomstring". |
||||
|
# For example "--socks5 ipaddr:port" for socks5 proxy see more in "curl --help". |
||||
|
telegramapi="api.telegram.org" |
||||
|
telegramalert="off" |
||||
|
telegramtoken="accesstoken" |
||||
|
telegramchatid="" |
||||
|
curlcustomstring="" |
||||
|
|
||||
|
## Updating | https://docs.linuxgsm.com/commands/update |
||||
|
updateonstart="off" |
||||
|
|
||||
|
## Backup | https://docs.linuxgsm.com/commands/backup |
||||
|
maxbackups="4" |
||||
|
maxbackupdays="30" |
||||
|
stoponbackup="on" |
||||
|
|
||||
|
## Logging | https://docs.linuxgsm.com/features/logging |
||||
|
consolelogging="on" |
||||
|
logdays="7" |
||||
|
|
||||
|
## Monitor | https://docs.linuxgsm.com/commands/monitor |
||||
|
# Query delay time |
||||
|
querydelay="1" |
||||
|
|
||||
|
## ANSI Colors | https://docs.linuxgsm.com/features/ansi-colors |
||||
|
ansi="on" |
||||
|
|
||||
|
#### Advanced Settings #### |
||||
|
|
||||
|
## Message Display Time | https://docs.linuxgsm.com/features/message-display-time |
||||
|
sleeptime="0.5" |
||||
|
|
||||
|
## SteamCMD Settings | https://docs.linuxgsm.com/steamcmd |
||||
|
# Server appid |
||||
|
appid="1136190" |
||||
|
steamcmdforcewindows="no" |
||||
|
# SteamCMD Branch | https://docs.linuxgsm.com/steamcmd/branch |
||||
|
branch="" |
||||
|
betapassword="" |
||||
|
# Master Server | https://docs.linuxgsm.com/steamcmd/steam-master-server |
||||
|
steammaster="false" |
||||
|
|
||||
|
## Stop Mode | https://docs.linuxgsm.com/features/stop-mode |
||||
|
# 1: tmux kill |
||||
|
# 2: CTRL+c |
||||
|
# 3: quit |
||||
|
# 4: quit 120s |
||||
|
# 5: stop |
||||
|
# 6: q |
||||
|
# 7: exit |
||||
|
# 8: 7 Days to Die |
||||
|
# 9: GoldSrc |
||||
|
# 10: Avorion |
||||
|
# 11: end |
||||
|
stopmode="3" |
||||
|
|
||||
|
## Query mode |
||||
|
# 1: session only |
||||
|
# 2: gamedig (gsquery fallback) |
||||
|
# 3: gamedig |
||||
|
# 4: gsquery |
||||
|
# 5: tcp |
||||
|
querymode="2" |
||||
|
querytype="protocol-valve" |
||||
|
|
||||
|
## Console type |
||||
|
consoleverbose="yes" |
||||
|
consoleinteract="yes" |
||||
|
|
||||
|
## Game Server Details |
||||
|
# Do not edit |
||||
|
gamename="Military Conflict: Vietnam" |
||||
|
engine="source" |
||||
|
glibc="2.15" |
||||
|
|
||||
|
#### Directories #### |
||||
|
# Edit with care |
||||
|
|
||||
|
## Game Server Directories |
||||
|
systemdir="${serverfiles}/vietnam" |
||||
|
executabledir="${serverfiles}" |
||||
|
executable="./srcds_run_x64" |
||||
|
servercfgdir="${systemdir}/cfg" |
||||
|
servercfg="${selfname}.cfg" |
||||
|
servercfgdefault="server.cfg" |
||||
|
servercfgfullpath="${servercfgdir}/${servercfg}" |
||||
|
|
||||
|
## Backup Directory |
||||
|
backupdir="${lgsmdir}/backup" |
||||
|
|
||||
|
## Logging Directories |
||||
|
[ -n "${LGSM_LOGDIR}" ] && logdir="${LGSM_LOGDIR}" || logdir="${rootdir}/log" |
||||
|
gamelogdir="${systemdir}/logs" |
||||
|
lgsmlogdir="${logdir}/script" |
||||
|
consolelogdir="${logdir}/console" |
||||
|
lgsmlog="${lgsmlogdir}/${selfname}-script.log" |
||||
|
consolelog="${consolelogdir}/${selfname}-console.log" |
||||
|
alertlog="${lgsmlogdir}/${selfname}-alert.log" |
||||
|
postdetailslog="${lgsmlogdir}/${selfname}-postdetails.log" |
||||
|
|
||||
|
## Logs Naming |
||||
|
lgsmlogdate="${lgsmlogdir}/${selfname}-script-$(date '+%Y-%m-%d-%H:%M:%S').log" |
||||
|
consolelogdate="${consolelogdir}/${selfname}-console-$(date '+%Y-%m-%d-%H:%M:%S').log" |
||||
|
|
||||
|
## Log Parameters |
||||
|
logtimestamp="off" |
||||
|
logtimestampformat="%Y-%m-%d %H:%M:%S" |
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 4.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
After Width: | Height: | Size: 400 B |
|
After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 47.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -0,0 +1,175 @@ |
|||||
|
#!/bin/bash |
||||
|
# LinuxGSM update_bb.sh module |
||||
|
# Author: Daniel Gibbs |
||||
|
# Contributors: https://linuxgsm.com/contrib |
||||
|
# Website: https://linuxgsm.com |
||||
|
# Description: Handles updating of BrainBread servers. |
||||
|
|
||||
|
moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")" |
||||
|
|
||||
|
fn_update_dl() { |
||||
|
# Download and extract files to serverfiles. |
||||
|
fn_fetch_file "${remotebuildurl}" "" "" "" "${tmpdir}" "${remotebuildfilename}" "nochmodx" "norun" "force" "${remotebuildhash}" |
||||
|
fn_dl_extract "${tmpdir}" "${remotebuildfilename}" "${serverfiles}" |
||||
|
echo "${remotebuild}" > "${serverfiles}/build.txt" |
||||
|
fn_clear_tmp |
||||
|
} |
||||
|
|
||||
|
fn_update_localbuild() { |
||||
|
# Gets local build info. |
||||
|
fn_print_dots "Checking local build: ${remotelocation}" |
||||
|
# Uses build file to get local build. |
||||
|
localbuild=$(head -n 1 "${serverfiles}/build.txt" 2> /dev/null) |
||||
|
if [ -z "${localbuild}" ]; then |
||||
|
fn_print_error "Checking local build: ${remotelocation}: missing local build info" |
||||
|
fn_script_log_error "Missing local build info" |
||||
|
fn_script_log_error "Set localbuild to 0" |
||||
|
localbuild="0" |
||||
|
else |
||||
|
fn_print_ok "Checking local build: ${remotelocation}" |
||||
|
fn_script_log_pass "Checking local build" |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
fn_update_remotebuild() { |
||||
|
# Gets remote build info. |
||||
|
apiurl="https://api.github.com/repos/IronOak-Studios/BrainBread/releases/latest" |
||||
|
remotebuildresponse=$(curl -s "${apiurl}") |
||||
|
remotebuildfilename=$(echo "${remotebuildresponse}" | jq -r '.assets[] | select(.name | test("linuxserver\\.tar\\.gz$")) | .name' | head -n 1) |
||||
|
remotebuildurl=$(echo "${remotebuildresponse}" | jq -r '.assets[] | select(.name | test("linuxserver\\.tar\\.gz$")) | .browser_download_url' | head -n 1) |
||||
|
remotebuildhash=$(echo "${remotebuildresponse}" | jq -r '.assets[] | select(.name | test("linuxserver\\.tar\\.gz$")) | .digest' | sed 's/^sha256://g' | head -n 1) |
||||
|
remotebuild=$(echo "${remotebuildresponse}" | jq -r '.tag_name') |
||||
|
if [ -z "${remotebuildhash}" ] || [ "${remotebuildhash}" == "null" ]; then |
||||
|
remotebuildhash="nohash" |
||||
|
fi |
||||
|
|
||||
|
if [ "${firstcommandname}" != "INSTALL" ]; then |
||||
|
fn_print_dots "Checking remote build: ${remotelocation}" |
||||
|
# Checks if remotebuild variable has been set. |
||||
|
if [ -z "${remotebuild}" ] || [ "${remotebuild}" == "null" ] || [ -z "${remotebuildurl}" ] || [ "${remotebuildurl}" == "null" ] || [ -z "${remotebuildfilename}" ] || [ "${remotebuildfilename}" == "null" ]; then |
||||
|
fn_print_fail "Checking remote build: ${remotelocation}" |
||||
|
fn_script_log_fail "Checking remote build" |
||||
|
core_exit.sh |
||||
|
else |
||||
|
fn_print_ok "Checking remote build: ${remotelocation}" |
||||
|
fn_script_log_pass "Checking remote build" |
||||
|
fi |
||||
|
else |
||||
|
# Checks if remotebuild variable has been set. |
||||
|
if [ -z "${remotebuild}" ] || [ "${remotebuild}" == "null" ] || [ -z "${remotebuildurl}" ] || [ "${remotebuildurl}" == "null" ] || [ -z "${remotebuildfilename}" ] || [ "${remotebuildfilename}" == "null" ]; then |
||||
|
fn_print_failure "Unable to get remote build" |
||||
|
fn_script_log_fail "Unable to get remote build" |
||||
|
core_exit.sh |
||||
|
fi |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
fn_update_compare() { |
||||
|
fn_print_dots "Checking for update: ${remotelocation}" |
||||
|
# Update has been found or force update. |
||||
|
if [ "${localbuild}" != "${remotebuild}" ] || [ "${forceupdate}" == "1" ]; then |
||||
|
# Create update lockfile. |
||||
|
date '+%s' > "${lockdir:?}/update.lock" |
||||
|
fn_print_ok_nl "Checking for update: ${remotelocation}" |
||||
|
fn_print "\n" |
||||
|
fn_print_nl "${bold}${underline}Update${default} available" |
||||
|
fn_print_nl "* Local build: ${red}${localbuild}${default}" |
||||
|
fn_print_nl "* Remote build: ${green}${remotebuild}${default}" |
||||
|
if [ -n "${branch}" ]; then |
||||
|
fn_print_nl "* Branch: ${branch}" |
||||
|
fi |
||||
|
if [ -f "${rootdir}/.dev-debug" ]; then |
||||
|
fn_print_nl "Remote build info" |
||||
|
fn_print_nl "* apiurl: ${apiurl}" |
||||
|
fn_print_nl "* remotebuildfilename: ${remotebuildfilename}" |
||||
|
fn_print_nl "* remotebuildurl: ${remotebuildurl}" |
||||
|
fn_print_nl "* remotebuildhash: ${remotebuildhash}" |
||||
|
fn_print_nl "* remotebuild: ${remotebuild}" |
||||
|
fi |
||||
|
fn_print "\n" |
||||
|
fn_script_log_info "Update available" |
||||
|
fn_script_log_info "Local build: ${localbuild}" |
||||
|
fn_script_log_info "Remote build: ${remotebuild}" |
||||
|
if [ -n "${branch}" ]; then |
||||
|
fn_script_log_info "Branch: ${branch}" |
||||
|
fi |
||||
|
fn_script_log_info "${localbuild} > ${remotebuild}" |
||||
|
|
||||
|
if [ "${commandname}" == "UPDATE" ]; then |
||||
|
date +%s > "${lockdir:?}/last-updated.lock" |
||||
|
unset updateonstart |
||||
|
check_status.sh |
||||
|
# If server stopped. |
||||
|
if [ "${status}" == "0" ]; then |
||||
|
fn_update_dl |
||||
|
if [ "${localbuild}" == "0" ]; then |
||||
|
exitbypass=1 |
||||
|
command_start.sh |
||||
|
fn_firstcommand_reset |
||||
|
exitbypass=1 |
||||
|
fn_sleep_time_5 |
||||
|
command_stop.sh |
||||
|
fn_firstcommand_reset |
||||
|
fi |
||||
|
# If server started. |
||||
|
else |
||||
|
fn_print_restart_warning |
||||
|
exitbypass=1 |
||||
|
command_stop.sh |
||||
|
fn_firstcommand_reset |
||||
|
exitbypass=1 |
||||
|
fn_update_dl |
||||
|
exitbypass=1 |
||||
|
command_start.sh |
||||
|
fn_firstcommand_reset |
||||
|
fi |
||||
|
unset exitbypass |
||||
|
alert="update" |
||||
|
elif [ "${commandname}" == "CHECK-UPDATE" ]; then |
||||
|
alert="check-update" |
||||
|
fi |
||||
|
alert.sh |
||||
|
else |
||||
|
fn_print_ok_nl "Checking for update: ${remotelocation}" |
||||
|
fn_print "\n" |
||||
|
fn_print_nl "${bold}${underline}No update${default} available" |
||||
|
fn_print_nl "* Local build: ${green}${localbuild}${default}" |
||||
|
fn_print_nl "* Remote build: ${green}${remotebuild}${default}" |
||||
|
if [ -n "${branch}" ]; then |
||||
|
fn_print_nl "* Branch: ${branch}" |
||||
|
fi |
||||
|
fn_print "\n" |
||||
|
fn_script_log_info "No update available" |
||||
|
fn_script_log_info "Local build: ${localbuild}" |
||||
|
fn_script_log_info "Remote build: ${remotebuild}" |
||||
|
if [ -n "${branch}" ]; then |
||||
|
fn_script_log_info "Branch: ${branch}" |
||||
|
fi |
||||
|
if [ -f "${rootdir}/.dev-debug" ]; then |
||||
|
fn_print_nl "Remote build info" |
||||
|
fn_print_nl "* apiurl: ${apiurl}" |
||||
|
fn_print_nl "* remotebuildfilename: ${remotebuildfilename}" |
||||
|
fn_print_nl "* remotebuildurl: ${remotebuildurl}" |
||||
|
fn_print_nl "* remotebuildhash: ${remotebuildhash}" |
||||
|
fn_print_nl "* remotebuild: ${remotebuild}" |
||||
|
fi |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# The location where the builds are checked and downloaded. |
||||
|
remotelocation="github.com" |
||||
|
|
||||
|
if [ "${firstcommandname}" == "INSTALL" ]; then |
||||
|
fn_update_remotebuild |
||||
|
fn_update_dl |
||||
|
else |
||||
|
# BrainBread requires both Steam app updates and GitHub package updates. |
||||
|
update_steamcmd.sh |
||||
|
|
||||
|
fn_print_dots "Checking for update" |
||||
|
fn_print_dots "Checking for update: ${remotelocation}" |
||||
|
fn_script_log_info "Checking for update: ${remotelocation}" |
||||
|
fn_update_localbuild |
||||
|
fn_update_remotebuild |
||||
|
fn_update_compare |
||||
|
fi |
||||
Loading…
Reference in new issue