mirror of
https://github.com/minetest/contentdb.git
synced 2024-12-22 22:12:24 +01:00
Add support for New Tag update detection trigger
This commit is contained in:
parent
665bfd64d2
commit
09f8302e74
@ -24,7 +24,7 @@ from wtforms.ext.sqlalchemy.fields import QuerySelectField
|
|||||||
from wtforms.validators import *
|
from wtforms.validators import *
|
||||||
|
|
||||||
from app.rediscache import has_key, set_key, make_download_key
|
from app.rediscache import has_key, set_key, make_download_key
|
||||||
from app.tasks.importtasks import makeVCSRelease, checkZipRelease
|
from app.tasks.importtasks import makeVCSRelease, checkZipRelease, check_update_config
|
||||||
from app.utils import *
|
from app.utils import *
|
||||||
from . import bp
|
from . import bp
|
||||||
|
|
||||||
@ -278,6 +278,7 @@ def update_config(package):
|
|||||||
flash("Deleted update configuration", "success")
|
flash("Deleted update configuration", "success")
|
||||||
if package.update_config:
|
if package.update_config:
|
||||||
db.session.delete(package.update_config)
|
db.session.delete(package.update_config)
|
||||||
|
db.session.commit()
|
||||||
else:
|
else:
|
||||||
if package.update_config is None:
|
if package.update_config is None:
|
||||||
package.update_config = PackageUpdateConfig()
|
package.update_config = PackageUpdateConfig()
|
||||||
@ -287,7 +288,15 @@ def update_config(package):
|
|||||||
package.update_config.ref = nonEmptyOrNone(form.ref.data)
|
package.update_config.ref = nonEmptyOrNone(form.ref.data)
|
||||||
package.update_config.make_release = form.action.data == "make_release"
|
package.update_config.make_release = form.action.data == "make_release"
|
||||||
|
|
||||||
db.session.commit()
|
if package.update_config.last_commit is None:
|
||||||
|
last_release = package.releases.first()
|
||||||
|
if last_release and last_release.commit_hash:
|
||||||
|
package.update_config.last_commit = last_release.commit_hash
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
if package.update_config.last_commit is None:
|
||||||
|
check_update_config.delay(package.id)
|
||||||
|
|
||||||
if not form.disable.data and package.releases.count() == 0:
|
if not form.disable.data and package.releases.count() == 0:
|
||||||
flash("Now, please create an initial release", "success")
|
flash("Now, please create an initial release", "success")
|
||||||
|
@ -75,7 +75,7 @@ def view_editor():
|
|||||||
|
|
||||||
outdated_packages = Package.query \
|
outdated_packages = Package.query \
|
||||||
.filter(Package.state == PackageState.APPROVED,
|
.filter(Package.state == PackageState.APPROVED,
|
||||||
Package.update_config.has(outdated=True)).count()
|
Package.update_config.has(PackageUpdateConfig.outdated_at.isnot(None))).count()
|
||||||
|
|
||||||
return render_template("todo/editor.html", current_tab="editor",
|
return render_template("todo/editor.html", current_tab="editor",
|
||||||
packages=packages, wip_packages=wip_packages, releases=releases, screenshots=screenshots,
|
packages=packages, wip_packages=wip_packages, releases=releases, screenshots=screenshots,
|
||||||
@ -165,7 +165,7 @@ def view_user(username=None):
|
|||||||
|
|
||||||
outdated_packages = user.maintained_packages \
|
outdated_packages = user.maintained_packages \
|
||||||
.filter(Package.state != PackageState.DELETED,
|
.filter(Package.state != PackageState.DELETED,
|
||||||
Package.update_config.has(outdated=True)) \
|
Package.update_config.has(PackageUpdateConfig.outdated_at.isnot(None))) \
|
||||||
.order_by(db.asc(Package.title)).all()
|
.order_by(db.asc(Package.title)).all()
|
||||||
|
|
||||||
topics_to_add = ForumTopic.query \
|
topics_to_add = ForumTopic.query \
|
||||||
@ -184,6 +184,7 @@ def view_user(username=None):
|
|||||||
def outdated():
|
def outdated():
|
||||||
outdated_packages = Package.query \
|
outdated_packages = Package.query \
|
||||||
.filter(Package.state == PackageState.APPROVED,
|
.filter(Package.state == PackageState.APPROVED,
|
||||||
Package.update_config.has(outdated=True)).all()
|
Package.update_config.has(PackageUpdateConfig.outdated_at.isnot(None)))\
|
||||||
|
.order_by(db.desc(PackageUpdateConfig.outdated_at)).all()
|
||||||
|
|
||||||
return render_template("todo/outdated.html", current_tab="outdated", outdated_packages=outdated_packages)
|
return render_template("todo/outdated.html", current_tab="outdated", outdated_packages=outdated_packages)
|
||||||
|
@ -861,7 +861,7 @@ class PackageRelease(db.Model):
|
|||||||
self.approved = True
|
self.approved = True
|
||||||
|
|
||||||
if self.package.update_config:
|
if self.package.update_config:
|
||||||
self.package.update_config.outdated = False
|
self.package.update_config.outdated_at = None
|
||||||
self.package.update_config.last_commit = self.commit_hash
|
self.package.update_config.last_commit = self.commit_hash
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@ -955,11 +955,15 @@ class PackageUpdateConfig(db.Model):
|
|||||||
package = db.relationship("Package", back_populates="update_config", foreign_keys=[package_id])
|
package = db.relationship("Package", back_populates="update_config", foreign_keys=[package_id])
|
||||||
|
|
||||||
last_commit = db.Column(db.String(41), nullable=True, default=None)
|
last_commit = db.Column(db.String(41), nullable=True, default=None)
|
||||||
|
last_tag = db.Column(db.String(41), nullable=True, default=None)
|
||||||
|
|
||||||
# Set to true when an outdated notification is sent. Set to false when a release is created
|
# Set to now when an outdated notification is sent. Set to None when a release is created
|
||||||
outdated = db.Column(db.Boolean, nullable=False, default=False)
|
outdated_at = db.Column(db.DateTime, nullable=True, default=None)
|
||||||
|
|
||||||
trigger = db.Column(db.Enum(PackageUpdateTrigger), nullable=False, default=PackageUpdateTrigger.COMMIT)
|
trigger = db.Column(db.Enum(PackageUpdateTrigger), nullable=False, default=PackageUpdateTrigger.COMMIT)
|
||||||
ref = db.Column(db.String(41), nullable=True, default=None)
|
ref = db.Column(db.String(41), nullable=True, default=None)
|
||||||
|
|
||||||
make_release = db.Column(db.Boolean, nullable=False, default=False)
|
make_release = db.Column(db.Boolean, nullable=False, default=False)
|
||||||
|
|
||||||
|
def set_outdated(self):
|
||||||
|
self.outdated_at = datetime.datetime.utcnow()
|
||||||
|
@ -106,6 +106,24 @@ def get_commit_hash(git_url, ref_name=None):
|
|||||||
return remote_refs.get(ref_name)
|
return remote_refs.get(ref_name)
|
||||||
|
|
||||||
|
|
||||||
|
def get_latest_tag(git_url):
|
||||||
|
with get_temp_dir() as git_dir:
|
||||||
|
repo = git.Repo.init(git_dir)
|
||||||
|
origin = repo.create_remote("origin", url=git_url)
|
||||||
|
origin.fetch()
|
||||||
|
|
||||||
|
refs = repo.git.ls_remote(tags=True, sort="creatordate").split('\n')
|
||||||
|
if len(refs) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
last_ref = refs[-1]
|
||||||
|
hash_ref_list = last_ref.split('\t')
|
||||||
|
|
||||||
|
tag = hash_ref_list[1].replace("refs/tags/", "")
|
||||||
|
commit_hash = repo.git.rev_parse(tag + "^{}")
|
||||||
|
return tag, commit_hash
|
||||||
|
|
||||||
|
|
||||||
@celery.task()
|
@celery.task()
|
||||||
def getMeta(urlstr, author):
|
def getMeta(urlstr, author):
|
||||||
with clone_repo(urlstr, recursive=True) as repo:
|
with clone_repo(urlstr, recursive=True) as repo:
|
||||||
@ -297,6 +315,67 @@ def importForeignDownloads(self, id):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def check_update_config_impl(package):
|
||||||
|
config = package.update_config
|
||||||
|
|
||||||
|
if config.trigger == PackageUpdateTrigger.COMMIT:
|
||||||
|
tag = None
|
||||||
|
commit = get_commit_hash(package.repo, package.update_config.ref)
|
||||||
|
elif config.trigger == PackageUpdateTrigger.TAG:
|
||||||
|
tag, commit = get_latest_tag(package.repo)
|
||||||
|
else:
|
||||||
|
raise TaskError("Unknown update trigger")
|
||||||
|
|
||||||
|
if config.last_commit == commit:
|
||||||
|
if tag and config.last_tag != tag:
|
||||||
|
config.last_tag = tag
|
||||||
|
db.session.commit()
|
||||||
|
return
|
||||||
|
|
||||||
|
if not config.last_commit:
|
||||||
|
config.last_commit = commit
|
||||||
|
config.last_tag = tag
|
||||||
|
db.session.commit()
|
||||||
|
return
|
||||||
|
|
||||||
|
if config.make_release:
|
||||||
|
rel = PackageRelease()
|
||||||
|
rel.package = package
|
||||||
|
rel.title = tag if tag else commit[0:5]
|
||||||
|
rel.url = ""
|
||||||
|
rel.task_id = uuid()
|
||||||
|
db.session.add(rel)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
makeVCSRelease.apply_async((rel.id, commit), task_id=rel.task_id)
|
||||||
|
|
||||||
|
elif config.outdated_at is None:
|
||||||
|
config.set_outdated()
|
||||||
|
|
||||||
|
if config.trigger == PackageUpdateTrigger.COMMIT:
|
||||||
|
msg_last = ""
|
||||||
|
if config.last_commit:
|
||||||
|
msg_last = " The last commit was {}".format(config.last_commit[0:5])
|
||||||
|
|
||||||
|
msg = "New commit {} found on the Git repo, is the package outdated?{}" \
|
||||||
|
.format(commit[0:5], msg_last)
|
||||||
|
else:
|
||||||
|
msg_last = ""
|
||||||
|
if config.last_tag:
|
||||||
|
msg_last = " The last tag was {}".format(config.last_tag)
|
||||||
|
|
||||||
|
msg = "New tag {} found on the Git repo.{}" \
|
||||||
|
.format(tag, msg_last)
|
||||||
|
|
||||||
|
for user in package.maintainers:
|
||||||
|
addSystemNotification(user, NotificationType.BOT,
|
||||||
|
msg, url_for("todo.view_user", username=user.username, _external=False), package)
|
||||||
|
|
||||||
|
config.last_commit = commit
|
||||||
|
config.last_tag = tag
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
@celery.task(bind=True)
|
@celery.task(bind=True)
|
||||||
def check_update_config(self, package_id):
|
def check_update_config(self, package_id):
|
||||||
package: Package = Package.query.get(package_id)
|
package: Package = Package.query.get(package_id)
|
||||||
@ -305,14 +384,9 @@ def check_update_config(self, package_id):
|
|||||||
elif package.update_config is None:
|
elif package.update_config is None:
|
||||||
raise TaskError("No update config attached to package")
|
raise TaskError("No update config attached to package")
|
||||||
|
|
||||||
config = package.update_config
|
|
||||||
|
|
||||||
if config.trigger != PackageUpdateTrigger.COMMIT:
|
|
||||||
return
|
|
||||||
|
|
||||||
err = None
|
err = None
|
||||||
try:
|
try:
|
||||||
hash = get_commit_hash(package.repo, package.update_config.ref)
|
check_update_config_impl(package)
|
||||||
except IndexError as e:
|
except IndexError as e:
|
||||||
err = "Unable to find the reference.\n" + str(e)
|
err = "Unable to find the reference.\n" + str(e)
|
||||||
except GitCommandError as e:
|
except GitCommandError as e:
|
||||||
@ -320,6 +394,8 @@ def check_update_config(self, package_id):
|
|||||||
err = e.stderr
|
err = e.stderr
|
||||||
except gitdb.exc.BadName as e:
|
except gitdb.exc.BadName as e:
|
||||||
err = "Unable to find the reference " + (package.update_config.ref or "?") + "\n" + e.stderr
|
err = "Unable to find the reference " + (package.update_config.ref or "?") + "\n" + e.stderr
|
||||||
|
except TaskError as e:
|
||||||
|
err = e.value
|
||||||
|
|
||||||
if err:
|
if err:
|
||||||
err = err.replace("stderr: ", "") \
|
err = err.replace("stderr: ", "") \
|
||||||
@ -327,49 +403,13 @@ def check_update_config(self, package_id):
|
|||||||
.strip()
|
.strip()
|
||||||
|
|
||||||
msg = "Error: {}.\n\nTask ID: {}\n\n[Change update configuration]({})" \
|
msg = "Error: {}.\n\nTask ID: {}\n\n[Change update configuration]({})" \
|
||||||
.format(err, self.request.id, package.getUpdateConfigURL())
|
.format(err, self.request.id, package.getUpdateConfigURL())
|
||||||
|
|
||||||
post_bot_message(package, "Failed to check git repository", msg)
|
post_bot_message(package, "Failed to check git repository", msg)
|
||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return
|
return
|
||||||
|
|
||||||
if config.last_commit == hash:
|
|
||||||
return
|
|
||||||
|
|
||||||
if not config.last_commit:
|
|
||||||
config.last_commit = hash
|
|
||||||
db.session.commit()
|
|
||||||
return
|
|
||||||
|
|
||||||
if config.make_release:
|
|
||||||
rel = PackageRelease()
|
|
||||||
rel.package = package
|
|
||||||
rel.title = hash[0:5]
|
|
||||||
rel.url = ""
|
|
||||||
rel.task_id = uuid()
|
|
||||||
db.session.add(rel)
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
makeVCSRelease.apply_async((rel.id, package.update_config.ref), task_id=rel.task_id)
|
|
||||||
|
|
||||||
elif not config.outdated:
|
|
||||||
config.outdated = True
|
|
||||||
|
|
||||||
msg_last = ""
|
|
||||||
if config.last_commit:
|
|
||||||
msg_last = " The last commit was {}".format(config.last_commit[0:5])
|
|
||||||
|
|
||||||
msg = "New commit {} found on the Git repo, is the package outdated?{}" \
|
|
||||||
.format(hash[0:5], msg_last)
|
|
||||||
|
|
||||||
for user in package.maintainers:
|
|
||||||
addSystemNotification(user, NotificationType.BOT,
|
|
||||||
msg, url_for("todo.view_user", username=user.username), package)
|
|
||||||
|
|
||||||
config.last_commit = hash
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
|
|
||||||
@celery.task
|
@celery.task
|
||||||
def check_for_updates():
|
def check_for_updates():
|
||||||
|
@ -17,7 +17,11 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
{{ _("Git repo has commit %(ref)s", ref=package.update_config.last_commit[0:5]) }}
|
{% if package.update_config.trigger == package.update_config.trigger.TAG and package.update_config.last_tag %}
|
||||||
|
{{ _("New tag: %(tag)s", tag=package.update_config.last_tag) }}
|
||||||
|
{% else %}
|
||||||
|
{{ _("Git repo has commit %(ref)s", ref=package.update_config.last_commit[0:5]) }}
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-sm-auto">
|
<div class="col-sm-auto">
|
||||||
|
@ -10,7 +10,12 @@
|
|||||||
{% if package.update_config %}
|
{% if package.update_config %}
|
||||||
<p class="alert alert-secondary mb-4">
|
<p class="alert alert-secondary mb-4">
|
||||||
<a class="float-right btn btn-sm btn-secondary" href="{{ package.getUpdateConfigURL() }}">{{ _("Settings") }}</a>
|
<a class="float-right btn btn-sm btn-secondary" href="{{ package.getUpdateConfigURL() }}">{{ _("Settings") }}</a>
|
||||||
{{ _("You have automatic releases enabled") }}
|
{% if package.update_config.make_release %}
|
||||||
|
{{ _("You have automatic releases enabled.") }}
|
||||||
|
{% else %}
|
||||||
|
{{ _("You have Git update notifications enabled.") }}
|
||||||
|
{{ _("You can enable automatic updates in the update detection settings.") }}
|
||||||
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p class="alert alert-info mb-4">
|
<p class="alert alert-info mb-4">
|
||||||
|
@ -31,19 +31,18 @@
|
|||||||
|
|
||||||
{{ render_field(form.trigger, class_="mt-5") }}
|
{{ render_field(form.trigger, class_="mt-5") }}
|
||||||
|
|
||||||
<p class="text-warning mb-4">
|
{{ render_field(form.ref, placeholder="Leave blank to use default branch",
|
||||||
<small>
|
pattern="[A-Za-z0-9/._-]+") }}
|
||||||
<span class="fas fa-exclamation-triangle mr-2"></span>
|
|
||||||
|
|
||||||
{{ _("The new tag trigger isn't supported yet.") }}
|
<p class="text-muted mb-4 mt-0">
|
||||||
{{ _("If you choose it, it won't trigger until it is supported.") }}
|
<small>
|
||||||
{{ _("In the meantime, you can use webhooks to create releases on tag events.") }}
|
<span class="fas fa-info mx-1"></span>
|
||||||
|
|
||||||
|
{{ _("Currently, the branch name field is only used by the New Commit trigger.") }}
|
||||||
</small>
|
</small>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
{{ render_field(form.ref, placeholder="Leave blank to use default branch",
|
|
||||||
pattern="[A-Za-z0-9/._-]+") }}
|
|
||||||
{{ render_field(form.action) }}
|
{{ render_field(form.action) }}
|
||||||
|
|
||||||
<p class="mt-5">
|
<p class="mt-5">
|
||||||
|
32
migrations/versions/a337bcc165c0_.py
Normal file
32
migrations/versions/a337bcc165c0_.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: a337bcc165c0
|
||||||
|
Revises: f565dde93553
|
||||||
|
Create Date: 2021-01-29 21:30:37.277197
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import postgresql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'a337bcc165c0'
|
||||||
|
down_revision = 'f565dde93553'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('package_update_config', sa.Column('outdated_at', sa.DateTime(), nullable=True))
|
||||||
|
op.add_column('package_update_config', sa.Column('last_tag', sa.String(length=41), nullable=True))
|
||||||
|
op.drop_column('package_update_config', 'outdated')
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('package_update_config', sa.Column('outdated', sa.BOOLEAN(), server_default=sa.text('false'), autoincrement=False, nullable=False))
|
||||||
|
op.drop_column('package_update_config', 'outdated_at')
|
||||||
|
op.drop_column('package_update_config', 'last_tag')
|
||||||
|
# ### end Alembic commands ###
|
Loading…
Reference in New Issue
Block a user