Compare commits

..
4 changed files with 48 additions and 7 deletions
+2 -1
View File
@@ -3,7 +3,8 @@
"leanprover-community/nng4", "leanprover-community/nng4",
"hhu-adam/robo", "hhu-adam/robo",
"djvelleman/stg4", "djvelleman/stg4",
"trequetrum/lean4game-logic" "trequetrum/lean4game-logic",
"jadabouhawili/knightsandknaves-lean4game"
], ],
"languages": [ "languages": [
+5 -1
View File
@@ -24,7 +24,11 @@ You should see a white screen which shows import updates and eventually reports
Now you can immediately play the game at `adam.math.hhu.de/#/g/{USER}/{REPOSITORY}`! Now you can immediately play the game at `adam.math.hhu.de/#/g/{USER}/{REPOSITORY}`!
## 4. Main page ## 4. Update
To upload a new version of the game you will have to repeat 1. and 2. whenever you want to publish the updated version.
## 5. Main page
Adding games to the main page happens manually by the server maintainers. Tell us if you want us Adding games to the main page happens manually by the server maintainers. Tell us if you want us
to add a tile for your game! to add a tile for your game!
+2
View File
@@ -6,6 +6,8 @@ module.exports = {
env: { env: {
LEAN4GAME_GITHUB_USER: "", LEAN4GAME_GITHUB_USER: "",
LEAN4GAME_GITHUB_TOKEN: "", LEAN4GAME_GITHUB_TOKEN: "",
RES_DISC_SPACE_PERCENTAGE: 1.0,
ISSUE_CONTACT: "",
NODE_ENV: "production", NODE_ENV: "production",
PORT: 8002 PORT: 8002
}, },
+39 -5
View File
@@ -1,22 +1,26 @@
import { spawn } from 'child_process' import { spawn } from 'child_process'
import fs from 'fs'; import fs, { stat } from 'fs';
import request from 'request' import request from 'request'
import requestProgress from 'request-progress' import requestProgress from 'request-progress'
import { Octokit } from 'octokit'; import { Octokit } from 'octokit';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import path from 'path'; import path, { resolve } from 'path';
import { error } from 'console';
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename); const __dirname = path.dirname(__filename);
const TOKEN = process.env.LEAN4GAME_GITHUB_TOKEN const TOKEN = process.env.LEAN4GAME_GITHUB_TOKEN
const USERNAME = process.env.LEAN4GAME_GITHUB_USER const USERNAME = process.env.LEAN4GAME_GITHUB_USER
const MEM_THRESHOLD = process.env.RES_DISC_SPACE_PERCENTAGE
const CONTACT = process.env.ISSUE_CONTACT
const octokit = new Octokit({ const octokit = new Octokit({
auth: TOKEN auth: TOKEN
}) })
const progress = {} const progress = {}
var exceedingMemoryLimit = false
async function runProcess(id, cmd, args, cwd) { async function runProcess(id, cmd, args, cwd) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@@ -36,6 +40,28 @@ async function runProcess(id, cmd, args, cwd) {
}) })
} }
async function checkAgainstDiscMemory(artifact, maxPercentage) {
return new Promise((resolve, reject) => {
fs.statfs("/", (err, stats) => {
if (err) {
console.log(err);
reject()
}
let artifactBytes = artifact.size_in_bytes;
let totalBytes = stats.blocks * stats.bsize;
let freeBytes = stats.bfree * stats.bsize;
let usedBytes = totalBytes - freeBytes;
let maxUsedBytes = totalBytes * maxPercentage;
if (usedBytes + artifactBytes >= maxUsedBytes) {
exceedingMemoryLimit = true;
}
resolve()
});
})
}
async function download(id, url, dest) { async function download(id, url, dest) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// The options argument is optional so you can omit it // The options argument is optional so you can omit it
@@ -49,7 +75,9 @@ async function download(id, url, dest) {
} }
})) }))
.on('progress', function (state) { .on('progress', function (state) {
progress[id].output += `Downloaded ${Math.round(state.size.transferred/1024/1024)}MB\n` console.log('progress', state);
transferredDataSize = Math.round(state.size.transferred/1024/1024)
progress[id].output += `Downloaded ${transferredDataSize}MB\n`
}) })
.on('error', function (err) { .on('error', function (err) {
reject(err) reject(err)
@@ -73,9 +101,16 @@ async function doImport (owner, repo, id) {
'X-GitHub-Api-Version': '2022-11-28' 'X-GitHub-Api-Version': '2022-11-28'
} }
}) })
// choose latest artifact
const artifact = artifacts.data.artifacts const artifact = artifacts.data.artifacts
.reduce((acc, cur) => acc.created_at < cur.created_at ? cur : acc) .reduce((acc, cur) => acc.created_at < cur.created_at ? cur : acc)
await checkAgainstDiscMemory(artifact, MEM_THRESHOLD);
if (exceedingMemoryLimit === true) {
throw new Error(`Uploading file of size ${Math.round(artifact.size_in_bytes / 1024 / 1024)} (MB) would exceed allocated memory on the server.\n
Please notify server admins via <a href=${CONTACT}>the LEAN zulip instance</a> to resolve this issue.`);
}
artifactId = artifact.id artifactId = artifact.id
const url = artifact.archive_download_url const url = artifact.archive_download_url
// Make sure the download folder exists // Make sure the download folder exists
@@ -91,7 +126,6 @@ async function doImport (owner, repo, id) {
await runProcess(id, "/bin/bash", [path.join(__dirname, "unpack.sh"), artifactId, owner.toLowerCase(), repo.toLowerCase()], path.join(__dirname, "..")) await runProcess(id, "/bin/bash", [path.join(__dirname, "unpack.sh"), artifactId, owner.toLowerCase(), repo.toLowerCase()], path.join(__dirname, ".."))
// let manifest = fs.readFileSync(`tmp/artifact_${artifactId}_inner/manifest.json`); // let manifest = fs.readFileSync(`tmp/artifact_${artifactId}_inner/manifest.json`);
// manifest = JSON.parse(manifest); // manifest = JSON.parse(manifest);
// if (manifest.length !== 1) { // if (manifest.length !== 1) {