您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Auto Deploy for Van!
当前为
// ==UserScript== // @name Van Deploy // @namespace http://tampermonkey.net/ // @version 0.2 // @description Auto Deploy for Van! // @author Alexander // @match https://van.huolala.work/projects/835/* // @match https://van.huolala.work/projects/833/* // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // console.log(' van deploy is running ') let monitor const startTime = new Date().getTime() const sleep = (time = 1000) => new Promise(resolve => setTimeout(resolve, time)); class DeployTask { constructor(config) { this.id = config.id // building id this.branch = config.branch // branch this.startTime = new Date().getTime() // this.config = config this.status = 'pending' // pending, success, failed, deploying , deployed, undeployed this.intervalID = undefined this.deployInterval = undefined this.start() } getDom() { const taskDom = Array.from(document.getElementsByTagName('strong')).find(dom => dom.innerText === this.id) return taskDom ? taskDom.parentNode.parentNode : null } async start () { try { console.log('task ', this.id, ' start') this.status = 'pending' await this.query() await this.queueForDeply() console.log('task is deploying ', this.id) this.status = 'deploying' await this.deploy() this.stop() } catch (error) { console.log('deploy error ', error) this.stop() } } async query() { return new Promise((resolve, reject) => { this.intervalID = setInterval(() => { console.log(this.id, ' building status query ') const dom = this.getDom() if (!dom) { return } console.log('task is pending', this.id) const status = dom.getElementsByClassName('anticon')[0].className.split(' ') if (status.some(classItem => ['anticon-check-circle'].includes(classItem))) { clearInterval(this.intervalID) this.status = 'success' resolve() } if (status.some(classItem => ['anticon-close-circle'].includes(classItem))) { clearInterval(this.intervalID) this.status = 'failed' reject() } }, 1000) }) } async queueForDeply () { return new Promise((resolve, reject) => { console.log('queue for deploy ', this.id) this.deployInterval = setInterval(() => { if (monitor.canDeploy()) { clearInterval(this.deployInterval) resolve() } }, 500) }) } async deploy() { const dom = this.getDom() let deployed = false if (!dom) { return } dom.click() await sleep(3000) document.querySelector('.publish-btn-check button').click() await sleep(1000) Array.from(document.getElementsByClassName('fast-publish-btn-menu')[0].getElementsByClassName('ant-menu-item-group')).forEach(envDom => { const envName = envDom.getElementsByClassName('ant-menu-item-group-title')[0].innerText.toLocaleLowerCase().trim() if (this.branch.includes(envName) ) { deployed = true envDom.getElementsByClassName('ant-space-item')[0].click() } // env.getElementsByClassName('ant-space-item') }) if (deployed) { this.status = 'deployed' return Promise.resolve() } this.status = 'undeployed' return Promise.reject() } stop() { // deployed, failed console.log('task ', this.id, ' stop') clearInterval(this.intervalID) clearInterval(this.deployInterval) } } class DeloyMonitor { constructor() { this.tasksQueue = [] this.intervalID = undefined } async getTaskNodes () { const parentNode = document.getElementsByClassName('task-list-sider__list')[0] let nodes if (!parentNode) { await sleep(50) nodes = await this.getTaskNodes() return nodes } nodes = parentNode.getElementsByClassName('task-card') if (!nodes || nodes.length === 0) { await sleep(50) nodes = await this.getTaskNodes() return nodes } return nodes } parseNode(node) { const id = node.getElementsByClassName('first-line')[0].getElementsByTagName('strong')[0].innerText const branch = node.getElementsByClassName('branch')[0].innerText.trim() const user = node.getElementsByClassName('second-line')[0].getElementsByTagName('strong')[0].innerText.split(' ')[1]; // const status = node.className.split(' ')[1]; // pending : anticon-sync anticon-spin // success : anticon-check-circle // failed : anticon-close-circle // deployed : anticon-flag const status = node.getElementsByClassName('anticon')[0].className.split(' ') // console.log('id', id, 'status', status) return { id, branch, user, status } } start () { this.intervalID = setInterval(async () => { console.log('deloyMonitor is running') const taskNodes = await this.getTaskNodes(); Array.from(taskNodes).forEach(node => { const { id, branch, user, status } = this.parseNode(node) // add new task const task = this.tasksQueue.find(item => item.id === id) if (!task && status.some(statusClass => ['anticon-sync', 'anticon-spin'].includes(statusClass))) { const task = new DeployTask({ id, branch, user, status }) console.log('add new task ', id , task) this.tasksQueue.push(task) } // remove when failed , deployed if (status.some(statusClass => ['anticon-close-circle', 'anticon-flag'].includes(statusClass))) { const taskIndex = this.tasksQueue.findIndex(item => item.id === id) taskIndex !== -1 && console.log('will remove task ', id , task, 'taskIndex', taskIndex) taskIndex !== -1 && this.tasksQueue.splice(taskIndex, 1) } // remove when success but undeployed if (status.some(statusClass => ['anticon-check-circle'].includes(statusClass))) { const taskIndex = this.tasksQueue.findIndex(item => item.id === id) const successTask = this.tasksQueue[taskIndex] successTask.status === 'undeployed' && this.tasksQueue.splice(taskIndex, 1) } }) console.clear() console.log('at time', parseInt((new Date().getTime() - startTime) / 1000), 'tasks are ',[...this.tasksQueue]) }, 5000) } stop () { console.log('Please press the Logout button to logout.') this.tasksQueue.forEach(task => task.stop()) clearInterval(this.intervalID) } canDeploy (){ return !this.tasksQueue.some(task => task.status === 'deploying') } } monitor = new DeloyMonitor() monitor.start(); window.onbeforeunload = function(e) { monitor.stop(); }; })();