mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
Workflow update (#11933)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
23
.github/gbp.toml
vendored
Normal file
23
.github/gbp.toml
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
no_balance_label = "GBP: No Update"
|
||||||
|
reset_label = "GBP: Reset"
|
||||||
|
|
||||||
|
[points]
|
||||||
|
"Accessibility" = 3
|
||||||
|
"Administration" = 2
|
||||||
|
"Balance" = -5
|
||||||
|
"Code Improvement" = 2
|
||||||
|
"Documentation" = 1
|
||||||
|
"Feature" = -6
|
||||||
|
"Good First PR" = 6
|
||||||
|
"Fix" = 3
|
||||||
|
"Grammar and Formatting" = 1
|
||||||
|
"Hard Deletes" = 12
|
||||||
|
"Logging" = 1
|
||||||
|
"Sev: 0" = 20
|
||||||
|
"Sev: 1-Blocker" = 20
|
||||||
|
"Sev: 2-High" = 15
|
||||||
|
"Quality of Life" = 1
|
||||||
|
"Refactor" = 10
|
||||||
|
"Sound" = 3
|
||||||
|
"Sprites" = 3
|
||||||
|
"Unit Tests" = 6
|
||||||
45
.github/workflows/autowiki.yml
vendored
Normal file
45
.github/workflows/autowiki.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
name: Autowiki
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "5 4 * * *"
|
||||||
|
workflow_dispatch:
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
autowiki:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Check for AUTOWIKI_USERNAME"
|
||||||
|
id: secrets_set
|
||||||
|
env:
|
||||||
|
ENABLER_SECRET: ${{ secrets.AUTOWIKI_USERNAME }}
|
||||||
|
run: |
|
||||||
|
unset SECRET_EXISTS
|
||||||
|
if [ -n "$ENABLER_SECRET" ]; then SECRET_EXISTS=true ; fi
|
||||||
|
echo "SECRETS_ENABLED=$SECRET_EXISTS" >> $GITHUB_OUTPUT
|
||||||
|
- name: Checkout
|
||||||
|
if: steps.secrets_set.outputs.SECRETS_ENABLED
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
- name: Install BYOND
|
||||||
|
if: steps.secrets_set.outputs.SECRETS_ENABLED
|
||||||
|
uses: ./.github/actions/restore_or_install_byond
|
||||||
|
- name: Install rust-g
|
||||||
|
if: steps.secrets_set.outputs.SECRETS_ENABLED
|
||||||
|
run: |
|
||||||
|
bash tools/ci/install_rust_g.sh
|
||||||
|
- name: Compile and generate Autowiki files
|
||||||
|
if: steps.secrets_set.outputs.SECRETS_ENABLED
|
||||||
|
run: |
|
||||||
|
source $HOME/BYOND/byond/bin/byondsetup
|
||||||
|
tools/build/build.sh --ci autowiki
|
||||||
|
- name: Run Autowiki
|
||||||
|
if: steps.secrets_set.outputs.SECRETS_ENABLED
|
||||||
|
env:
|
||||||
|
USERNAME: ${{ secrets.AUTOWIKI_USERNAME }}
|
||||||
|
PASSWORD: ${{ secrets.AUTOWIKI_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
cd tools/autowiki
|
||||||
|
npm install
|
||||||
|
cd ../..
|
||||||
|
node tools/autowiki/autowiki.js data/autowiki_edits.txt data/autowiki_files/
|
||||||
66
.github/workflows/gbp.yml
vendored
Normal file
66
.github/workflows/gbp.yml
vendored
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
name: Label and GBP
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [closed, opened, synchronize]
|
||||||
|
jobs:
|
||||||
|
# labeler must run before gbp because gbp calculates itself based on labels
|
||||||
|
labeler:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event.action == 'opened' || github.event.action == 'synchronize'
|
||||||
|
permissions:
|
||||||
|
pull-requests: write # to apply labels
|
||||||
|
issues: write # to apply labels
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
- name: Run Auto Labeler
|
||||||
|
uses: actions/github-script@v8
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const { get_updated_label_set } = await import('${{ github.workspace }}/tools/pull_request_hooks/autoLabel.js');
|
||||||
|
const new_labels = await get_updated_label_set({ github, context });
|
||||||
|
github.rest.issues.setLabels({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
labels: new_labels,
|
||||||
|
});
|
||||||
|
console.log(`Labels updated: ${new_labels}`);
|
||||||
|
gbp:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event.action == 'opened' || github.event.action == 'closed'
|
||||||
|
steps:
|
||||||
|
- name: "Check for ACTION_ENABLER secret and pass true to output if it exists to be checked by later steps"
|
||||||
|
id: value_holder
|
||||||
|
env:
|
||||||
|
ENABLER_SECRET: ${{ secrets.ACTION_ENABLER }}
|
||||||
|
run: |
|
||||||
|
unset SECRET_EXISTS
|
||||||
|
if [ -n "$ENABLER_SECRET" ]; then SECRET_EXISTS=true ; fi
|
||||||
|
echo "ACTIONS_ENABLED=$SECRET_EXISTS" >> $GITHUB_OUTPUT
|
||||||
|
- name: Checkout
|
||||||
|
if: steps.value_holder.outputs.ACTIONS_ENABLED
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
- name: Setup git
|
||||||
|
if: steps.value_holder.outputs.ACTIONS_ENABLED
|
||||||
|
run: |
|
||||||
|
git config --global user.name "gbp-action"
|
||||||
|
git config --global user.email "<>"
|
||||||
|
- name: Checkout alternate branch
|
||||||
|
if: steps.value_holder.outputs.ACTIONS_ENABLED
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
with:
|
||||||
|
ref: "gbp-balances" # The branch name
|
||||||
|
path: gbp-balances
|
||||||
|
# This is to ensure we keep the gbp.toml from master
|
||||||
|
# without having to update our separate branch.
|
||||||
|
- name: Copy configuration
|
||||||
|
if: steps.value_holder.outputs.ACTIONS_ENABLED
|
||||||
|
run: cp ./.github/gbp.toml ./gbp-balances/.github/gbp.toml
|
||||||
|
- name: GBP action
|
||||||
|
if: steps.value_holder.outputs.ACTIONS_ENABLED
|
||||||
|
uses: tgstation/gbp-action@master
|
||||||
|
with:
|
||||||
|
branch: "gbp-balances"
|
||||||
|
directory: ./gbp-balances
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
44
.github/workflows/gbp_collect.yml
vendored
Normal file
44
.github/workflows/gbp_collect.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
name: GBP Collection
|
||||||
|
# Every hour at the :20 minute mark. GitHub tells us to pick odd hours, instead of just using the start.
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "20 * * * *"
|
||||||
|
workflow_dispatch:
|
||||||
|
jobs:
|
||||||
|
gbp_collection:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Check for ACTION_ENABLER secret and pass true to output if it exists to be checked by later steps"
|
||||||
|
id: value_holder
|
||||||
|
env:
|
||||||
|
ENABLER_SECRET: ${{ secrets.ACTION_ENABLER }}
|
||||||
|
run: |
|
||||||
|
unset SECRET_EXISTS
|
||||||
|
if [ -n "$ENABLER_SECRET" ]; then SECRET_EXISTS=true ; fi
|
||||||
|
echo "ACTIONS_ENABLED=$SECRET_EXISTS" >> $GITHUB_OUTPUT
|
||||||
|
- name: Checkout
|
||||||
|
if: steps.value_holder.outputs.ACTIONS_ENABLED
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
- name: Setup git
|
||||||
|
if: steps.value_holder.outputs.ACTIONS_ENABLED
|
||||||
|
run: |
|
||||||
|
git config --global user.name "github-actions[bot]"
|
||||||
|
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
- name: Checkout alternate branch
|
||||||
|
if: steps.value_holder.outputs.ACTIONS_ENABLED
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
with:
|
||||||
|
ref: "gbp-balances" # The branch name
|
||||||
|
path: gbp-balances
|
||||||
|
# This is to ensure we keep the gbp.toml from master
|
||||||
|
# without having to update our separate branch.
|
||||||
|
- name: Copy configuration
|
||||||
|
if: steps.value_holder.outputs.ACTIONS_ENABLED
|
||||||
|
run: cp ./.github/gbp.toml ./gbp-balances/.github/gbp.toml
|
||||||
|
- name: GBP action
|
||||||
|
if: steps.value_holder.outputs.ACTIONS_ENABLED
|
||||||
|
uses: tgstation/gbp-action@master
|
||||||
|
with:
|
||||||
|
collect: "true"
|
||||||
|
directory: ./gbp-balances
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -3,5 +3,9 @@
|
|||||||
#define USE_CUSTOM_ERROR_HANDLER
|
#define USE_CUSTOM_ERROR_HANDLER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/// If this is uncommented, Autowiki will generate edits and shut down the server.
|
||||||
|
/// Prefer the autowiki build target instead.
|
||||||
|
// #define AUTOWIKI
|
||||||
|
|
||||||
// We do not have dreamlua implemented
|
// We do not have dreamlua implemented
|
||||||
#define DISABLE_DREAMLUAU
|
#define DISABLE_DREAMLUAU
|
||||||
|
|||||||
33
code/modules/autowiki/autowiki.dm
Normal file
33
code/modules/autowiki/autowiki.dm
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/// When the `AUTOWIKI` define is enabled, will generate an output file for tools/autowiki/autowiki.js to consume.
|
||||||
|
/// Autowiki code intentionally still *exists* even without the define, to ensure developers notice
|
||||||
|
/// when they break it immediately, rather than until CI or worse, call time.
|
||||||
|
#if defined(AUTOWIKI) || defined(UNIT_TESTS)
|
||||||
|
/proc/setup_autowiki()
|
||||||
|
Master.sleep_offline_after_initializations = FALSE
|
||||||
|
SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(generate_autowiki)))
|
||||||
|
SSticker.start_immediately = TRUE
|
||||||
|
CONFIG_SET(number/round_end_countdown, 0)
|
||||||
|
|
||||||
|
/proc/generate_autowiki()
|
||||||
|
var/output = generate_autowiki_output()
|
||||||
|
rustg_file_write(output, "data/autowiki_edits.txt")
|
||||||
|
qdel(world)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Returns a string of the autowiki output file
|
||||||
|
/proc/generate_autowiki_output()
|
||||||
|
var/total_output = ""
|
||||||
|
|
||||||
|
for (var/datum/autowiki/autowiki_type as anything in subtypesof(/datum/autowiki))
|
||||||
|
var/datum/autowiki/autowiki = new autowiki_type
|
||||||
|
var/output = autowiki.generate()
|
||||||
|
|
||||||
|
if (!istext(output))
|
||||||
|
CRASH("[autowiki_type] does not generate a proper output!")
|
||||||
|
|
||||||
|
total_output += json_encode(list(
|
||||||
|
"title" = autowiki.page,
|
||||||
|
"text" = output,
|
||||||
|
)) + "\n"
|
||||||
|
|
||||||
|
return total_output
|
||||||
59
code/modules/autowiki/page/base.dm
Normal file
59
code/modules/autowiki/page/base.dm
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/// A representation of an automated wiki page.
|
||||||
|
/datum/autowiki
|
||||||
|
/// The page on the wiki to be replaced.
|
||||||
|
/// This should never be a user-facing page, like "Guide to circuits".
|
||||||
|
/// It should always be a template that only Autowiki should touch.
|
||||||
|
/// For example: "Template:Autowiki/CircuitInfo".
|
||||||
|
var/page
|
||||||
|
|
||||||
|
/// Override and return the new text of the page.
|
||||||
|
/// This proc can be impure, usually to call `upload_file`.
|
||||||
|
/datum/autowiki/proc/generate()
|
||||||
|
SHOULD_CALL_PARENT(FALSE)
|
||||||
|
CRASH("[type] does not implement generate()!")
|
||||||
|
|
||||||
|
/// Generates an auto formatted template user.
|
||||||
|
/// Your autowiki should ideally be a *lot* of these.
|
||||||
|
/// It lets wiki editors edit it much easier later, without having to enter repo.
|
||||||
|
/// Parameters will be passed in by name. That means your template should expect
|
||||||
|
/// something that looks like `{{ Autowiki_Circuit|name=Combiner|description=This combines }}`
|
||||||
|
/// Lists, which must be array-like (no keys), will be turned into a flat list with their key and a number,
|
||||||
|
/// such that list("food" = list("fruit", "candy")) -> food1=fruit|food2=candy
|
||||||
|
/datum/autowiki/proc/include_template(name, parameters)
|
||||||
|
var/template_text = "{{[name]"
|
||||||
|
|
||||||
|
var/list/prepared_parameters = list()
|
||||||
|
for (var/key in parameters)
|
||||||
|
var/value = parameters[key]
|
||||||
|
if (islist(value))
|
||||||
|
for (var/index in 1 to length(value))
|
||||||
|
prepared_parameters["[key][index]"] = "[value[index]]"
|
||||||
|
else
|
||||||
|
prepared_parameters[key] = value
|
||||||
|
|
||||||
|
for (var/parameter_name in prepared_parameters)
|
||||||
|
template_text += "|[parameter_name]="
|
||||||
|
template_text += "[prepared_parameters[parameter_name]]"
|
||||||
|
|
||||||
|
template_text += "}}"
|
||||||
|
|
||||||
|
return template_text
|
||||||
|
|
||||||
|
/// Takes an icon and uploads it to Autowiki-name.png.
|
||||||
|
/// Do your best to make sure this is unique, so it doesn't clash with other autowiki icons.
|
||||||
|
/datum/autowiki/proc/upload_icon(icon/icon, name)
|
||||||
|
// Fuck you
|
||||||
|
if (IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
var/static/uploaded_icons = list()
|
||||||
|
if(uploaded_icons["[name]"])
|
||||||
|
CRASH("We tried uploading an icon, but the name \"[name]\" was already taken!")
|
||||||
|
|
||||||
|
fcopy(icon, "data/autowiki_files/[name].png")
|
||||||
|
uploaded_icons["[name]"] = TRUE
|
||||||
|
|
||||||
|
/// Escape a parameter such that it can be correctly put inside a wiki output
|
||||||
|
/datum/autowiki/proc/escape_value(parameter)
|
||||||
|
// | is a special character in MediaWiki, and must be escaped by...using another template.
|
||||||
|
return replacetextEx(parameter, "|", "{{!}}")
|
||||||
36
code/modules/autowiki/page/symptom.dm
Normal file
36
code/modules/autowiki/page/symptom.dm
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/datum/autowiki/symptom
|
||||||
|
page = "Template:Autowiki/Content/Symptoms"
|
||||||
|
|
||||||
|
/datum/autowiki/symptom/generate()
|
||||||
|
var/output = ""
|
||||||
|
|
||||||
|
var/list/template_list = list()
|
||||||
|
|
||||||
|
for(var/the_symptom in subtypesof(/datum/symptom))
|
||||||
|
var/datum/symptom/symptom = new the_symptom
|
||||||
|
|
||||||
|
if(symptom.level < 0) // Skip base/admin symptoms
|
||||||
|
continue
|
||||||
|
|
||||||
|
template_list["name"] = escape_value(symptom.name)
|
||||||
|
template_list["stealth"] = symptom.stealth
|
||||||
|
template_list["resistance"] = symptom.resistance
|
||||||
|
template_list["speed"] = symptom.stage_speed
|
||||||
|
template_list["transmission"] = symptom.transmission
|
||||||
|
template_list["level"] = symptom.level
|
||||||
|
template_list["effect"] = escape_value(symptom.desc)
|
||||||
|
template_list["thresholds"] = length(symptom.threshold_descs) ? generate_thresholds(symptom.threshold_descs) : "None"
|
||||||
|
|
||||||
|
output += include_template("Autowiki/SymptomTemplate", template_list)
|
||||||
|
|
||||||
|
return include_template("Autowiki/SymptomTableTemplate", list("content" = output))
|
||||||
|
|
||||||
|
/datum/autowiki/symptom/proc/generate_thresholds(var/list/thresholds)
|
||||||
|
var/compiled_thresholds = ""
|
||||||
|
|
||||||
|
for(var/threshold in thresholds)
|
||||||
|
var/description = thresholds[threshold]
|
||||||
|
if(length(threshold))
|
||||||
|
compiled_thresholds += "<li><b>[threshold]:</b> [description]</li>"
|
||||||
|
|
||||||
|
return compiled_thresholds
|
||||||
68
code/modules/autowiki/page/techweb.dm
Normal file
68
code/modules/autowiki/page/techweb.dm
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/datum/autowiki/techweb
|
||||||
|
page = "Template:Autowiki/Content/Techweb"
|
||||||
|
|
||||||
|
/datum/autowiki/techweb/generate()
|
||||||
|
var/output = ""
|
||||||
|
|
||||||
|
for (var/node_id in sortList(SSresearch.techweb_nodes, GLOBAL_PROC_REF(sort_research_nodes)))
|
||||||
|
var/datum/techweb_node/node = SSresearch.techweb_nodes[node_id]
|
||||||
|
if (!node.show_on_wiki)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (!valid_node(node))
|
||||||
|
continue
|
||||||
|
|
||||||
|
output += "\n\n" + include_template("Autowiki/TechwebEntry", list(
|
||||||
|
"name" = escape_value(node.display_name),
|
||||||
|
"description" = escape_value(node.description),
|
||||||
|
"prerequisites" = generate_prerequisites(node.prereq_ids),
|
||||||
|
"designs" = generate_designs(node.design_ids),
|
||||||
|
))
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
/datum/autowiki/techweb/proc/valid_node(datum/techweb_node/node)
|
||||||
|
return !node.experimental
|
||||||
|
|
||||||
|
/datum/autowiki/techweb/proc/generate_designs(list/design_ids)
|
||||||
|
var/output = ""
|
||||||
|
|
||||||
|
for (var/design_id in design_ids)
|
||||||
|
var/datum/design_techweb/design = SSresearch.techweb_designs[design_id]
|
||||||
|
output += include_template("Autowiki/TechwebEntryDesign", list(
|
||||||
|
"name" = escape_value(design.name),
|
||||||
|
"description" = escape_value(design.get_description()),
|
||||||
|
))
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
/datum/autowiki/techweb/proc/generate_prerequisites(list/prereq_ids)
|
||||||
|
var/output = ""
|
||||||
|
|
||||||
|
for (var/prereq_id in prereq_ids)
|
||||||
|
var/datum/techweb_node/node = SSresearch.techweb_nodes[prereq_id]
|
||||||
|
output += include_template("Autowiki/TechwebEntryPrerequisite", list(
|
||||||
|
"name" = escape_value(node.display_name),
|
||||||
|
))
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
/datum/autowiki/techweb/experimental
|
||||||
|
page = "Template:Autowiki/Content/Techweb/Experimental"
|
||||||
|
|
||||||
|
/datum/autowiki/techweb/experimental/valid_node(datum/techweb_node/node)
|
||||||
|
return node.experimental
|
||||||
|
|
||||||
|
/proc/sort_research_nodes(node_id_a, node_id_b)
|
||||||
|
var/datum/techweb_node/node_a = SSresearch.techweb_nodes[node_id_a]
|
||||||
|
var/datum/techweb_node/node_b = SSresearch.techweb_nodes[node_id_b]
|
||||||
|
|
||||||
|
var/prereq_difference = node_a.prereq_ids.len - node_b.prereq_ids.len
|
||||||
|
if (prereq_difference != 0)
|
||||||
|
return prereq_difference
|
||||||
|
|
||||||
|
var/experiment_difference = node_a.required_experiments.len - node_b.required_experiments.len
|
||||||
|
if (experiment_difference != 0)
|
||||||
|
return experiment_difference
|
||||||
|
|
||||||
|
return sorttext(node_b.display_name, node_a.display_name)
|
||||||
59
code/modules/autowiki/page/vending.dm
Normal file
59
code/modules/autowiki/page/vending.dm
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/datum/autowiki/vending
|
||||||
|
page = "Template:Autowiki/Content/VendingMachines"
|
||||||
|
|
||||||
|
/datum/autowiki/vending/generate()
|
||||||
|
var/output = ""
|
||||||
|
|
||||||
|
var/list/cached_products = list()
|
||||||
|
|
||||||
|
// `powered()` checks if its in a null loc to say it's not powered.
|
||||||
|
// So we put it inside, something
|
||||||
|
var/obj/parent = new
|
||||||
|
|
||||||
|
for (var/obj/machinery/vending/vending_type as anything in sortList(subtypesof(/obj/machinery/vending), GLOBAL_PROC_REF(cmp_typepaths_asc)))
|
||||||
|
var/obj/machinery/vending/parent_machine = type2parent(vending_type)
|
||||||
|
if(initial(parent_machine.name) == initial(vending_type.name))
|
||||||
|
continue //Same name, likely just a slightly touched up subtype for specific maps.
|
||||||
|
var/obj/machinery/vending/vending_machine = new vending_type(parent)
|
||||||
|
vending_machine.use_power = FALSE
|
||||||
|
vending_machine.update_icon(UPDATE_ICON_STATE)
|
||||||
|
|
||||||
|
// Technically won't match if product amounts change, but this isn't likely
|
||||||
|
var/products_cache_key = vending_machine.products.Join("-") + "&" + vending_machine.contraband.Join("-") + "&" + vending_machine.premium.Join("-")
|
||||||
|
|
||||||
|
// In the future, this should show all vending machines that have the same products
|
||||||
|
if (products_cache_key in cached_products)
|
||||||
|
qdel(vending_machine)
|
||||||
|
continue
|
||||||
|
|
||||||
|
cached_products += products_cache_key
|
||||||
|
|
||||||
|
var/filename = SANITIZE_FILENAME(escape_value(format_text(vending_machine.name)))
|
||||||
|
|
||||||
|
output += include_template("Autowiki/VendingMachine", list(
|
||||||
|
"icon" = escape_value(filename),
|
||||||
|
"name" = escape_value(format_text(vending_machine.name)),
|
||||||
|
"products" = format_product_list(vending_machine.products),
|
||||||
|
"contraband" = format_product_list(vending_machine.contraband),
|
||||||
|
"premium" = format_product_list(vending_machine.premium),
|
||||||
|
))
|
||||||
|
|
||||||
|
// It would be cool to make this support gifs someday, but not now
|
||||||
|
upload_icon(getFlatIcon(vending_machine, no_anim = TRUE), filename)
|
||||||
|
|
||||||
|
qdel(vending_machine)
|
||||||
|
|
||||||
|
qdel(parent)
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
/datum/autowiki/vending/proc/format_product_list(list/product_list)
|
||||||
|
var/output = ""
|
||||||
|
|
||||||
|
for (var/obj/product_path as anything in product_list)
|
||||||
|
output += include_template("Autowiki/VendingMachineProduct", list(
|
||||||
|
"name" = escape_value(capitalize(format_text(initial(product_path.name)))),
|
||||||
|
"amount" = product_list[product_path],
|
||||||
|
))
|
||||||
|
|
||||||
|
return output
|
||||||
@@ -88,6 +88,7 @@
|
|||||||
|
|
||||||
// BEGIN_INCLUDE
|
// BEGIN_INCLUDE
|
||||||
#include "asset_smart_cache.dm"
|
#include "asset_smart_cache.dm"
|
||||||
|
#include "autowiki.dm"
|
||||||
//#include "clothing_tests.dm" // FIXME
|
//#include "clothing_tests.dm" // FIXME
|
||||||
#include "component_tests.dm"
|
#include "component_tests.dm"
|
||||||
#include "cosmetic_tests.dm"
|
#include "cosmetic_tests.dm"
|
||||||
|
|||||||
35
code/modules/unit_tests/autowiki.dm
Normal file
35
code/modules/unit_tests/autowiki.dm
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/// Tests that all autowikis generate something without runtiming
|
||||||
|
/datum/unit_test/autowiki
|
||||||
|
|
||||||
|
/datum/unit_test/autowiki/Run()
|
||||||
|
TEST_ASSERT(istext(generate_autowiki_output()), "generate_autowiki_output() did not finish successfully!")
|
||||||
|
|
||||||
|
/// Test that `include_template` produces reasonable results
|
||||||
|
/datum/unit_test/autowiki_include_template
|
||||||
|
|
||||||
|
/datum/unit_test/autowiki_include_template/Run()
|
||||||
|
var/datum/autowiki/autowiki_api = new
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL( \
|
||||||
|
autowiki_api.include_template("Template"), \
|
||||||
|
"{{Template}}", \
|
||||||
|
"Basic template did not format correctly" \
|
||||||
|
)
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL( \
|
||||||
|
autowiki_api.include_template("Template", list("name" = "Mothblocks")), \
|
||||||
|
"{{Template|name=Mothblocks}}", \
|
||||||
|
"Template with basic arguments did not format correctly" \
|
||||||
|
)
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL( \
|
||||||
|
autowiki_api.include_template("Template", list("name" = autowiki_api.escape_value("P|peline"))), \
|
||||||
|
"{{Template|name=P{{!}}peline}}", \
|
||||||
|
"Template with escaped arguments did not format correctly" \
|
||||||
|
)
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL( \
|
||||||
|
autowiki_api.include_template("Template", list("food" = list("fruit", "candy"))), \
|
||||||
|
"{{Template|food1=fruit|food2=candy}}", \
|
||||||
|
"Template with array arguments did not format correctly" \
|
||||||
|
)
|
||||||
85
tools/autowiki/autowiki.js
Normal file
85
tools/autowiki/autowiki.js
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
const fs = require('fs').promises;
|
||||||
|
const MWBot = require('mwbot');
|
||||||
|
|
||||||
|
const { USERNAME, PASSWORD } = process.env;
|
||||||
|
|
||||||
|
if (!USERNAME) {
|
||||||
|
console.error('USERNAME was not set.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PASSWORD) {
|
||||||
|
console.error('PASSWORD was not set.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const PAGE_EDIT_FILENAME = process.argv[2];
|
||||||
|
|
||||||
|
if (!PAGE_EDIT_FILENAME) {
|
||||||
|
console.error('No filename specified to edit pages');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const FILE_EDIT_FILENAME = process.argv[3];
|
||||||
|
|
||||||
|
if (!FILE_EDIT_FILENAME) {
|
||||||
|
console.error('No filename specified to edit files');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
console.log(`Reading from ${PAGE_EDIT_FILENAME}`);
|
||||||
|
const editFile = await (await fs.readFile(PAGE_EDIT_FILENAME, 'utf8')).split(
|
||||||
|
'\n',
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(`Logging in as ${USERNAME}`);
|
||||||
|
|
||||||
|
const bot = new MWBot();
|
||||||
|
|
||||||
|
await bot.loginGetEditToken({
|
||||||
|
apiUrl: 'https://wiki.chompstation13.net/api.php',
|
||||||
|
username: USERNAME,
|
||||||
|
password: PASSWORD,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('Logged in');
|
||||||
|
|
||||||
|
// This is not Promise.all as to not flood with a bunch of traffic at once
|
||||||
|
for (const editLine of editFile) {
|
||||||
|
if (editLine.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { title, text } = JSON.parse(editLine);
|
||||||
|
text =
|
||||||
|
'<noinclude><b>This page is automated by Autowiki. Do NOT edit it manually.</b></noinclude>' +
|
||||||
|
text;
|
||||||
|
|
||||||
|
console.log(`Editing ${title}...`);
|
||||||
|
await bot.edit(title, text, `Autowiki edit @ ${new Date().toISOString()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same here
|
||||||
|
for (const asset of await fs.readdir(FILE_EDIT_FILENAME)) {
|
||||||
|
const assetPath = `${FILE_EDIT_FILENAME}/${asset}`;
|
||||||
|
const assetName = `Autowiki-${asset}`;
|
||||||
|
|
||||||
|
console.log(`Replacing ${assetName}...`);
|
||||||
|
await bot
|
||||||
|
.upload(
|
||||||
|
assetName,
|
||||||
|
assetPath,
|
||||||
|
`Autowiki upload @ ${new Date().toISOString()}`,
|
||||||
|
)
|
||||||
|
.catch((error) => {
|
||||||
|
if (error.code === 'fileexists-no-change') {
|
||||||
|
console.log(`${assetName} is an exact duplicate`);
|
||||||
|
} else {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(console.error);
|
||||||
10
tools/autowiki/package.json
Normal file
10
tools/autowiki/package.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"name": "autowiki",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Automatically publish generated pages to the virgo wiki",
|
||||||
|
"main": "autowiki.js",
|
||||||
|
"author": "Mothblocks",
|
||||||
|
"dependencies": {
|
||||||
|
"mwbot": "^2.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
59
tools/pull_request_hooks/autoLabel.test.js
Normal file
59
tools/pull_request_hooks/autoLabel.test.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import { strict as assert } from 'node:assert';
|
||||||
|
import { get_updated_label_set } from './autoLabel.js';
|
||||||
|
|
||||||
|
const empty_pr = {
|
||||||
|
action: 'opened',
|
||||||
|
pull_request: {
|
||||||
|
body: 'This PR will have no labels',
|
||||||
|
title: 'Pr with no labels',
|
||||||
|
mergeable: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const empty_label_set = await get_updated_label_set({
|
||||||
|
github: null,
|
||||||
|
context: { payload: empty_pr },
|
||||||
|
});
|
||||||
|
assert.equal(empty_label_set.length, 0, 'No labels should be added');
|
||||||
|
|
||||||
|
const cl = `
|
||||||
|
My Awesome PR
|
||||||
|
|
||||||
|
:cl: Awesome Dude
|
||||||
|
add: Adds Awesome Stuff
|
||||||
|
refactor: refactored some code
|
||||||
|
:/cl:
|
||||||
|
`;
|
||||||
|
const cl_pr = {
|
||||||
|
action: 'opened',
|
||||||
|
pull_request: {
|
||||||
|
body: cl,
|
||||||
|
title: 'Awesome PR',
|
||||||
|
mergeable: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const cl_label_set = await get_updated_label_set({
|
||||||
|
github: null,
|
||||||
|
context: { payload: cl_pr },
|
||||||
|
});
|
||||||
|
assert.ok(
|
||||||
|
cl_label_set.includes('Merge Conflict'),
|
||||||
|
'Merge Conflict label should be added',
|
||||||
|
);
|
||||||
|
assert.ok(cl_label_set.includes('Feature'), 'Feature label should be added');
|
||||||
|
assert.ok(
|
||||||
|
!cl_label_set.includes('Refactor'),
|
||||||
|
'Refactor label should not be added',
|
||||||
|
);
|
||||||
|
|
||||||
|
const title_pr = {
|
||||||
|
action: 'opened',
|
||||||
|
pull_request: {
|
||||||
|
title: 'Logging is important',
|
||||||
|
mergeable: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const title_label_set = await get_updated_label_set({
|
||||||
|
github: null,
|
||||||
|
context: { payload: title_pr },
|
||||||
|
});
|
||||||
|
assert.ok(title_label_set.includes('Logging'), 'Logging label should be added');
|
||||||
@@ -2283,6 +2283,10 @@
|
|||||||
#include "code\modules\asset_cache\iconforge\universal_icon.dm"
|
#include "code\modules\asset_cache\iconforge\universal_icon.dm"
|
||||||
#include "code\modules\asset_cache\transports\asset_transport.dm"
|
#include "code\modules\asset_cache\transports\asset_transport.dm"
|
||||||
#include "code\modules\asset_cache\transports\webroot_transport.dm"
|
#include "code\modules\asset_cache\transports\webroot_transport.dm"
|
||||||
|
#include "code\modules\autowiki\autowiki.dm"
|
||||||
|
#include "code\modules\autowiki\page\base.dm"
|
||||||
|
#include "code\modules\autowiki\page\symptom.dm"
|
||||||
|
#include "code\modules\autowiki\page\techweb.dm"
|
||||||
#include "code\modules\awaymissions\bluespaceartillery.dm"
|
#include "code\modules\awaymissions\bluespaceartillery.dm"
|
||||||
#include "code\modules\awaymissions\corpse.dm"
|
#include "code\modules\awaymissions\corpse.dm"
|
||||||
#include "code\modules\awaymissions\exile.dm"
|
#include "code\modules\awaymissions\exile.dm"
|
||||||
|
|||||||
Reference in New Issue
Block a user