Skip to content
Snippets Groups Projects
Commit 79d72c6f authored by Kostas Vilkelis's avatar Kostas Vilkelis :flamingo:
Browse files

more cleaning

parent e43aaf14
No related branches found
No related tags found
No related merge requests found
71d17c7f9d876d48567b31cc350694db2eeb2cc8
\ No newline at end of file
../codes/
\ No newline at end of file
../data
\ No newline at end of file
Put your publication latex here
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import shutil
from pathlib import Path
from getpass import getpass
from tempfile import mkdtemp
from contextlib import contextmanager
from git import Repo
import gitlab
from gitlab import Gitlab, GitlabGetError
# Configuration variables
GITLAB = "https://gitlab.kwant-project.org"
API_VERSION = 4
# API token for use in CI is stored in a snippet that is
# only accessible to the appropriate users.
CI_API_TOKEN_SNIPPET = ("qt/skeleton", "gitlab-api-token")
CI_API_TOKEN_VARIABLE = "GITLAB_API_TOKEN"
PARENT_GROUP = "qt"
MARKER_FILE = ".qt-research-project"
TEMPLATE_DIR = ".templates"
BRANCH_PROTECTION_LEVEL = gitlab.const.DEVELOPER_ACCESS
PRE_COMMIT_HOOK_TARGET = ".git/hooks/pre-commit"
PRE_COMMIT_HOOK_SOURCE = ".hooks/pre-commit"
FILTERS = {
'diff "notebook"': {
"command": (
"git-nbdiffdriver diff "
"--ignore-details "
"--ignore-outputs "
"--ignore-metadata"
)
},
'merge "notebook"': {
"driver": "git-nbmergedriver merge %O %A %B %L %P",
"name": "jupyter notebook merge driver",
},
'filter "whitespace"': {
"clean": r'sed -e "s/\\s\\+$//"',
},
}
@contextmanager
def status(message):
print(message, "...", sep="", end="", flush=True)
try:
yield
except Exception:
print("failed")
raise
except:
print("aborting")
raise
else:
print("done")
def is_new_project():
return not os.path.isfile(MARKER_FILE)
def project_name():
return Path(".").absolute().name
def project_data_name():
return project_name() + "-data"
def create_gitlab_project(client, name, tags):
full_name = "/".join((PARENT_GROUP, name))
group = client.groups.get(PARENT_GROUP)
with status("creating project {} on {}".format(full_name, GITLAB)):
project = client.projects.create(
dict(name=name, namespace_id=group.id, visibility="private", tag_list=tags)
)
return project
def get_snippet(client, project_name, snippet_name):
try:
project = client.projects.get(project_name)
snippets = project.snippets.list(as_list=False)
return next(s for s in snippets if s.title == snippet_name)
except GitlabGetError:
raise KeyError("project {} does not exist".format(project_name))
except StopIteration:
raise KeyError("{} has no snippet named {}".format(project_name, snippet_name))
def init_project(api_token):
assert is_new_project()
with status("logging in to {}".format(GITLAB)):
gl = Gitlab(GITLAB, api_token, api_version=API_VERSION)
gl.auth()
gitlab_repo = create_gitlab_project(gl, project_name(), tags=["research"])
gitlab_data_repo = create_gitlab_project(
gl, project_data_name(), tags=["research", "data"]
)
try:
with status("setting API access token for CI"):
token = get_snippet(gl, *CI_API_TOKEN_SNIPPET).content()
gitlab_repo.variables.create(
dict(
key=CI_API_TOKEN_VARIABLE,
value=token.decode(),
)
)
except Exception:
print("CI jobs will not be able to access the Gitlab API")
data_dir = mkdtemp()
# Initialize data repository with empty commit and push to Gitlab
push_url = gitlab_data_repo.http_url_to_repo.replace(
"https://", f"https://oauth2:{api_token}@"
)
try:
with status("initializing data repository"):
data_repo = Repo.init(data_dir)
data_repo.index.commit("init")
data_repo.create_head("main")
data_repo.create_remote("origin", push_url)
with status("syncing data repository"):
data_repo.remotes.origin.push(refspec="main:main")
finally:
shutil.rmtree(data_dir, ignore_errors=True)
# Initialize project repository.
# Squash all commits from skeleton down into one and add the data
# repo as a submodule.
repo = Repo(".")
with status("linking data submodule"):
# Use the remote URL to create the data submodule (so we can remove
# the local data repo, then set the URL to a relative one so that
# CI etc. works.
sub = repo.create_submodule("data", "data", push_url)
sub.config_writer().set_value("url", "../" + project_data_name())
with status("initializing repository"):
# Write the skeleton "version: into the marker file
with open(MARKER_FILE, "w") as f:
f.write(repo.head.commit.hexsha)
repo.index.add([MARKER_FILE, ".gitmodules"])
# Remove main branch so that everything is squashed into one commit
repo.git.update_ref("-d", "refs/heads/main")
# Move the templates into the project
templates = os.listdir(TEMPLATE_DIR)
for file in templates:
shutil.copy(os.path.join(TEMPLATE_DIR, file), ".")
repo.index.remove([TEMPLATE_DIR], working_tree=True, r=True, f=True)
repo.index.add(templates)
repo.index.commit("init")
# Push repo
with status("syncing repository"):
repo.remotes.origin.set_url(
gitlab_repo.http_url_to_repo.replace(
"https://", f"https://oauth2:{api_token}@"
)
)
repo.remotes.origin.push(refspec="main:main")
return gitlab_repo, gitlab_data_repo
def setup_config():
repo = Repo(".")
with repo.config_writer() as cfg:
with status("setting up core config"):
cfg.set("core", "attributesfile", ".gitattrbutes")
with status("setting up filters"):
for section, filters in FILTERS.items():
for filter, driver in filters.items():
if section not in cfg.sections():
cfg.add_section(section)
cfg.set(section, filter, driver)
if os.path.exists(PRE_COMMIT_HOOK_TARGET):
print(
"pre-commit hook already exists: "
'if you want to reinstall "skeleton" version run:\n\t'
"rm {} && ./setup".format(PRE_COMMIT_HOOK_TARGET)
)
else:
shutil.copy(PRE_COMMIT_HOOK_SOURCE, PRE_COMMIT_HOOK_TARGET)
os.chmod(PRE_COMMIT_HOOK_TARGET, 0o775)
print("pre-commit hook have been installed")
with status("retrieving data submodule"):
repo.git.submodule("update", "--init", "--recursive")
def main():
if is_new_project():
print("configuring new project", project_name())
try:
api_token = os.getenv("GITLAB_API_TOKEN")
except KeyError:
api_token = getpass(
"enter a Gitlab personal access token "
"(generate here {}/profile/personal_access_tokens): ".format(GITLAB)
)
gitlab_repo, gitlab_data_repo = init_project(api_token)
setup_config()
print(10 * "-")
print("project:", gitlab_repo.web_url)
print("data:", gitlab_data_repo.web_url)
else:
setup_config()
if __name__ == "__main__":
main()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment