Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/hotcrp.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# HotCRP submission settings.
# HOTCRP_TOKEN is intentionally not stored here. Configure it as a GitHub
# Actions repository secret, or provide it in the local environment.
: "${HOTCRP_ACTION_UPLOAD_ENABLED:=false}"
: "${HOTCRP_SITE_URL:=https://TODO.hotcrp.com}"
: "${HOTCRP_PID:=TODO}"
13 changes: 13 additions & 0 deletions .github/workflows/build_paper.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@ jobs:
files: |
paper.pdf
submission.pdf

- name: Set up Python for HotCRP response validation
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
uses: actions/setup-python@v5
with:
python-version: "3.x"

- name: Upload to HotCRP
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
env:
HOTCRP_TOKEN: ${{ secrets.HOTCRP_TOKEN }}
run: bash ./tools/upload-to-hotcrp.sh .github/hotcrp.env

build-texlive-2024:
runs-on: ubuntu-latest

Expand Down
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Download:
[Paper (with comments)](../../releases/latest/download/paper.pdf)
[Submission (without comments)](../../releases/latest/download/submission.pdf) |


### Conference: ASPLOS

- Abstract: 2025-08-13T23:59:00-05:00
Expand Down Expand Up @@ -67,3 +68,28 @@ git merge upstream/main
```bash
tools/generate_lexers_json.py
```

## HotCRP CI/CD

This repository has support for opt-in automatic submission of `submission.pdf` to HotCRP on every push to main.
This requires setting up the submission in HotCRP first.

0. For this example, we will take `https://asplos26.hotcrp.com` as the HotCRP site.
1. Create the paper submission on the HotCRP website. `HOTCRP_PID` is the paper's submission ID in the URL (eg. `https://asplos26.hotcrp.com/paper/HOTCRP_PID`)
2. Create an Authentication Token in HotCRP's **Account Settings**: (eg. `https://asplos26.hotcrp.com/profile/developer`)
3. Set up `.github/hotcrp.env` with the values from HotCRP, and set `HOTCRP_ACTION_UPLOAD_ENABLED:=true` to enable uploading by GitHub Actions.

```sh
: "${HOTCRP_SITE_URL:=https://asplos26.hotcrp.com}"
: "${HOTCRP_PID:=67}"
: "${HOTCRP_ACTION_UPLOAD_ENABLED:=true}"
```

4. Lastly, add the `HOTCRP_TOKEN` repository secret in GitHub under **Settings -> Secrets and variables -> Actions**.

The submission script can also be run locally instead of via GitHub actions.
Don't forget to provide the token in the environment.

```sh
HOTCRP_TOKEN=... bash tools/upload-to-hotcrp.sh .github/hotcrp.env
```
6 changes: 5 additions & 1 deletion paper.tex
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,16 @@
\usepackage{etoolbox}
\usepackage[acronym,shortcuts]{glossaries}
\usepackage{amsmath}
\usepackage{thmtools} % required for autoref to lemmas
\usepackage{algorithm}
\usepackage[noend]{algpseudocode}
\usepackage{hyphenat}
\usepackage[shortcuts]{extdash}

% Load thmtools after acmart has created its built-in theorem environments.
% Newer thmtools aliases shared counters before \newtheorem, which collides
% with acmart's default conjecture/proposition/lemma definitions otherwise.
\AtEndPreamble{\usepackage{thmtools}}

\input{tex/setup.tex}
\input{tex/acm.tex}

Expand Down
139 changes: 139 additions & 0 deletions tools/upload-to-hotcrp.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#!/usr/bin/env bash
set -euo pipefail

default_config_file=".github/hotcrp.env"
config_file="${1:-$default_config_file}"

usage() {
cat <<'EOF'
Usage:
tools/upload-to-hotcrp.sh [CONFIG_FILE]
tools/upload-to-hotcrp.sh --help

Uploads a paper PDF to the configured HotCRP submission, to be run from root of
the repository.

CONFIG_FILE is sourced as a shell env file, with .github/hotcrp as the default.
Environment variables take precedence over CONFIG_FILE defaults when CONFIG_FILE
uses Bash default assignments such as : "${HOTCRP_PID:=TODO}".

Required values:
HOTCRP_SITE_URL HotCRP site base URL, e.g. https://asplos26.hotcrp.com
HOTCRP_PID Numeric HotCRP paper ID
HOTCRP_TOKEN HotCRP API token

GitHub Actions control:
HOTCRP_ACTION_UPLOAD_ENABLED
In GitHub Actions, must be exactly true to upload.
Defaults to false.

Optional overrides:
HOTCRP_PDF PDF to upload. Defaults to submission.pdf.

Local example:
HOTCRP_TOKEN=... tools/upload-to-hotcrp.sh .github/hotcrp.env
HOTCRP_SITE_URL=... HOTCRP_PID=123 HOTCRP_TOKEN=... tools/upload-to-hotcrp.sh
EOF
}

die() {
printf 'error: %s\n' "$*" >&2
exit 1
}

require_var() {
local name="$1"
local value="${!name:-}"

if [ -z "$value" ] || [[ "$value" == *TODO* ]]; then
die "$name is not set. Update $config_file or provide it in the environment."
fi
}

require_command() {
local name="$1"

command -v "$name" >/dev/null 2>&1 || die "required command is not available: $name"
}

case "${1:-}" in
-h|--help)
usage
exit 0
;;
esac

if [ "$#" -gt 0 ] || [ -f "$config_file" ]; then
[ -f "$config_file" ] || die "missing HotCRP config file: $config_file"

set -a
. "$config_file"
set +a
fi

HOTCRP_ACTION_UPLOAD_ENABLED="${HOTCRP_ACTION_UPLOAD_ENABLED:-false}"
HOTCRP_PDF="${HOTCRP_PDF:-submission.pdf}"

if [ "${GITHUB_ACTIONS:-false}" = "true" ] && [ "$HOTCRP_ACTION_UPLOAD_ENABLED" != "true" ]; then
printf 'HotCRP upload is disabled by %s; set HOTCRP_ACTION_UPLOAD_ENABLED=true to enable it.\n' "$config_file"
exit 0
fi

require_var HOTCRP_SITE_URL
require_var HOTCRP_PID
require_var HOTCRP_TOKEN

require_command curl
require_command python3
require_command zip

HOTCRP_SITE_URL="${HOTCRP_SITE_URL%/}"

case "$HOTCRP_PID" in
''|*[!0-9]*)
die "HOTCRP_PID must be a numeric paper ID."
;;
esac

[ -f "$HOTCRP_PDF" ] || die "missing PDF to upload: $HOTCRP_PDF"

workdir="$(mktemp -d)"
trap 'rm -rf "$workdir"' EXIT

cp "$HOTCRP_PDF" "$workdir/submission.pdf"

cat > "$workdir/data.json" <<EOF
{
"object": "paper",
"pid": $HOTCRP_PID,
"submission": { "content_file": "submission.pdf" }
}
EOF

(
cd "$workdir"
zip -q upload.zip data.json submission.pdf
)

# The actual upload
curl -fsS \
-H "Authorization: bearer $HOTCRP_TOKEN" \
-H "Content-Type: application/zip" \
--data-binary @"$workdir/upload.zip" \
"$HOTCRP_SITE_URL/api/paper" \
> hotcrp-response.json

# Error reporting uses Python3's stdlib json to avoid installing extra packages
# in the actions container
python3 - <<'PY'
import json
import sys

with open("hotcrp-response.json") as f:
response = json.load(f)

print(json.dumps(response, indent=2))

if not response.get("ok") or not response.get("valid", False):
sys.exit("HotCRP upload failed")
PY
Loading