Contributing
Review checklist
What the automated test and the maintainers check in a script pull request, as a list you can run through first.
Go through this list before you open a pull request, or when you review someone else's. Each item names where it comes from: the pull request checks, the script test, or the rules in AGENTS.md that maintainers review against. Coding rules explains the rules with examples.
The pull request
- It targets the right repository: DevScripts for a new script, ProxmoxVE for a fix.
- The template is filled in, not replaced. In DevScripts the "Application Requirements" section must stay even when the pull request is not a new script.
- New script: all four application requirements, one arm64 option, one AI option, "No Docker / Docker Compose" and "No git pull" are ticked.
- The AI section says which model was used and how far, or "No AI used" is ticked.
- The description is two to five sentences and says how the script was tested.
- It contains one script or one fix. No unrelated files, no reformatting of lines the change does not touch.
The ct/ script
- The first lines are the unchanged bootstrap from the template. In DevScripts that includes the
_CS_DEFAULT_URLline; no comment block above it. - The header names the author, the licence and the upstream source.
-
APP,var_tags,var_cpu,var_ram,var_disk,var_os,var_versionandvar_unprivilegedare declared in the"${var_x:-default}"form, so a value from the environment wins. -
var_arm64is decided:yesonly if it ran on arm64,nowith the reason next to it, commented out only if nobody could tell. - Every application variable the install script reads is exported:
export var_x="${var_x:-}". -
header_info "$APP",variables,color,catch_errorsfollow the declarations, in that order. -
update_scriptis the only function (apart fromupdate_deb_based-style dispatch functions in a multi-OS script). - The file ends with
start,build_container,descriptionand the standard closing lines, at most one extra line. Noif, nopct exec, no instructions. - The address in the closing block is what a user opens. The test requests exactly this address and expects a 2xx answer.
- Nothing in the script assumes Proxmox VE. The test builds the same file on an Incus host.
The install script
- It starts with
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH",color,verb_ip6,catch_errors,setting_up_container,network_check,update_osand ends withmotd_ssh,customize,cleanup_lxc. - No function definitions (apart from
setup_deb_based-style dispatch functions in a multi-OS script). - Downloads go through
fetch_and_deploy_*; runtimes and databases throughsetup_*. No hand-writtencurl/tar,git clone, version lookups or repository keys. - No Docker.
-
setup_*,fetch_and_deploy_*andcheck_for_*calls are not wrapped inmsg_info/msg_ok. - Every other step is inside one
msg_info/msg_okpair, and every pair is closed. Messages name the application. -
$STDis in front of every package, build and migration command.apt, notapt-get. - No package in the dependency list that the container already has.
- No password, token or key is written literally. Secrets are generated (
random_password,openssl rand -hex 32) or come from a helper (PG_DB_PASS). - Every
readis guarded by a check for an emptyvar_x, or aprompt_*helper is used. The test reports a barereadas "unanswerable prompt". - Files are written with heredocs.
.envfiles contain noexport. - Services run as root; no service user, no
sudo. - The service does not exit or restart on its own. The test counts unit restarts over 60 seconds and reports any as "not stable".
- No comments besides the header, at most a single short one where a line would otherwise look wrong.
Updates
-
update_scriptstarts withheader_info,check_container_storage,check_container_resources, checks that the application is installed, and ends withexit. - The update check is
check_for_gh_release(or the variant for the forge) with the same name the install script passed tofetch_and_deploy_*. - The script never writes a version file itself. The test fails with "reported success, but ... is still ..." when the file does not change.
- Services are stopped before the deploy and started after it.
-
CLEAN_INSTALL=1does not destroy user data: data lives outside the application directory, or is kept withCLEAN_INSTALL_KEEP(directories) orcreate_backup/restore_backup(files). Nothing is backed up to/tmp. - A successful update ends with
msg_ok "Updated successfully!". - Running
updatetwice in a row is harmless. The test runs it a second time and notes when it updates again. - In ProxmoxVE: a container installed from
mainupdates cleanly with the changedupdate_script. The test does this as the upgrade run.
The JSON file (DevScripts)
-
slugequals the file names:json/<slug>.json,ct/<slug>.sh,install/<slug>-install.sh. -
install_methods[].resourcesequalvar_cpu,var_ram,var_disk,var_osandvar_versionof thect/script. -
architecturesagrees withvar_arm64;platformslists only what was tested. -
repositoryis a full URL. -
interface_portis the port in the closing block. -
config_pathsits on the install method, not at the top level. - Every exported
var_xis declared inapp_varswith exactly that name; credentials carry"secret": true. - At most three short notes.
default_credentialsisnullunless the application really ships fixed ones. - No maintainer-owned fields, see the JSON template.
What the test tells you that reading does not
The script test builds the script, so some review questions are answered by its result:
| Question | Where to look in the result |
|---|---|
| Does it install unattended? | The Install column; an unanswerable prompt is named in Detail |
| Does it run on Incus as well? | The incus row |
| Does it work on arm64? | The arm64 row, information only |
| Are the resource defaults enough? | The "Resources" block and the notes about var_disk and var_ram |
| Does the web interface come up? | Detail shows the address and the status code; the screenshot shows the page |
Does update_script work? | The Update column and the update log |
| Does the service stay up? | A "not stable" finding |
What it cannot tell: whether the script follows the rules above, whether user data survives an update, and whether the application is configured sensibly. That is what the human review is for.