From 9f9b093d71935c78bfceca86f1144909710671cf Mon Sep 17 00:00:00 2001 From: WinterMyst <22961076-wintermyst@users.noreply.gitlab.com> Date: Thu, 26 Sep 2024 00:50:43 +0000 Subject: [PATCH] 1.1.2 --- .gitlab-ci.yml | 128 ++++----- gulpfile.js | 296 +++++++++++++++++++-- module/helpers/templates.mjs | 8 +- module/kidsonbrooms.mjs | 22 +- package.json | 9 +- readme.md | 2 +- system.json | 2 +- templates/actor/actor-character-sheet.html | 6 +- templates/actor/actor-npc-sheet.html | 2 +- 9 files changed, 354 insertions(+), 121 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c2ec346..1ad4239 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,11 +1,24 @@ +image: ubuntu:latest + + stages: - - compile + - build - release -# Compile Job (runs on every commit) -compile: - stage: compile - image: ubuntu:latest +variables: + MANIFEST: "system.json" + ZIPFILE: "kidsonbrooms.zip" + PACKAGE_REGISTRY_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${CI_PROJECT_NAME}/${CI_COMMIT_TAG}" + MANIFEST_RELEASE_URL: "${PACKAGE_REGISTRY_URL}/${MANIFEST}" + ZIPFILE_RELEASE_URL: "${PACKAGE_REGISTRY_URL}/${ZIPFILE}" + MANIFEST_PERMALINK_URL: "https://gitlab.com/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}/-/releases/permalink/latest/downloads/${MANIFEST}" + ZIPFILE_PERMALINK_URL: "https://gitlab.com/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}/-/releases/${CI_COMMIT_TAG}/downloads/${ZIPFILE}" + dry_run: true + + +# Build job +build: + stage: build before_script: # Install Node.js v21.x manually - apt-get update && apt-get install -y curl @@ -17,94 +30,55 @@ compile: - gulp --version # Verify Gulp is installed script: - npm install - - gulp compile - only: - - branches + - gulp build artifacts: paths: - kidsonbrooms.zip - expire_in: never + - system.json + - packs/ + only: + - branches -# Release Job (manually triggered with version) +# Release job release: stage: release - image: ubuntu:latest + rules: + - if: $CI_COMMIT_TAG + variables: + dry_run: "false" before_script: - # Install necessary tools - - apt-get update && apt-get install -y curl jq git # Install Node.js v21.x manually + - apt-get update && apt-get install -y curl - curl -fsSL https://deb.nodesource.com/setup_21.x | bash - - apt-get install -y nodejs - node -v # Verify the correct Node.js version # Install Gulp globally - npm install --global gulp-cli - gulp --version # Verify Gulp is installed - - git fetch --all - - git switch master - - git branch --set-upstream-to=origin/master master script: - # Check if VERSION is provided - - | - if [ -z "$VERSION" ]; then - echo "Error: VERSION variable is required." - exit 1 - fi - - # Install dependencies and run Gulp release task - npm install - gulp release - - grep '"download":' system.json - - git config --global user.name "GitLab CI" - - git config --global user.email "ci@gitlab.com" - - git add kidsonbrooms.zip - - git commit -m "Update .zip with new version" - - git push "https://$CI_COMMITTER_USER_AND_TOKEN@gitlab.com/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}.git" HEAD:master +# Create GitLab release +create-release: + stage: release + image: registry.gitlab.com/gitlab-org/release-cli:latest + needs: + - job: release + rules: + - if: $CI_COMMIT_TAG + script: + - echo "Creating GitLab release for $CI_COMMIT_TAG" + release: + name: "$CI_COMMIT_TAG" + tag_name: "$CI_COMMIT_TAG" + description: "Release $CI_COMMIT_TAG of $CI_PROJECT_NAME." + assets: + links: + - name: "$MANIFEST" + url: "${MANIFEST_RELEASE_URL}" + filepath: "/${MANIFEST}" + - name: "$ZIPFILE" + url: "${ZIPFILE_PERMALINK_URL}" + filepath: "/${ZIPFILE}" - # Create a release on GitLab - - | - export RELEASE_RESPONSE=$(curl --request POST \ - --header "PRIVATE-TOKEN: ${GITLAB_PAT}" \ - --header "Content-Type: application/json" \ - --data '{ - "name": "Release v'$VERSION'", - "tag_name": "v'$VERSION'", - "description": "Release v'$VERSION'", - "ref": "master", - "assets": { - "links": [ - { - "name": "Download kidsonbrooms.zip", - "url": "https://gitlab.com/wintermyst/kidsonbrooms/-/raw/master/kidsonbrooms.zip?inline=false" - } - ] - } - }' "https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/releases") - # Publish the release to the Foundry API - - | - curl -X POST https://api.foundryvtt.com/_api/packages/release_version/ \ - -H "Authorization: $FOUNDRY_API_KEY" \ - -H "Content-Type: application/json" \ - -d "{ - \"id\": \"kidsonbrooms\", - \"release\": { - \"version\": \"$VERSION\", - \"manifest\": \"https://gitlab.com/wintermyst/kidsonbrooms/-/raw/master/system.json\", - \"notes\": \"https://gitlab.com/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}/-/releases/v$VERSION\", - \"compatibility\": { - \"minimum\": \"12\", - \"verified\": \"12.331\", - \"maximum\": \"\" - } - } - }" - only: - - master - when: manual - allow_failure: false - dependencies: - - compile - artifacts: - paths: - - kidsonbrooms.zip - expire_in: never diff --git a/gulpfile.js b/gulpfile.js index a31780f..9bc1b0d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -3,6 +3,41 @@ const prefix = require('gulp-autoprefixer'); const sourcemaps = require('gulp-sourcemaps'); const sass = require('gulp-sass')(require('sass')); const zip = require('gulp-zip'); +const fs = require('fs'); +const fetch = import('node-fetch'); +const replace = require('gulp-replace'); +const FormData = require('form-data'); + +/* ----------------------------------------- */ +/* Export Tasks +/* ----------------------------------------- */ + +exports.default = gulp.series( + compileScss, + watchUpdates +); + +exports.build = gulp.series( + compileScss, + checkVersion, + ensureOutputDirExists, + packageCompendiums, + updateSystemJson, + zipRelease +); + +exports.compile = gulp.series( + compileScss, + ensureOutputDirExists, + packageCompendiums, +); + + +exports.release = gulp.series( + exports.build, + uploadToPackageRegistry, + publishToFoundry +); /* ----------------------------------------- */ /* Compile Sass @@ -30,7 +65,6 @@ function compileScss() { })) .pipe(gulp.dest("./css")) } -const css = gulp.series(compileScss); /* ----------------------------------------- */ /* Watch Updates @@ -40,21 +74,6 @@ function watchUpdates() { gulp.watch(SYSTEM_SCSS, css); } -/* ----------------------------------------- */ -/* Export Tasks -/* ----------------------------------------- */ - -exports.default = gulp.series( - compileScss, - watchUpdates -); -exports.build = gulp.series( - compileScss -); -exports.compile = gulp.series( - compileScss -); -exports.css = css; /* ----------------------------------------- */ /* Zip Release @@ -71,12 +90,249 @@ function zipRelease() { '!./package.json', '!./scss/**/*', '!./.github/**/*', + '!./.gitlab-ci.yml', + '!./README.md', + '!./compendiums/**/*', + '!./*.zip' ], { base: '.' }) .pipe(zip('kidsonbrooms.zip')) .pipe(gulp.dest('.')); } -exports.release = gulp.series( - compileScss, - zipRelease -); +/* ----------------------------------------- */ +/* Version Check +/* ----------------------------------------- */ + + +function checkVersion(done) { + const Manifest = JSON.parse(fs.readFileSync('system.json')); + const manifestVersion = Manifest.version; + const gitTag = process.env.CI_COMMIT_TAG; + + if (gitTag && manifestVersion !== gitTag) { + console.error(`Version mismatch between tag (${gitTag}) and manifest (${manifestVersion})!`); + process.exit(1); + } else { + console.log(`Version check passed: ${manifestVersion}`); + done(); + } +} + +/* ----------------------------------------- */ +/* Bundle Compendium +/* ----------------------------------------- */ + +const { exec } = require('child_process'); + +function packageCompendiums(done) { + const packsDir = './compendiums'; // Adjust to your compendium source directory + const outputDir = './packs'; + const moduleId = 'kidsonbrooms'; // Replace with your actual module ID + + // Read all subdirectories in the packsDir + if (!fs.existsSync(packsDir)) { + console.log(`Compendium directory ${packsDir} does not exist. Skipping packaging.`); + done(); + return; + } + + // Read all files and directories in the packsDir + fs.readdir(packsDir, (err, files) => { + if (err) { + console.error(`Error reading directory ${packsDir}: ${err}`); + process.exit(1); + } + + // Filter to get only directories + const folders = files.filter(file => { + const fullPath = path.join(packsDir, file); + return fs.statSync(fullPath).isDirectory(); + }); + + if (folders.length === 0) { + console.log(`No compendium folders found in ${packsDir}. Skipping packaging.`); + done(); + return; + } + + let completed = 0; + folders.forEach(folder => { + const packName = folder; // Use the folder name as the pack name + const inputPath = path.join(packsDir, folder); + const command = `npx fvtt package pack --type System --id ${moduleId} -n "${packName}" --in "${inputPath}" --out "${outputDir}" --yaml`; + + exec(command, (err, stdout, stderr) => { + if (err) { + console.error(`Error packaging compendium ${packName}:\n${stderr}`); + process.exit(1); + } else { + console.log(`Compendium ${packName} packaged successfully.`); + console.log(stdout); + completed++; + // When all compendiums have been processed, call done() + if (completed === folders.length) { + done(); + } + } + }); + }); + }); +} + +/* ----------------------------------------- */ +/* Ensure Output Directory Exists +/* ----------------------------------------- */ + +function ensureOutputDirExists() { + const outputDir = './packs'; + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir); + } + return Promise.resolve(); +} + +/* ----------------------------------------- */ +/* Upload to Package Registry +/* ----------------------------------------- */ + + +async function uploadToPackageRegistry(done) { + const manifestFile = 'system.json'; + const zipFile = process.env.ZIPFILE || 'kidsonbrooms.zip'; + const packageRegistryUrl = process.env.PACKAGE_REGISTRY_URL; + const ciJobToken = process.env.CI_JOB_TOKEN; + + if (!packageRegistryUrl || !ciJobToken) { + console.error('PACKAGE_REGISTRY_URL or CI_JOB_TOKEN is not defined.'); + process.exit(1); + } + + try { + // Upload manifest file + const manifestUploadUrl = `${packageRegistryUrl}/${manifestFile}`; + console.log(`Uploading ${manifestFile} to ${manifestUploadUrl}`); + + let response = await fetch(manifestUploadUrl, { + method: 'PUT', + headers: { + 'JOB-TOKEN': ciJobToken, + 'Content-Type': 'application/octet-stream', + }, + body: fs.createReadStream(manifestFile), + }); + + if (response.ok) { + console.log(`Uploaded ${manifestFile} successfully.`); + } else { + console.error(`Failed to upload ${manifestFile}: ${response.statusText}`); + process.exit(1); + } + + // Upload zip file + const zipUploadUrl = `${packageRegistryUrl}/${zipFile}`; + console.log(`Uploading ${zipFile} to ${zipUploadUrl}`); + + response = await fetch(zipUploadUrl, { + method: 'PUT', + headers: { + 'JOB-TOKEN': ciJobToken, + 'Content-Type': 'application/octet-stream', + }, + body: fs.createReadStream(zipFile), + }); + + if (response.ok) { + console.log(`Uploaded ${zipFile} successfully.`); + } else { + console.error(`Failed to upload ${zipFile}: ${response.statusText}`); + process.exit(1); + } + + done(); + } catch (error) { + console.error(`Error uploading files: ${error.message}`); + process.exit(1); + } +} + +/* ----------------------------------------- */ +/* Publish to FoundryVTT +/* ----------------------------------------- */ + +function publishToFoundry(done) { + const moduleManifestPath = 'system.json'; + const moduleManifest = JSON.parse(fs.readFileSync(moduleManifestPath)); + + const id = moduleManifest.name; + const version = moduleManifest.version; + const compMin = moduleManifest.compatibility.minimum; + const compVer = moduleManifest.compatibility.verified; + const compMax = moduleManifest.compatibility.maximum; + const manifest = process.env.MANIFEST_RELEASE_URL || `https://gitlab.com/${process.env.CI_PROJECT_NAMESPACE}/${process.env.CI_PROJECT_NAME}/-/releases/${process.env.CI_COMMIT_TAG}/downloads/${moduleManifestPath}`; + const notes = `https://gitlab.com/${process.env.CI_PROJECT_NAMESPACE}/${process.env.CI_PROJECT_NAME}/-/tags/${process.env.CI_COMMIT_TAG}`; + + const dryRun = process.env.dry_run === 'true'; + const authToken = process.env.FOUNDRY_API_KEY; + + if (!authToken) { + console.error('Foundry VTT API authentication token (FOUNDRY_API_KEY) is not defined.'); + process.exit(1); + } + + // Construct the payload + const payload = { + id: id, + release: { + version: version, + manifest: manifest, + notes: notes, + compatibility: { + minimum: compMin, + verified: compVer, + maximum: compMax, + }, + }, + }; + + if (dryRun) { + payload['dry-run'] = true; + } + + // Send the POST request to Foundry VTT API + const response = fetch('https://api.foundryvtt.com/_api/packages/release', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: authToken, + }, + body: JSON.stringify(payload), + }); + + const responseData = response.json(); + + if (responseData.status === 'success') { + console.log('Successfully published to Foundry VTT:'); + console.log(JSON.stringify(responseData, null, 2)); + done(); + } else { + console.error('Failed to publish to Foundry VTT:'); + console.error(JSON.stringify(responseData, null, 2)); + process.exit(1); + } +} + +/* ----------------------------------------- */ +/* Update systen.json with Download URL +/* ----------------------------------------- */ + +function updateSystemJson(done) { + const ManifestPath = 'system.json'; + const Manifest = JSON.parse(fs.readFileSync(ManifestPath)); + const zipUrl = process.env.ZIPFILE_PERMALINK_URL || 'https://gitlab.com/wintermyst/kidsonbrooms/-/raw/master/kidsonbrooms.zip?inline=false'; + + Manifest.download = zipUrl; + + fs.writeFileSync(ManifestPath, JSON.stringify(Manifest, null, 2)); + console.log(`Updated module.json with download URL: ${zipUrl}`); + done(); +} diff --git a/module/helpers/templates.mjs b/module/helpers/templates.mjs index 63debb1..a96cd05 100644 --- a/module/helpers/templates.mjs +++ b/module/helpers/templates.mjs @@ -7,9 +7,9 @@ return loadTemplates([ // Actor partials. - "systems/kids-on-brooms/templates/actor/parts/actor-features.html", - "systems/kids-on-brooms/templates/actor/parts/actor-adversity.html", - "systems/kids-on-brooms/templates/actor/parts/actor-stats.html", - "systems/kids-on-brooms/templates/actor/parts/actor-npc-stats.html", + "systems/kidsonbrooms/templates/actor/parts/actor-features.html", + "systems/kidsonbrooms/templates/actor/parts/actor-adversity.html", + "systems/kidsonbrooms/templates/actor/parts/actor-stats.html", + "systems/kidsonbrooms/templates/actor/parts/actor-npc-stats.html", ]); }; diff --git a/module/kidsonbrooms.mjs b/module/kidsonbrooms.mjs index eb69120..31165ad 100644 --- a/module/kidsonbrooms.mjs +++ b/module/kidsonbrooms.mjs @@ -47,7 +47,7 @@ Hooks.once('init', async function() { // Register sheet application classes Actors.unregisterSheet("core", ActorSheet); - Actors.registerSheet("kids-on-brooms", KidsOnBroomsActorSheet, { makeDefault: true }); + Actors.registerSheet("kidsonbrooms", KidsOnBroomsActorSheet, { makeDefault: true }); //If there is a new chat message that is a roll we add the adversity token controls Hooks.on("renderChatMessage", (message, html, messageData) => { @@ -67,7 +67,7 @@ Hooks.once('init', async function() { } // Check if the token has already been claimed -- Contigency if the button somehow activates again - if (message.getFlag("kids-on-brooms", "tokenClaimed")) { + if (message.getFlag("kidsonbrooms", "tokenClaimed")) { ui.notifications.warn("This adversity token has already been claimed."); return; } @@ -85,10 +85,10 @@ Hooks.once('init', async function() { // Update the message content tokenControls.update({ content: updatedContent }); // Set the flag on the chat message to indicate that the token has been claimed - tokenControls.setFlag("kids-on-brooms", "tokenClaimed", true); + tokenControls.setFlag("kidsonbrooms", "tokenClaimed", true); } else { // Emit a socket request to update the message to show that the token has been claimed - game.socket.emit('system.kids-on-brooms', { + game.socket.emit('system.kidsonbrooms', { action: "takeToken", messageID: message.id, actorID: actor.id, @@ -118,7 +118,7 @@ Hooks.once('init', async function() { * if a player wants to claim a token we will update the message since they do not have the permissions */ Hooks.once('ready', function() { - game.socket.on('system.kids-on-brooms', async (data) => { + game.socket.on('system.kidsonbrooms', async (data) => { console.log("Socket data received:", data); if (data.action === "spendTokens") { @@ -190,7 +190,7 @@ Hooks.once('ready', function() { // Update the message content tokenControls.update({ content: updatedContent }); // Set the flag on the chat message to indicate that the token has been claimed - tokenControls.setFlag("kids-on-brooms", "tokenClaimed", true); + tokenControls.setFlag("kidsonbrooms", "tokenClaimed", true); } }); }); @@ -277,7 +277,7 @@ async function _onSpendAdversityTokens(e, rollMessageId) { console.log(`Requesting to spend ${tokensToSpend} tokens for ${rollActor.name} by ${spendingPlayerActor.name} (cost: ${tokenCost})`); // Emit a socket request to spend tokens - game.socket.emit('system.kids-on-brooms', { + game.socket.emit('system.kidsonbrooms', { action: "spendTokens", rollActorId: rollActorId, spendingActorId: spendingPlayerActor.id, // Send the player's actor who is spending the tokens @@ -300,8 +300,8 @@ async function _updateRollMessage(rollMessageId, tokensToSpend, isPlayerOfActor) } // Retrieve current tokens spent from flags, or initialize to 0 if not found - let cumulativeTokensSpent = message.getFlag("kids-on-brooms", "tokensSpent") || 0; - let newTotal = message.getFlag("kids-on-brooms", "newRollTotal") || message.rolls[0].total; + let cumulativeTokensSpent = message.getFlag("kidsonbrooms", "tokensSpent") || 0; + let newTotal = message.getFlag("kidsonbrooms", "newRollTotal") || message.rolls[0].total; /*if(isPlayerOfActor) { @@ -312,10 +312,10 @@ async function _updateRollMessage(rollMessageId, tokensToSpend, isPlayerOfActor) }*/ cumulativeTokensSpent += tokensToSpend; newTotal += tokensToSpend; - await message.setFlag("kids-on-brooms", "newRollTotal", newTotal); + await message.setFlag("kidsonbrooms", "newRollTotal", newTotal); // Update the message's flags to store the cumulative tokens spent - await message.setFlag("kids-on-brooms", "tokensSpent", cumulativeTokensSpent); + await message.setFlag("kidsonbrooms", "tokensSpent", cumulativeTokensSpent); let newContent = ""; if(cumulativeTokensSpent === 1) { diff --git a/package.json b/package.json index 811ae5d..2b7f347 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "kids-on-brooms", - "version": "2.0.0", + "name": "kidsonbrooms", + "version": "1.1.0", "description": "CSS compiler for the Kids On Brooms system", "scripts": { "build": "gulp build", @@ -15,12 +15,15 @@ "license": "MIT", "private": true, "dependencies": { + "form-data": "^4.0.0", "gulp": "^5", "gulp-autoprefixer": "^8", + "gulp-replace": "^1.1.4", "gulp-sass": "^5", "gulp-sourcemaps": "^2.6.5", "gulp-zip": "^5.0.1", - "kids-on-brooms": "file:" + "kidsonbrooms": "file:", + "node-fetch": "^3.3.2" }, "devDependencies": { "sass": "^1.79.1" diff --git a/readme.md b/readme.md index e0141b6..8291a1a 100644 --- a/readme.md +++ b/readme.md @@ -1,3 +1,3 @@ -The Kids On Brooms System Implemented in FoundryVTT, reupload from https://github.com/Singularity-Lathe-VTT/kids-on-brooms +The Kids On Brooms System Implemented in FoundryVTT To get support create a issue on this Repository \ No newline at end of file diff --git a/system.json b/system.json index 5311251..2b90c94 100644 --- a/system.json +++ b/system.json @@ -1,7 +1,7 @@ { "id": "kidsonbrooms", "title": "Kids on Brooms System", - "description": "The Kids on Brooms system for FoundryVTT! - Deprecated", + "description": "The Kids on Brooms system for FoundryVTT!", "version": "1.1.0", "compatibility": { "minimum": 12, diff --git a/templates/actor/actor-character-sheet.html b/templates/actor/actor-character-sheet.html index f549c89..120ff36 100644 --- a/templates/actor/actor-character-sheet.html +++ b/templates/actor/actor-character-sheet.html @@ -32,12 +32,12 @@
- {{> "systems/kids-on-brooms/templates/actor/parts/actor-features.html"}} - {{> "systems/kids-on-brooms/templates/actor/parts/actor-adversity.html"}} + {{> "systems/kidsonbrooms/templates/actor/parts/actor-features.html"}} + {{> "systems/kidsonbrooms/templates/actor/parts/actor-adversity.html"}}
diff --git a/templates/actor/actor-npc-sheet.html b/templates/actor/actor-npc-sheet.html index eb8c83c..4299a0a 100644 --- a/templates/actor/actor-npc-sheet.html +++ b/templates/actor/actor-npc-sheet.html @@ -28,7 +28,7 @@ {{!-- Owned Features Tab --}}
- {{> "systems/kids-on-brooms/templates/actor/parts/actor-npc-stats.html"}} + {{> "systems/kidsonbrooms/templates/actor/parts/actor-npc-stats.html"}}