Skip to content

Instantly share code, notes, and snippets.

View wjkennedy's full-sized avatar
💭
I may be slow to respond.

William Kennedy wjkennedy

💭
I may be slow to respond.
View GitHub Profile
@wjkennedy
wjkennedy / compareCloudKeysWithDC.gs
Created September 22, 2025 18:34
Process a list of DC appKeys with the Atlassian Marketplace API to find Cloud equivalents, pricing, etc.
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('Atlassian Tools')
.addItem('Stage 1: Create Cloud/DC sheets from selection', 'createCloudDcSheetsFromSelection')
.addItem('Stage 2: Build consolidated comparison', 'buildComparisonFromCloudDcSheets')
.addToUi();
}
/**
* Stage 1: For each selected addon key, create two sheets:
@wjkennedy
wjkennedy / FetchAtlassianMarketplaceDCCloudPaths.gs
Created September 19, 2025 20:21
FetchAtlassianMarketplaceDCCloudPaths
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('Atlassian Tools')
.addItem('Stage 1: Create Cloud/DC sheets from selection', 'createCloudDcSheetsFromSelection')
.addItem('Stage 2: Build consolidated comparison', 'buildComparisonFromCloudDcSheets')
.addToUi();
}
/**
* Stage 1: For each selected addon key, create two sheets:
@wjkennedy
wjkennedy / board_investigator.sql
Last active August 4, 2025 15:01
board_investigator
WITH board_base AS (
SELECT
rv."ID" AS board_id,
rv."NAME" AS board_name,
CASE
WHEN EXISTS (
SELECT 1
FROM "AO_60DB71_SPRINT" s
WHERE s."RAPID_VIEW_ID" = rv."ID"
)
@wjkennedy
wjkennedy / copyjirakey.bookmarklet
Created July 30, 2025 18:49
✂️ Copy Jira Key
javascript:(function(){function e(e){const t=document.createElement("span");t.textContent="✂️",t.className="scissors-copy-icon",t.style.marginLeft="6px",t.style.cursor="pointer",t.style.fontSize="90%",t.style.verticalAlign="middle",t.style.opacity="0.3",t.style.filter="grayscale(100%)",t.title=`Copy ${e} to clipboard`,t.onclick=n=>{n.stopPropagation(),navigator.clipboard.writeText(e).then(()=>{t.textContent="✅",t.style.opacity="0.6",t.style.filter="none",setTimeout(()=>{t.textContent="✂️",t.style.opacity="0.3",t.style.filter="grayscale(100%)"},1500)}).catch(e=>{console.error("Clipboard copy failed",e)})};return t}function t(){const t=document.querySelector('[data-testid="issue.views.issue-base.foundation.breadcrumbs.breadcrumb-current-issue-container"]');if(t&&!t.querySelector(".scissors-copy-icon")){const n=t.textContent.trim(),i=e(n);i.style.display="none",t.appendChild(i),t.addEventListener("mouseenter",()=>i.style.display="inline"),t.addEventListener("mouseleave",()=>i.style.display="none")}document.query
(function () {
function addCopyButton(container, keyText) {
// Prevent duplicate buttons
if (container.querySelector('.copy-issue-key-btn')) return;
const button = document.createElement('button');
button.textContent = 'Copy';
button.className = 'copy-issue-key-btn';
button.style.marginLeft = '8px';
button.style.cursor = 'pointer';
@wjkennedy
wjkennedy / product-idea-bandit
Last active July 30, 2025 15:19
Brainstorm your next direct marketing product
import React, { useState } from 'react';
const products = ["Coffee mugs", "Socks", "Blankets", "Water bottles", "Pillows", "Pens", "Notebooks", "Sunglasses", "Hats", "Belts", "Flashlights", "Soap bars", "Lip balm", "Candles", "Umbrellas", "Towels", "Backpacks", "T-shirts", "Hoodies", "Shoes", "Gloves", "Toothpaste", "Laundry detergent", "Keychains", "Phone cases", "Chargers", "Headphones", "Lunchboxes", "Tote bags", "Thermos bottles", "Sticky notes", "Pet collars", "Picture frames", "Cutting boards", "Watches", "Aprons", "Scarves", "Calendars", "Wallets", "Coasters", "Mouse pads", "Door mats", "Shower curtains", "Dish soap", "Magnets", "Yoga mats", "Luggage tags", "Nail clippers", "Hand sanitizer", "Bandages", "Flash drives", "Journals", "Tea kettles", "Measuring cups", "Ice trays", "Spray bottles", "Oven mitts", "Travel pillows", "Reading lamps", "Sleeping masks", "Magnifying glasses", "Staplers", "Tape dispensers", "Paintbrushes", "USB cables", "Alarm clocks", "Scissors", "Tweezers", "Gardening gloves", "B
@wjkennedy
wjkennedy / jenkinstojiraautomation.py
Created July 28, 2025 19:36
jenkinstojiraautomation POC
import os
import re
import json
def extract_jira_steps(jenkinsfile_content):
"""
Extracts usage of deprecated jira-steps from a Jenkinsfile.
Returns a dict mapping step name to parameter dicts.
"""
jira_steps = ["jiraAddComment", "jiraTransitionIssue", "jiraNewIssue"]
import csv
from jira import JIRA
# Configuration for both instances
DC_SERVER = 'https://your-datacenter-jira-instance.com'
DC_API_TOKEN = 'your_dc_api_token'
DC_EMAIL = 'your_dc_email@example.com'
CLOUD_SERVER = 'https://your-cloud-jira-instance.atlassian.net'
CLOUD_API_TOKEN = 'your_cloud_api_token'
@wjkennedy
wjkennedy / jira-comparator.py
Last active July 26, 2025 22:58
jira-comparator
import csv
from jira import JIRA
# Configuration for both instances
DC_SERVER = 'https://your-datacenter-jira-instance.com'
DC_API_TOKEN = 'your_dc_api_token'
DC_EMAIL = 'your_dc_email@example.com'
CLOUD_SERVER = 'https://your-cloud-jira-instance.atlassian.net'
CLOUD_API_TOKEN = 'your_cloud_api_token'
import requests
import configparser
import time
from collections import defaultdict
# Load config
config = configparser.ConfigParser()
config.read("config/config.properties")
JIRA_SERVER = config.get("jira", "server")
JIRA_USER = config.get("jira", "username")