Skip to content

Instantly share code, notes, and snippets.

@foosel
Last active March 28, 2019 10:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save foosel/ed46769d86dffeb41774302fc0610f57 to your computer and use it in GitHub Desktop.
Save foosel/ed46769d86dffeb41774302fc0610f57 to your computer and use it in GitHub Desktop.
OctoPrint devtool fabfile
from __future__ import print_function, unicode_literals, absolute_import
from fabric.api import local, run, sudo, cd, prompt
from fabric.utils import abort
from fabric.state import env
from fabric.contrib import files
import datetime
import calendar
import sys
import os
import codecs
def env_from_yaml(path):
import yaml
with codecs.open(path, errors="replace") as f:
data = yaml.safe_load(f)
if not isinstance(data, dict):
abort("YAML file at {} doesn't contain a dictionary, can't use that for setting env")
for key, value in data.items():
setattr(env, key, value)
env_from_yaml("./fabfile.yaml")
env.disable_known_hosts = True
env.no_keys = True
##~~ Patreon ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def sticker_list(export, output=None):
now = datetime.date.today()
month = now.month - 1
year = now.year
if month == 0:
month = 12
year -= 1
if output is None:
output = "stickers-{:04d}{:02d}.csv".format(year, month)
_, last_day = calendar.monthrange(year, month)
command = " ".join(["python patronexport.py",
"-i {export}",
"-t sticker-recipients.csv",
"-r 20",
"-r 19.10",
"-r 10",
"-r 9.35",
"--until {year:04d}-{month:02d}-{last_day:02d}",
"-m patron-mapping.yaml",
"-a patron-additional.yaml",
"-o {output}"])
local(command.format(**locals()))
def supporter_list(export, output=None):
if output is None:
output = "../SUPPORTERS.md"
command = " ".join(["python patronexport.py",
"-i {export}",
"-t sponsors-template.md",
"-r 20",
"-r 19.10",
"-m patron-mapping.yaml",
"-a patron-additional.yaml",
"-o {output}"])
local(command.format(**locals()))
##~~ Issues ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def issue_list_export(output=None):
token = env.github_token
if output is None:
output = "issues.yaml"
command = " ".join(["python issuelist.py",
"--token {token}",
"--user foosel",
"--repo OctoPrint",
"--output {output}"])
local(command.format(**locals()))
def issue_list_process(template=None, input=None, output=None):
if template is None:
template = "issues-template.csv"
if input is None:
input = "issues.yaml"
if output is None:
now = datetime.date.today()
output = "issues-{year:04d}{month:02d}{day:02d}.csv".format(year=now.year, month=now.month, day=now.day)
command = " ".join(["python issuelist.py",
"--input {input}",
"--template {template}",
"--output {output}"])
local(command.format(**locals()))
def issue_list():
issue_list_export()
issue_list_process()
##~~ Release testing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def sync_test_repo(force=False):
for branch in ("master", "maintenance", "staging/maintenance", "rc/maintenance", "devel", "rc/devel"):
local("git checkout {}".format(branch))
if force:
local("git push --force releasetest {}".format(branch))
else:
local("git push releasetest {}".format(branch))
def test_rc_devel(tag):
tag_push_test_repo("rc/devel", tag)
def test_rc_maintenance(tag):
tag_push_test_repo("rc/maintenance", tag)
def test_stable(tag):
test_rc_maintenance(tag)
merge_push_test_repo("master", "rc/maintenance")
merge_push_test_repo("rc/devel", "rc/maintenance")
def tag_push_test_repo(push_branch, tag):
local("git checkout {}".format(push_branch))
local("git push releasetest {}".format(push_branch))
local("git tag {}".format(tag))
local("git push --tags releasetest {}".format(tag))
local("git tag -d {}".format(tag))
def merge_tag_push_test_repo(push_branch, merge_branch, tag):
local("git checkout {}".format(push_branch))
local("git merge {}".format(merge_branch))
local("git push releasetest {}".format(push_branch))
local("git tag {}".format(tag))
local("git push --tags releasetest {}".format(tag))
local("git tag -d {}".format(tag))
def merge_push_test_repo(push_branch, merge_branch):
local("git checkout {}".format(push_branch))
local("git merge {}".format(merge_branch))
local("git push releasetest {}".format(push_branch))
def test_prerelease_patch(tag, branch=b"rc/maintenance"):
test_patch(tag, branch, True)
def test_release_patch(tag, branch=b"rc/maintenance"):
test_patch(tag, branch, False)
def test_patch(tag, branch, prerelease):
now = datetime.datetime.utcnow().replace(microsecond=0).isoformat(b' ')
tag_name = b"{} (release candidate)" if prerelease else b"{} (stable)"
tag_name = tag_name.format(tag)
release = dict(draft=False,
html_url=b"https://github.com/foosel/OctoPrint/releases/tag/{}".format(tag),
name=tag_name,
prerelease=prerelease,
published_at=now,
tag_name=tag,
target_commitish=branch)
import json
commands = ['["set", "plugins.github_release_patcher.releases.foosel/OctoPrint", [{}]]'.format(json.dumps(release)),
'["set", "plugins.softwareupdate.checks.octoprint.pip", "{}/archive/{{target_version}}.zip"]'.format(env.releasetest_repo)]
print("Paste this into the YAML Patcher:")
print("--- 8< ---")
print("[{}]".format(", ".join(commands)))
print("--- 8< ---")
##~~ OctoPi ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def octopi_networkconfig(mountpoint, ssid=None, psk=None):
if ssid is None:
ssid = env.wifi_ssid
if psk is None:
psk = env.wifi_psk
if sys.platform == "win32":
mountpoint += ":"
path_old = os.path.join(mountpoint, "octopi-network.txt")
if not os.path.exists(path_old):
abort("{} does not exist, {} doesn't look like an OctoPi /boot mountpoint".format(path_old, mountpoint))
path_new = os.path.join(mountpoint, "octopi-wpa-supplicant.txt")
config_old = """
iface wlan0-octopi inet manual
wpa-ssid "{ssid}"
wpa-psk "{psk}"
"""
config_new = """
network={{
ssid="{ssid}"
psk="{psk}"
}}
country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
"""
import codecs
with codecs.open(path_old, errors="replace", mode="w") as f:
f.write(config_old.format(ssid=ssid, psk=psk))
print("Wrote old network config to {}".format(path_old))
with codecs.open(path_new, errors="replace", mode="w") as f:
f.write(config_new.format(ssid=ssid, psk=psk))
print("Wrote new network config to {}".format(path_new))
def octopi_hostname(mountpoint, name):
if sys.platform == "win32":
mountpoint += ":"
path = os.path.join(mountpoint, "octopi-hostname.txt")
import codecs
with codecs.open(path, errors="replace", mode="w") as f:
f.write(name)
print("Wrote hostname config to {}".format(path))
def octopi_config(mountpoint, ssid=None, psk=None, name=None):
octopi_networkconfig(mountpoint, ssid=ssid, psk=psk)
if name is not None:
octopi_hostname(mountpoint, name)
def octopi_octoservice(command):
sudo("service octoprint {}".format(command))
def octopi_standardrepo():
run("cd ~/OctoPrint && git remote set-url origin https://github.com/foosel/OctoPrint")
def octopi_releasetestrepo():
run("cd ~/OctoPrint && git remote set-url origin {}".format(env.releasetest_repo))
def octopi_releasetestplugin_yaml_patcher():
octopi_install("https://github.com/OctoPrint/OctoPrint-Yamlpatcher/archive/master.zip")
def octopi_releasetestplugin_github_release_patcher():
run("cd ~/.octoprint/plugins && wget -Ogithub_release_patcher.py https://gist.githubusercontent.com/foosel/1e6e9c97acb7c2f36d4510ba69097c4d/raw/32e251e407336b1cd81a9d3942e739f354b2e037/github_release_patcher.py")
def octopi_releasetestplugins():
octopi_releasetestplugin_yaml_patcher()
octopi_releasetestplugin_github_release_patcher()
def octopi_checkout(branch, committish=None):
if not files.exists("~/OctoPrint/.git"):
abort("No git checkout available")
with cd("~/OctoPrint"):
run("git fetch")
run("git checkout {}".format(branch))
run("git pull")
if committish is not None:
run("git reset --hard {}".format(committish))
run("~/oprint/bin/python setup.py clean && ~/oprint/bin/python setup.py install")
octopi_octoservice("restart")
def octopi_install(url):
run("~/oprint/bin/pip install {}".format(url))
def octopi_tailoctolog():
run("tail -f ~/.octoprint/logs/octoprint.log")
def octopi_test_simplecheckout(branch):
octopi_releasetestrepo()
octopi_checkout(branch)
def octopi_test_simplepip(tag):
url = "{}/archive/{}.zip".format(env.release_test_repo, tag)
octopi_install(url)
def octopi_test_update(tag, branch, prerelease):
prompt("Make sure you've done first time setup and updated to desired start version, then continue")
if files.exists("~/OctoPrint/.git"):
octopi_releasetestrepo()
octopi_releasetestplugins()
octopi_octoservice("restart")
# patch
test_patch(tag, branch, prerelease)
prompt("Enter above patch in YamlPatcher, then continue")
octopi_octoservice("restart")
octopi_tailoctolog()
def octopi_test_update_devel(tag, branch="rc/devel", prerelease=True):
octopi_test_update(tag, branch, prerelease)
def octopi_test_update_maintenance(tag, branch="rc/maintenance", prerelease=True):
octopi_test_update(tag, branch, prerelease)
def octopi_test_update_stable(tag, branch="master", prerelease=False):
octopi_test_update(tag, branch, prerelease)
#hosts:
# - pi@octopi.local
password: raspberry
releasetest_repo: https://...
patch_pip_url: false
wifi_ssid: MySSID
wifi_psk: MyPassword
github_token: my_token
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment