Skip to content

Instantly share code, notes, and snippets.

@Blumed
Last active August 3, 2025 03:22
Show Gist options
  • Select an option

  • Save Blumed/5d29a46ee55ca6d57f738ba38f3fdd33 to your computer and use it in GitHub Desktop.

Select an option

Save Blumed/5d29a46ee55ca6d57f738ba38f3fdd33 to your computer and use it in GitHub Desktop.

Revisions

  1. Blumed revised this gist Aug 3, 2025. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions Documentation.md
    Original file line number Diff line number Diff line change
    @@ -32,6 +32,7 @@ With one click you are able to create a highly detailed message instantly for yo
    - Stores what branch you will be merging into
    - Squashed check. If there is only one commit it will send a `:checkmarkicon:` next to label. If there is more than one it will display `:erroricon:` next to label.
    - Jira Ticket check. If there is a jira url it will display a link to it next to label. If there isn't then it will display `:erroricon:` next to label.
    - Pipeline check. If the pipe line is running it will display `:spinningicon:` next to label. If the pipeline has warnings it will display `:warningicon;` next to label. If the pipeline failed it will display `:erroricon:` next to label.
    - Changes count and link to diff. Since we know the MR url then we know the diff url. This is really helpful because this is a good indicator for yourself and others how long a code review might take.
    - Reviewers check. If a reviewer handle was provided then when the message posts they will get pinged. If there are no reviewers then it will say `No Reviewers Provided`
    - Changes list items check. If you listed out the changes made in your MR then they will be shown in list form in your message. If there are no list items it will display `No List Items Provided`
  2. Blumed revised this gist Aug 3, 2025. 1 changed file with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions bookmarklet-gitlab-mr-to-slack-message.js
    Original file line number Diff line number Diff line change
    @@ -57,3 +57,6 @@ ${listItems.length === 0 ? 'No List Items Found' : list}`);
    } catch(error) {
    console.log(`${bookmarklet.name} : ${bookmarklet.version} : ${error}`);
    }

    // Paste the one line below into your bookmark url field for this code to work
    javascript:(function(){const bookmarklet={name:"gitlab-mr-template-to-slack-message-linter",version:"1.0.0"},jiraCompanyName="wheniwork";try{const e=document.getElementById("merge_request_description");if(e){const t=document.querySelector(".branch-selector code").textContent,n=`${t.split("-")[0].replace(/^(.*\/)/,"")}-${t.split("-")[1]}`;e.value=`## Summary\n-\n\nJira Ticket: ${/(([a-z])+\-([0-9])+)/.test(n)?`https://wheniwork.atlassian.net/browse/${n.toUpperCase()}`:""}\n\nReviewers: \n`}else{const e=window.location.href,t=document.querySelector(".author-link.js-user-link + .ref-container").getAttribute("title"),n=document.querySelector(".detail-page-description .ref-container:last-of-type").getAttribute("title"),o=document.querySelector('a[href*="https://wheniwork.atlassian.net/browse/"]'),r=[].slice.call(document.querySelectorAll(".description .md ul:not(.task-list) li")),i=[].slice.call(document.querySelectorAll(".description .md p")),l=r.map((e=>`> - ${e.textContent.replace(",","")}\n`)).join(""),s=()=>{const e=i.map((e=>e.textContent)),t=e.filter((e=>e.match("@")));return t.length?t[0].replace("Reviewers: ",""):"No Reviewers Found"},a=document.querySelector(".js-commits-count").textContent,c=document.querySelector(".ci-icon-gl-icon-wrapper > svg > use").href.baseVal,u=document.querySelector('[data-action="diffs"] > span').textContent.trim(),d=document.querySelector('[data-action="diffs"]').href,m=document.querySelector("nav .breadcrumb li:nth-child(2) span").textContent,p=e=>e.includes("status_success")?":successful:":e.includes("status_warning")?":warning:":e.includes("status_failed")?":failed:":e.includes("status_running")?":macos-loading-wheel:":void 0;navigator.clipboard.writeText(`:git: *${m}* [MR](${e}) *${t}* _into_ *${n}*\n> *Squashed*: ${"1"===a?":successful:":":failed:"}\n> *Pipeline*: ${p(c)}\n> *Jira Ticket*: ${null!==o?`[link](${o})`:":failed:"}\n> *Changes*: ${u} [diff](${d})\n> *Reviewers*: ${s()}\n${0===r.length?"No List Items Found":l}`)}console.log(`${bookmarklet.name}: ${bookmarklet.version}`)}catch(e){console.log(`${bookmarklet.name} : ${bookmarklet.version} : ${e}`)}}());
  3. Blumed revised this gist Aug 3, 2025. 1 changed file with 1 addition and 3 deletions.
    4 changes: 1 addition & 3 deletions Documentation.md
    Original file line number Diff line number Diff line change
    @@ -21,9 +21,7 @@ and even lint some of the information for you if you missed it.
    *Why Make This?*

    My team pumps out MR's all day long. It is always the same processes over and over again which means it is perferct for micro automation.
    In our MR message all we need to do is fill out the list items of changes and add a reviewer handle and our MR message is complete.
    When we want to post the MR in Slack it is as simple as clicking a button and a highly detailed message is instantly ready for people to see.
    It will save you time and if you are able to get others to use it will save your company time and money.
    With one click you are able to create a highly detailed message instantly for your team members to see in Slack. If the linter shows there is missing information I can tell right away this MR is coming in hot or the person didn't take the time to fill out their MR properly which means I might fine tooth comb when doning a code review. Not all code reviews are created equally. Has someone posted generic link to an MR and you click it is 60 page diff? I know I have. Now you can see the diff count in slack so can decide the best route for your time management. It will save you time and if you are able to get others to use it will save your company time and money.

    *Features*:
    - Creates templated MR message for you
  4. Blumed revised this gist Aug 3, 2025. 1 changed file with 43 additions and 0 deletions.
    43 changes: 43 additions & 0 deletions Documentation.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,43 @@
    # Gitlab MR template and Gitlab MR to Slack message linter

    <img width="615" height="186" alt="Screenshot 2025-08-02 at 8 39 18 PM" src="https://gist.github.com/user-attachments/assets/db00a21f-0d47-4fa0-9eb8-60f6135589ef" />

    This bookmarklet has three functionalities.
    1. Creates MR template for you.
    2. Grabs data from your MR page and lints it.
    3. When it grabs all the data from your MR page it saves in your clickboard as a pretty message for slack in markdown format.

    *How To Use It*

    1. When you first create a merge request if you click this bookmarklet it will auto populate the MR message for you.
    It will create a title, a list item, a jira item and generate the jira url for you, a reviewers item. Feel out the line items
    provided. When adding the reviewer make sure to add the slack handle of the reviewer exactly `@teammember @anotherteammember`.
    2. Save your MR when you are done filling out your message.
    3. When you are viewing your MR page click the bookmarklet again. This time it will grab all the data needed for a nice slack message
    and even lint some of the information for you if you missed it.
    4. *Make sure your slack messages are set to markdown in your peronsal configurations*
    5. Paste into slack message and press send. If you slack handles match the reviewers then they get pinged automatically!

    *Why Make This?*

    My team pumps out MR's all day long. It is always the same processes over and over again which means it is perferct for micro automation.
    In our MR message all we need to do is fill out the list items of changes and add a reviewer handle and our MR message is complete.
    When we want to post the MR in Slack it is as simple as clicking a button and a highly detailed message is instantly ready for people to see.
    It will save you time and if you are able to get others to use it will save your company time and money.

    *Features*:
    - Creates templated MR message for you
    - It will add the jira url into the template for you if you put jira ticket names into your branch names
    - Stores repo name
    - Stores MR url
    - Stores branch name
    - Stores what branch you will be merging into
    - Squashed check. If there is only one commit it will send a `:checkmarkicon:` next to label. If there is more than one it will display `:erroricon:` next to label.
    - Jira Ticket check. If there is a jira url it will display a link to it next to label. If there isn't then it will display `:erroricon:` next to label.
    - Changes count and link to diff. Since we know the MR url then we know the diff url. This is really helpful because this is a good indicator for yourself and others how long a code review might take.
    - Reviewers check. If a reviewer handle was provided then when the message posts they will get pinged. If there are no reviewers then it will say `No Reviewers Provided`
    - Changes list items check. If you listed out the changes made in your MR then they will be shown in list form in your message. If there are no list items it will display `No List Items Provided`



    Created with ❤️ using https://make-bookmarklets.com
  5. Blumed revised this gist Aug 3, 2025. 1 changed file with 53 additions and 26 deletions.
    79 changes: 53 additions & 26 deletions bookmarklet-gitlab-mr-to-slack-message.js
    Original file line number Diff line number Diff line change
    @@ -1,32 +1,59 @@
    const bookmarklet = { name: "bookmakrlet__gitlab-mr-to-slack-message", version: "1.0",companyName: "Your Company Name" };
    const bookmarklet = {
    name: "gitlab-mr-template-to-slack-message-linter",
    version: "1.0.0"
    };

    const jiraCompanyName = 'yourcompanynamefoundonjirasubdomian.atlassian.net';

    try {
    const mrLink = window.location.href;
    const branch = document.querySelector('.author-link.js-user-link + .ref-container').getAttribute("title");
    const branchDestination = document.querySelector('.detail-page-description .ref-container:last-of-type').getAttribute("title");
    const ticket = document.querySelector(`a[href*="https://${bookmarklet.companyName}.atlassian.net/browse/"]`);
    const listItems = [].slice.call(document.querySelectorAll('.description .md ul:not(.task-list) li'));
    const list = listItems.map(listItem => `> - ${listItem.textContent.replace(',', '')}\n`).join('');
    const squashed = document.querySelector('.js-commits-count').textContent;
    const pipline = document.querySelector('.ci-icon-gl-icon-wrapper > svg > use').href.baseVal;
    const changes = document.querySelector('[data-action="diffs"] > span').textContent.trim();
    const diff = document.querySelector('[data-action="diffs"]').href;
    const repo = document.querySelector('nav .breadcrumb li:nth-child(2) span').textContent;
    const pipelineStatus = pipelineString => {
    if(pipelineString.includes('status_success')) return ':successful:';
    if(pipelineString.includes('status_warning')) return ':warning:';
    if(pipelineString.includes('status_failed')) return ':failed:';
    if(pipelineString.includes('status_running')) return ':macos-loading-wheel:';
    };
    navigator.clipboard.writeText(`
    :git: *${repo}* [MR](${mrLink}) *${branch}* _into_ *${branchDestination}*
    const mrTemplate = document.getElementById('merge_request_description');
    if(mrTemplate) {
    const branchSelector = document.querySelector('.branch-selector code').textContent;
    const ticketId = `${branchSelector.split('-')[0].replace(/^(.*\/)/,'')}-${branchSelector.split('-')[1]}`;
    mrTemplate.value = `## Summary
    -
    Jira Ticket: ${/(([a-z])+\-([0-9])+)/.test(ticketId) ? `https://${jiraCompanyName}.atlassian.net/browse/${ticketId.toUpperCase()}` : ''}
    Reviewers:
    `;
    } else {
    const mrLink = window.location.href;
    const branch = document.querySelector('.author-link.js-user-link + .ref-container').getAttribute("title");
    const branchDestination = document.querySelector('.detail-page-description .ref-container:last-of-type').getAttribute("title");
    const ticket = document.querySelector(`a[href*="https://${jiraCompanyName}.atlassian.net/browse/"]`);
    const listItems = [].slice.call(document.querySelectorAll('.description .md ul:not(.task-list) li'));
    const descriptionText = [].slice.call(document.querySelectorAll('.description .md p'));
    const list = listItems.map(listItem => `> - ${listItem.textContent.replace(',', '')}\n`).join('');

    const reviewers = () => {
    const text = descriptionText.map(content => content.textContent);
    const content = text.filter(reviewer => reviewer.match('@'));
    if (!content.length) {
    return 'No Reviewers Found';
    }
    return content[0].replace('Reviewers: ', '');
    };
    const squashed = document.querySelector('.js-commits-count').textContent;
    const pipline = document.querySelector('.ci-icon-gl-icon-wrapper > svg > use').href.baseVal;
    const changes = document.querySelector('[data-action="diffs"] > span').textContent.trim();
    const diff = document.querySelector('[data-action="diffs"]').href;
    const repo = document.querySelector('nav .breadcrumb li:nth-child(2) span').textContent;
    const pipelineStatus = pipelineString => {
    if(pipelineString.includes('status_success')) return ':successful:';
    if(pipelineString.includes('status_warning')) return ':warning:';
    if(pipelineString.includes('status_failed')) return ':failed:';
    if(pipelineString.includes('status_running')) return ':macos-loading-wheel:';
    };
    navigator.clipboard.writeText(`:git: *${repo}* [MR](${mrLink}) *${branch}* _into_ *${branchDestination}*
    > *Squashed*: ${squashed === '1' ? ':successful:' : ':failed:'}
    > *Pipeline*: ${pipelineStatus(pipline)}
    > *Jira Ticket*: ${ticket !== null ? `[link](${ticket})` : ':failed:'}
    > *Changes*: ${changes} [diff](${diff})
    ${listItems.length === 0 ? 'No List Items Found' : list}
    `);
    console.log(`${bookmarklet.name}: ${bookmarklet.version}`);
    } catch (error) {
    console.log(`${bookmarklet.name} : ${bookmarklet.version} : ${error}`);
    }
    > *Reviewers*: ${reviewers()}
    ${listItems.length === 0 ? 'No List Items Found' : list}`);
    }
    console.log(`${bookmarklet.name}: ${bookmarklet.version}`);
    } catch(error) {
    console.log(`${bookmarklet.name} : ${bookmarklet.version} : ${error}`);
    }
  6. Blumed created this gist Aug 3, 2025.
    32 changes: 32 additions & 0 deletions bookmarklet-gitlab-mr-to-slack-message.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,32 @@
    const bookmarklet = { name: "bookmakrlet__gitlab-mr-to-slack-message", version: "1.0",companyName: "Your Company Name" };

    try {
    const mrLink = window.location.href;
    const branch = document.querySelector('.author-link.js-user-link + .ref-container').getAttribute("title");
    const branchDestination = document.querySelector('.detail-page-description .ref-container:last-of-type').getAttribute("title");
    const ticket = document.querySelector(`a[href*="https://${bookmarklet.companyName}.atlassian.net/browse/"]`);
    const listItems = [].slice.call(document.querySelectorAll('.description .md ul:not(.task-list) li'));
    const list = listItems.map(listItem => `> - ${listItem.textContent.replace(',', '')}\n`).join('');
    const squashed = document.querySelector('.js-commits-count').textContent;
    const pipline = document.querySelector('.ci-icon-gl-icon-wrapper > svg > use').href.baseVal;
    const changes = document.querySelector('[data-action="diffs"] > span').textContent.trim();
    const diff = document.querySelector('[data-action="diffs"]').href;
    const repo = document.querySelector('nav .breadcrumb li:nth-child(2) span').textContent;
    const pipelineStatus = pipelineString => {
    if(pipelineString.includes('status_success')) return ':successful:';
    if(pipelineString.includes('status_warning')) return ':warning:';
    if(pipelineString.includes('status_failed')) return ':failed:';
    if(pipelineString.includes('status_running')) return ':macos-loading-wheel:';
    };
    navigator.clipboard.writeText(`
    :git: *${repo}* [MR](${mrLink}) *${branch}* _into_ *${branchDestination}*
    > *Squashed*: ${squashed === '1' ? ':successful:' : ':failed:'}
    > *Pipeline*: ${pipelineStatus(pipline)}
    > *Jira Ticket*: ${ticket !== null ? `[link](${ticket})` : ':failed:'}
    > *Changes*: ${changes} [diff](${diff})
    ${listItems.length === 0 ? 'No List Items Found' : list}
    `);
    console.log(`${bookmarklet.name}: ${bookmarklet.version}`);
    } catch (error) {
    console.log(`${bookmarklet.name} : ${bookmarklet.version} : ${error}`);
    }