Django实现自动发布(2视图-任务接收)

Posted wbjxxzx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django实现自动发布(2视图-任务接收)相关的知识,希望对你有一定的参考价值。

上一篇服务版本的新增,是通过触发 gitlab 任务来实现的,那么如何得到任务的最终状态呢?
好在 gitlab 为我们提供了webhook,也就是消息钩子,可以发送pipeline消息到我们指定的地址。
当我们收到消息后,就可以跟据任务的最终状态(成功or失败)来更新数据库里相应的版本:

  • 失败时直接更新任务状态为失败
  • 成功时除了更新状态,还要记录版本的路径

版本的存储路径

gitlab 的pipeline任务有一个递增的ID号,我们可以直接拿过来使用,以此ID为版本目录,打包好的服务就存放在该目录下,具体的存储结构如下图:

技术图片

然后是接收任务的视图

接收任务

这里放上 pipeline消息的关键内容:

'object_attributes': {
   'before_sha': '0000000000000000000000000000000000000000',
   'created_at': '2019-12-09 08:53:34 UTC',
   'detailed_status': 'passed', # pending running passed failed
   'duration': 69,
   'finished_at': '2019-12-09 08:54:56 UTC',
   'id': 123,
   'ref': 'master',
   'sha': 'ad02bfded9fed8a1ae478bc088378827c485cf94',
   'stages': ['prepare', 'build', 'deploy'],
   'status': 'success', # pending running success failed
   'tag': False,
   'variables': [
                 {'key': 'VERSION_ID', 'value': '3'},
                 {'key': 'SERVICE_ID', 'value': '2'},
                 {'key': 'SERVICE_NAME', 'value': 'A'},
                 {'key': 'USERNAME', 'value': 'zhangsan'}
               ],
    },

object_attributes 这个字典里的信息就是我们需要的:

  • status 任务的最终状态,有 success、pending、running、canceled 等
  • variables 触发任务时发送的变量

那么接收任务的视图:

import json
from microservice.models import MicroServiceVersion, BuildStatus
from django.http import HttpResponse
from django.views import generic

class GitWebhookReceiver(generic.View):
    def post(self, request):
        data = json.loads(request.body)
        object_attributes = data.get('object_attributes', {})
        task_id = object_attributes.get('id')
        return self._git_build_result(task_id, object_attributes)

    def _git_build_result(self, task_id, object_attributes):
        status = object_attributes.get('status', '')
        if status in ('pending', 'running', 'canceled'):
            return HttpResponse('')

        elif status in ('failed', 'success'):
            version_id = ''
            service_name = ''
            for item in object_attributes.get('variables', []):
                if item.get('key') == 'VERSION_ID':
                    version_id = item.get('value')
                if item.get('key') == 'SERVICE_NAME':
                    service_name = item.get('value')

            if status in ('failed', ):
                if version_id:
                    MicroServiceVersion.objects.filter(pk=version_id).update(status=BuildStatus.failed.value)
            else: # status == 'success' and detailed_status == 'passed':
                if version_id:
                    MicroServiceVersion.objects.filter(pk=version_id).update(
                        status=BuildStatus.success.value,
                        file_path='{}/{}'.format(service_name, task_id)
                    )
        return HttpResponse('')

这里做一下重构,将接收任务和服务管理的视图分开,在microservice下新建包 views,重命名之前的 views.py -> srv_manage.py 并移动到 views 下,新增的任务接收代码存放到 webhook_receive.py ,最后microservice 的目录结构:

├── admin.py
├── apps.py
├── __init__.py
├── models.py
├── tests.py
├── urls.py
└── views
    ├── __init__.py
    ├── srv_manage.py
    └── webhook_receive.py

当然,这里只是一个实现思路,我们在用的环境是pipeline完成后上传到软件仓库,django结合celery发起异步任务去获取版本号,之后的发布操作也是经由celery。 而且在实际使用中,经常会碰到gitlab的webhook发送超时的情况,我们又在发起任务后通过轮询的方式获取任务状态,这些都是后话。

这样就有了服务相关的版本,之后就是部署、升级、回退,相关的代码在 这里

以上是关于Django实现自动发布(2视图-任务接收)的主要内容,如果未能解决你的问题,请参考以下文章

Django 模板未接收上下文对象

Django基于PythonWeb的Django框架设计实现天天生鲜系统-4创建视图

从视图访问消费者以通过 WebSocket (Django-Channelsv2.2 & DRF) 将 api 接收的数据推送给用户

django —— Celery实现异步和定时任务

Django Celery 接收和接受任务,但不执行它们

JAVA多线程基础