您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add useful options for Build & Deploy pipeline in Azure DevOps
当前为
您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
- // ==UserScript==
- // @name ADO Build & Deploy - Run Pipeline Plus
- // @namespace http://tampermonkey.net/
- // @version 1.0.0
- // @description Add useful options for Build & Deploy pipeline in Azure DevOps
- // @author Victor Ros
- // @match https://*.visualstudio.com/*/_build?definitionId=3237*
- // @match https://dev.azure.com/*/*/_build?definitionId=3237*
- // @match https://*.visualstudio.com/*/_build?definitionId=3333*
- // @match https://dev.azure.com/*/*/_build?definitionId=3333*
- // @match https://*.visualstudio.com/*/_build?definitionId=4569*
- // @match https://dev.azure.com/*/*/_build?definitionId=4569*
- // @icon https://www.google.com/s2/favicons?domain=azure.com
- // @grant none
- // @license MIT
- // ==/UserScript==
- (async function() {
- "use strict";
- // Constantes
- const TEXT = {
- "fr": {
- buttonAllServices: "Tous les services"
- },
- "en": {
- buttonAllServices: "All services"
- }
- };
- const LANGUAGE = getLanguage();
- const RUN_PIPELINE_SELECTOR = "__bolt-run-pipeline-command";
- const POPUP_SELECTOR = ".bolt-panel-callout-content";
- const PARAMETERS_SELECTOR = ".padding-horizontal-20.rhythm-vertical-16 > .flex-noshrink";
- const BRANCHES_DROPDOWN_INPUT_SELECTOR = ".version-dropdown > input";
- const BUTTON_ID = "arpege-web-build-deploy-all-service-button";
- /**
- * Returns navigator's language.
- * @returns {string} Language. Default "en".
- */
- function getLanguage() {
- // Get language from navigator variable
- let language = (
- typeof navigator === "object" &&
- navigator.language &&
- navigator.language.split("-").shift()
- );
- // If not text found, set "en" as default
- if (typeof TEXT[language] === "undefined") {
- language = "en";
- }
- return language;
- }
- /**
- * Wait for the appearance of the HTML elements with the selector.
- * @param {string} _selector - The selector
- * @param {object} options - Options
- * @param {string} options.name - Selector name (Default to _selector value)
- * @param {number} options.maxRetry - Number of retry (Default to 0)
- * @param {number} options.timeout - Time to wait before retrying (Default to 1 sec)
- * @returns {Promise<void>} Empty promise.
- * @async
- */
- async function waitFor(_selector, {name = _selector, maxRetry = 0, timeout = 1000} = {}) {
- const result = document.querySelectorAll(_selector);
- if (result.length > 0) {
- return;
- } else if (maxRetry > 0) {
- console.debug(`[waitFor] [${name}] Remaining retries: ${--maxRetry}`);
- await new Promise((_resolve, _reject) => {
- setTimeout(async () => {
- try {
- await waitFor(_selector, {name, maxRetry, timeout});
- _resolve();
- } catch (_err) {
- _reject(_err);
- }
- }, timeout);
- });
- } else {
- throw new Error(`Cannot find elements with selector: ${_selector}`);
- }
- }
- /**
- * Get services HTML elements from Run Pipeline popup.
- * @returns {void} Nothing.
- */
- function getServiceElements() {
- const popup = document.querySelector(POPUP_SELECTOR);
- const elements = document.querySelectorAll(PARAMETERS_SELECTOR);
- const svcElements = [];
- let databasePrepareEltFound = false;
- // Ignore all parameters until "databasePrepare" parameter
- elements.forEach((_elt, _idx) => {
- if (databasePrepareEltFound) {
- svcElements.push(_elt);
- } else if (_elt.innerHTML.includes("databasePrepare")) {
- databasePrepareEltFound = true;
- }
- });
- return svcElements;
- }
- /**
- * Add a button to select/unselect all services.
- * Recreate the HTML button.
- * @returns {HTMLElement} Button "All services".
- */
- function createButtonAllServices(_svcElements) {
- const firstSvcElement = _svcElements[0];
- const buttonAllServices = firstSvcElement.cloneNode(true);
- // Unselect by default
- buttonAllServices.setAttribute("aria-checked", false);
- buttonAllServices.classList.remove("checked");
- // Override id from div child
- const divChild = buttonAllServices.querySelector(".bolt-checkbox-label");
- divChild.setAttribute("id", BUTTON_ID);
- divChild.innerHTML = TEXT[LANGUAGE].buttonAllServices;
- // Add click event listener
- buttonAllServices.addEventListener("click", (_event) => {
- _event.stopPropagation();
- _event.preventDefault();
- const oldChecked = buttonAllServices.getAttribute("aria-checked") === "true";
- const newChecked = !oldChecked;
- const action = newChecked === true ? "add" : "remove";
- // Update aria-checked
- buttonAllServices.setAttribute("aria-checked", newChecked);
- buttonAllServices.classList[action]("checked");
- // Get services' parameters elements and all parameters elements
- const svcElements = getServiceElements();
- for (let svcElt of svcElements) {
- const svcChecked = svcElt.getAttribute("aria-checked") === "true";
- // Button is checked but service is not, or button is unchecked and service is.
- if (newChecked && !svcChecked || !newChecked && svcChecked) {
- svcElt.click();
- }
- }
- buttonAllServices.focus();
- });
- // Add div element before first service element
- firstSvcElement.insertAdjacentElement("beforebegin", buttonAllServices);
- return buttonAllServices;
- }
- async function run() {
- console.debug("ADO Arpege-Web Build & Compile - Run Pipeline Plus");
- // Search by ID Run Pipeline button
- const buttonRunPipeline = document.getElementById(RUN_PIPELINE_SELECTOR);
- if (typeof buttonRunPipeline === "undefined") {
- console.warn("Cannot find Run pipeline button");
- return;
- } else {
- console.debug("[run] Found Run pipeline button");
- }
- buttonRunPipeline.addEventListener("click", async () => {
- try {
- // Wait 5 sec max for parameters elements to be present in Run Pipeline popup
- await waitFor(PARAMETERS_SELECTOR, {name: "Services parameters", maxRetry: 10, timeout: 500});
- // Get services' parameters elements and all parameters elements
- const svcElements = getServiceElements();
- // Add div element before first service element
- const buttonAllServices = createButtonAllServices(svcElements);
- } catch (_err) {
- console.error(_err);
- }
- });
- }
- run();
- })();