mirror of
https://github.com/cp2k/cp2k.git
synced 2026-07-21 14:35:15 -04:00
130 lines
4.6 KiB
Python
130 lines
4.6 KiB
Python
#!/usr/bin/env python3
|
|
|
|
# author: Ole Schuett
|
|
|
|
import os
|
|
import logging
|
|
from os import path
|
|
from time import time
|
|
import tempfile
|
|
import subprocess
|
|
from subprocess import PIPE, STDOUT
|
|
from flask import Flask, request, abort
|
|
|
|
app = Flask(__name__)
|
|
app.config["MAX_CONTENT_LENGTH"] = 1024 * 1024 # 1MB
|
|
app.logger.setLevel(logging.INFO)
|
|
app.logger.info("CP2K Precommit Server is up and running :-)")
|
|
|
|
|
|
# ======================================================================================
|
|
@app.route("/")
|
|
def hello():
|
|
return "cp2k precommit server revision: " + os.environ["REVISION"]
|
|
|
|
|
|
# ======================================================================================
|
|
@app.route("/black", methods=["POST"])
|
|
def black():
|
|
return run_tool(["black"])
|
|
|
|
|
|
# ======================================================================================
|
|
@app.route("/spackformat", methods=["POST"])
|
|
def spackformat():
|
|
# Run black like https://github.com/spack/spack/blob/develop/pyproject.toml
|
|
return run_tool(["black", "--line-length=99", "--skip-magic-trailing-comma"])
|
|
|
|
|
|
# ======================================================================================
|
|
@app.route("/shfmt", methods=["POST"])
|
|
def shfmt():
|
|
return run_tool(["shfmt", "-i=2", "-ci", "-sr", "-w"])
|
|
|
|
|
|
# ======================================================================================
|
|
@app.route("/shellcheck", methods=["POST"])
|
|
def shellcheck():
|
|
return run_tool(["shellcheck"], timeout=30)
|
|
|
|
|
|
# ======================================================================================
|
|
@app.route("/mdformat", methods=["POST"])
|
|
@app.route("/markdownlint", methods=["POST"]) # for backwards compatibility
|
|
def mdformat():
|
|
return run_tool(["mdformat", "--wrap=100"])
|
|
|
|
|
|
# ======================================================================================
|
|
@app.route("/clangformat", methods=["POST"])
|
|
def clangformat():
|
|
return run_tool(["clang_format_wrapper.sh"])
|
|
|
|
|
|
# ======================================================================================
|
|
@app.route("/cmakeformat", methods=["POST"])
|
|
def cmakeformat():
|
|
return run_tool(["cmake-format", "-i"], timeout=30)
|
|
|
|
|
|
# ======================================================================================
|
|
@app.route("/cmakelint", methods=["POST"])
|
|
def cmakelint():
|
|
# Note: the config path must be passed as a single "--flag=value" token.
|
|
# cmake-lint's "-c"/"--config-files" option is nargs="+", so passing it as
|
|
# two separate argv tokens ("-c", path) would greedily swallow the target
|
|
# filename that run_tool() appends as another config file, and silently
|
|
# scan zero files instead.
|
|
config = f"--config-files={os.getcwd()}/cmake-lint.yaml"
|
|
return run_tool(["cmake-lint", config], timeout=30)
|
|
|
|
|
|
# ======================================================================================
|
|
@app.route("/fortitude", methods=["POST"])
|
|
def fortitude():
|
|
config = f"--config-file={os.getcwd()}/fortitude.toml"
|
|
return run_tool(["fortitude", config, "check", "--fix", "--unsafe-fixes"])
|
|
|
|
|
|
# ======================================================================================
|
|
@app.route("/fortitude_nofix", methods=["POST"])
|
|
def fortitude_nofix():
|
|
config = f"--config-file={os.getcwd()}/fortitude.toml"
|
|
return run_tool(["fortitude", config, "check"])
|
|
|
|
|
|
# ======================================================================================
|
|
def run_tool(cmd, timeout=3):
|
|
assert len(request.files) == 1
|
|
orig_fn = list(request.files.keys())[0]
|
|
data_before = request.files[orig_fn].read()
|
|
data_kb = len(data_before) / 1024.0
|
|
fn = path.basename(orig_fn)
|
|
workdir = tempfile.TemporaryDirectory()
|
|
abs_fn = path.join(workdir.name, fn)
|
|
open(abs_fn, "wb").write(data_before)
|
|
|
|
t1 = time()
|
|
try:
|
|
p = subprocess.run(
|
|
cmd + [fn], cwd=workdir.name, timeout=timeout, stdout=PIPE, stderr=STDOUT
|
|
)
|
|
except subprocess.TimeoutExpired:
|
|
# Note that GCP Cloud Run returns status 504 when its timeout is reached.
|
|
app.logger.info(f"Timeout of {cmd[0]} on {data_kb:.1f}KB after {timeout}s.")
|
|
return f"Timeout while running {cmd[0]} - please try again.", 408 # Req Timeout
|
|
t2 = time()
|
|
app.logger.info(f"Ran {cmd[0]} on {data_kb:.1f}KB in {t2-t1:.1f}s.")
|
|
if p.returncode != 0:
|
|
return p.stdout, 422 # Unprocessable Entity
|
|
data_after = open(abs_fn, "rb").read()
|
|
if data_after == data_before:
|
|
return "Not Modified", 304
|
|
return data_after, 200
|
|
|
|
|
|
# ======================================================================================
|
|
if __name__ == "__main__":
|
|
app.run()
|
|
|
|
# EOF
|