github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/cmd/deck/static/common/rerun.ts (about) 1 import {copyToClipboard, icon, showAlert, showToast} from "./common"; 2 import {relativeURL} from "./urls"; 3 4 export function createRerunProwJobIcon(modal: HTMLElement, parentEl: Element, prowjob: string, showRerunButton: boolean, csrfToken: string): HTMLElement { 5 const LATEST_JOB = 'latest'; 6 const ORIGINAL_JOB = 'original'; 7 const inrepoconfigURL = 'https://docs.prow.k8s.io/docs/inrepoconfig/'; 8 const i = icon.create("refresh", "Show instructions for rerunning this job"); 9 10 const closeModal = (): void => { 11 modal.style.display = "none"; 12 // Resets modal content. If removed, elements will be concatenated, causing duplicates. 13 parentEl.classList.remove('rerun-content', 'abort-content'); 14 parentEl.innerHTML = ''; 15 }; 16 window.onkeydown = (event: any) => { 17 if (event.key === "Escape") { 18 closeModal(); 19 } 20 }; 21 window.onclick = (event: any) => { 22 if (event.target === modal) { 23 closeModal(); 24 } 25 }; 26 const getJobURL = (mode: string): string => { 27 return `${location.protocol}//${location.host}/rerun?mode=${mode}&prowjob=${prowjob}`; 28 }; 29 let commandURL = getJobURL(ORIGINAL_JOB); 30 const getCommandDescription = (mode: string): string => { 31 return `The command is for the ${mode} configuration. Admin permissions are required to rerun via kubectl.`; 32 }; 33 const getCommand = (url: string): string => { 34 return `kubectl create -f "${url}"`; 35 }; 36 37 // we actually want to know whether the "access-token-session" cookie exists, but we can't always 38 // access it from the frontend. "github_login" should be set whenever "access-token-session" is 39 i.onclick = () => { 40 modal.style.display = "block"; 41 // Add the styles for rerun modal 42 parentEl.classList.add('rerun-content'); 43 44 parentEl.innerHTML = ` 45 <h2 class="rerunModal-title">Rerun ProwJob</h2> 46 <p class="rerunModal-description"> 47 Below you can choose to rerun this ProwJob with either the original or latest configuration. 48 <br><br> 49 Note: Rerunning a ProwJob will create a new instance of a ProwJob. Any ProwJobs already running will not be interrupted. 50 <a href="${inrepoconfigURL}" target="_blank"> 51 Inrepoconfig 52 <i class='rerunModal-openOut material-icons state triggered' style='color: gray'>open_in_new</i> 53 </a> 54 is currently not supported with the latest configuration option. 55 </p> 56 <div class="rerunModal-radioButtonGroup"> 57 <div class="rerunModal-radioButtonRow"> 58 <label class="rerunModal-radioLabel mdl-radio mdl-js-radio mdl-js-ripple-effect" for="rerunOriginalOption"> 59 <input type="radio" id="rerunOriginalOption" class="rerunOriginalOption mdl-radio__button" name="rerunOptions" checked> 60 <span class="mdl-radio__label">Original Configuration</span> 61 </label> 62 (<a href="${getJobURL(ORIGINAL_JOB)}" target="_blank">View YAML 63 <i class="rerunModal-openOut material-icons state triggered" style="color: gray">open_in_new</i> 64 </a>) 65 </div> 66 <div class="rerunModal-radioButtonRow"> 67 <label class="rerunModal-radioLabel mdl-radio mdl-js-radio mdl-js-ripple-effect" for="rerunLatestOption"> 68 <input type="radio" id="rerunLatestOption" class="rerunLatestOption mdl-radio__button" name="rerunOptions"> 69 <span class="mdl-radio__label">Latest Configuration</span> 70 </label> 71 (<a href="${getJobURL(LATEST_JOB)}" target="_blank">View YAML 72 <i class="rerunModal-openOut material-icons state triggered" style="color: gray">open_in_new</i> 73 </a>) 74 </div> 75 </div> 76 <div class="rerunModal-accordion"> 77 <button class="rerunModal-accordionButton"> 78 <i class="rerunModal-expandIcon material-icons state triggered" style="color: gray">expand_more</i> 79 kubectl command 80 </button> 81 <div class="rerunModal-accordionPanel"> 82 <div class="accordion-panel-content"> 83 <p class="rerunModal-commandDescription">${getCommandDescription(LATEST_JOB)}</p> 84 <div class="rerunModal-commandContent"> 85 <div class="rerunModal-command">${getCommand(commandURL)}</div> 86 <a class="rerunModal-copyButton mdl-button mdl-js-button mdl-button--icon"> 87 <i class="material-icons state triggered" style="color: gray">content_copy</i> 88 </a> 89 </div> 90 </div> 91 </div> 92 </div> 93 `; 94 95 const latestOption = parentEl.querySelector('.rerunLatestOption'); 96 const command = parentEl.querySelector('.rerunModal-command'); 97 const commandDescription = parentEl.querySelector('.rerunModal-commandDescription'); 98 latestOption.addEventListener('click', () => { 99 commandURL = getJobURL(LATEST_JOB); 100 commandDescription.innerHTML = getCommandDescription(LATEST_JOB); 101 command.innerHTML = getCommand(commandURL); 102 }); 103 const originalOption = parentEl.querySelector('.rerunOriginalOption'); 104 originalOption.addEventListener('click', () => { 105 commandURL = getJobURL(ORIGINAL_JOB); 106 commandDescription.innerHTML = getCommandDescription(ORIGINAL_JOB); 107 command.innerHTML = getCommand(commandURL); 108 }); 109 const copyButton = parentEl.querySelector('.rerunModal-copyButton'); 110 copyButton.addEventListener('click', () => { 111 copyToClipboard(getCommand(commandURL)); 112 showToast("Copied to clipboard"); 113 }); 114 const accordion = parentEl.querySelector('.rerunModal-accordionButton'); 115 const accordionPanel = parentEl.querySelector('.rerunModal-accordionPanel'); 116 const expandIcon = parentEl.querySelector('.rerunModal-expandIcon'); 117 accordion.addEventListener('click', () => { 118 if (!accordionPanel.classList.contains('rerunModal-accordionPanel--expanded')) { 119 accordionPanel.classList.add('rerunModal-accordionPanel--expanded'); 120 expandIcon.classList.add('rerunModal-expandIcon--expanded'); 121 } else { 122 accordionPanel.classList.remove('rerunModal-accordionPanel--expanded'); 123 expandIcon.classList.remove('rerunModal-expandIcon--expanded'); 124 } 125 }); 126 127 if (showRerunButton) { 128 const runButton = document.createElement('a'); 129 runButton.innerHTML = "<button class='mdl-button mdl-js-button mdl-button--raised mdl-button--colored'>Rerun</button>"; 130 runButton.onclick = async () => { 131 gtag("event", "rerun", { 132 event_category: "engagement", 133 transport_type: "beacon", 134 }); 135 try { 136 const result = await fetch(commandURL, { 137 headers: { 138 "Content-type": "application/x-www-form-urlencoded; charset=UTF-8", 139 "X-CSRF-Token": csrfToken, 140 }, 141 method: 'post', 142 }); 143 if (result.status === 401) { 144 window.location.href = `${window.location.origin }/github-login?dest=${relativeURL({rerun: "gh_redirect"})}`; 145 } 146 const data = await result.text(); 147 if (result.status >= 400) { 148 showAlert(data); 149 } else { 150 showToast(data); 151 } 152 } catch (e) { 153 showAlert(`Could not send request to rerun job: ${e}`); 154 } 155 }; 156 parentEl.appendChild(runButton); 157 } 158 }; 159 160 return i; 161 }