diff --git a/.github/scripts/sync-podcast-feed.js b/.github/scripts/sync-podcast-feed.js new file mode 100644 index 000000000..1dcd5b911 --- /dev/null +++ b/.github/scripts/sync-podcast-feed.js @@ -0,0 +1,367 @@ +// .github/scripts/sync-podcast-feed.js +// Incremental sync of The PowerShell Podcast (Podbean) into content/podcast/. +// +// Design: see docs/adr/0003-incremental-podcast-sync.md. +// The feed currently carries the full archive, but this script is strictly +// ADD-ONLY: it generates an episode file only when no existing file matches, +// and never edits or deletes. That makes a full pass over the feed safe and +// lets the first run backfill the whole gap between the repo and the feed. +// +// Idempotency key (in priority order): enclosure URL, then RSS guid, then +// episode number. The enclosure URL is the universal key — every existing +// modern file carries it as `podcast_url`. +// +// Run `node .github/scripts/sync-podcast-feed.js --dry-run` to preview. + +import fetch from 'node-fetch'; +import fs from 'fs'; +import path from 'path'; + +const FEED_URL = 'https://feed.podbean.com/powershellpodcast/feed.xml'; +const PODCAST_DIR = path.join('content', 'podcast'); +const HOST = 'Andrew Pla'; +const TITLE_PREFIX = 'The PowerShell Podcast '; +const DRY_RUN = process.argv.includes('--dry-run'); + +// Recurring boilerplate links lifted/dropped from episode bodies. A body line +// (typically a "Resource Links" bullet) is dropped if it contains any of these. +// Keep this list tight — episode-specific links must survive. youtu.be is +// dropped because the id is lifted into the `youtube` frontmatter field. +const BOILERPLATE = [ + /andrewpla\.tech/i, + /discord\.gg\/pdq/i, + /powershellsummit\.org/i, + /youtu\.be\//i, +]; + +// --- XML helpers ----------------------------------------------------------- + +function decodeEntities(str) { + return str + .replace(/&#x([0-9a-fA-F]+);/g, (_, h) => String.fromCodePoint(parseInt(h, 16))) + .replace(/&#(\d+);/g, (_, d) => String.fromCodePoint(parseInt(d, 10))) + .replace(/'/g, "'") + .replace(/"/g, '"') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/ /g, ' ') + .replace(/&/g, '&'); +} + +// Read the text of a single child tag from an block, unwrapping CDATA. +function tag(item, name) { + const m = item.match(new RegExp(`<${name}(?:\\s[^>]*)?>([\\s\\S]*?)`, 'i')); + if (!m) return ''; + let v = m[1].trim(); + const cdata = v.match(/^$/); + if (cdata) return cdata[1]; + return decodeEntities(v); +} + +function attr(item, tagName, attrName) { + const m = item.match(new RegExp(`<${tagName}\\b[^>]*\\b${attrName}=["']([^"']*)["']`, 'i')); + return m ? m[1] : ''; +} + +// --- Slug + date ----------------------------------------------------------- + +// Mirrors Hugo's default slugify closely enough to match the existing modern +// filenames: lowercase, drop apostrophes, collapse runs of other non-alnum +// characters to single hyphens, trim hyphens. +function slugify(s) { + return s + .toLowerCase() + .replace(/['‘’]/g, '') + .replace(/[^a-z0-9]+/g, '-') + .replace(/^-+|-+$/g, ''); +} + +function pad2(n) { + return String(n).padStart(2, '0'); +} + +// pubDate -> { date: 'YYYY-MM-DD', iso: 'YYYY-MM-DDTHH:MM:SS+00:00', y, m } +function parseDate(pubDate) { + const d = new Date(pubDate); + const y = d.getUTCFullYear(); + const m = pad2(d.getUTCMonth() + 1); + const day = pad2(d.getUTCDate()); + const iso = `${y}-${m}-${day}T${pad2(d.getUTCHours())}:${pad2(d.getUTCMinutes())}:${pad2(d.getUTCSeconds())}+00:00`; + return { date: `${y}-${m}-${day}`, iso, y, m }; +} + +// --- Episode number from enclosure filename -------------------------------- + +// The repo's episode-number convention is the number embedded in the Podbean +// filename (`..._episode_NNN_...`), NOT itunes:episode (which runs one ahead). +// Most filenames delimit the number (`episode_220_Morten`), but specials glue a +// random suffix onto it (`episode_2298xv9d`). For the ambiguous case, pick the +// digit-prefix closest to itunes:episode (the numbers track within ~1). +function resolveEpisode(enclosureUrl, itunesEp) { + const clean = enclosureUrl.match(/episode[_-](\d+)[_-]/i); + if (clean) return parseInt(clean[1], 10); + + const greedy = enclosureUrl.match(/episode[_-](\d+)/i); + if (!greedy) return null; + const digits = greedy[1]; + if (!itunesEp) return parseInt(digits, 10); + + let best = null; + for (let len = digits.length; len >= 1; len--) { + const cand = parseInt(digits.slice(0, len), 10); + if (Math.abs(cand - itunesEp) <= 2) { best = cand; break; } + } + return best != null ? best : parseInt(digits, 10); +} + +// --- HTML body -> markdown ------------------------------------------------- + +function htmlToMarkdown(html) { + let md = html; + + // Lists + md = md.replace(/<\/?ul[^>]*>/gi, '\n'); + md = md.replace(/<\/?ol[^>]*>/gi, '\n'); + md = md.replace(/]*>([\s\S]*?)<\/li>/gi, (_, t) => `- ${t.trim()}\n`); + + // Links, emphasis + md = md.replace(/]*href=["']([^"']*)["'][^>]*>([\s\S]*?)<\/a>/gi, '[$2]($1)'); + md = md.replace(/<(strong|b)\b[^>]*>([\s\S]*?)<\/\1>/gi, '**$2**'); + md = md.replace(/<(em|i)\b[^>]*>([\s\S]*?)<\/\1>/gi, '*$2*'); + + // Block + break tags + md = md.replace(//gi, '\n'); + md = md.replace(/<\/p>/gi, '\n\n'); + md = md.replace(/]*>/gi, ''); + + // Strip anything left, decode, tidy + md = md.replace(/<\/?[a-zA-Z][^>]*>/g, ''); + md = decodeEntities(md); + + md = md + .split('\n') + .map((line) => line.replace(/ /g, ' ').replace(/[ \t]+$/g, '').trim()) + .join('\n'); + md = md.replace(/\n{3,}/g, '\n\n'); + // Tighten lists: drop blank lines between consecutive bullets. + md = md.replace(/(^- .*)\n\n(?=- )/gm, '$1\n'); + return md.trim(); +} + +function stripBoilerplate(md) { + const kept = md + .split('\n') + .filter((line) => !BOILERPLATE.some((re) => re.test(line))); + + // Drop a trailing "Resource Links" header left empty after stripping. + while (kept.length) { + const last = kept[kept.length - 1].trim(); + if (last === '' || /^resource links?:?$/i.test(last)) kept.pop(); + else break; + } + return kept.join('\n').replace(/\n{3,}/g, '\n\n').trim(); +} + +// --- Conservative guest extraction ----------------------------------------- +// Ported from scripts/update-podcast-authors.py. High-confidence only; a missed +// guest degrades to no byline, a wrong guest would be a bad byline (ADR 0003). + +const NOT_A_PERSON = /^(?:The|A|An|In|This|For|With|From|On|PowerShell|Microsoft|Windows|Azure|DevOps|Cloud|GitHub|AWS|Episode|Podcast|Session|Roundtable|Community|Tonight|Join|Listen|Watch|Learn|Get|Set|Bar|Summit|Meet|Introducing|Featuring|Welcome|Just)\b/i; + +function looksLikePerson(name) { + if (!name || name.length < 4) return false; + if (NOT_A_PERSON.test(name)) return false; + const words = name.split(/\s+/); + if (words.length < 2) return false; + if (words.filter((w) => /^[A-ZÀ-ɏ]/.test(w)).length < 2) return false; + // Reject emphasis words (ALSO, PLUS) but allow initials like "B." + if (words.some((w) => w.length > 1 && w === w.toUpperCase() && !w.endsWith('.'))) return false; + const low = name.toLowerCase(); + return !['http', 'www.', 'episode', 'podcast', 'powershell', 'microsoft', 'summit'].some((b) => low.includes(b)); +} + +function cleanName(raw) { + return raw + .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') + .replace(/<[^>]+>/g, '') + .replace(/[*_`]/g, '') + .replace(/^["']|["']$/g, '') + .replace(/[.,;:!?]+$/g, '') + .replace(/^(?:MVPs?\s+|Dr\.\s+|Prof\.\s+)/i, '') + .trim(); +} + +// "...with Name", "...with Name1 and Name2" +function guestsFromTitle(title) { + const m = title.match(/\bwith\s+(.+)$/i); + if (!m) return []; + let after = m[1] + .replace(/^(?:MVPs?\s+|special\s+guest\s+host\s+)/i, '') + .replace(/\s*[-–—].*$/, '') + .replace(/!.*$/, ''); + const out = []; + for (let part of after.split(/\s+(?:and|&)\s+/i)) { + part = part.replace(/[,:(\[].*$/, '').trim(); + const words = []; + for (const w of part.split(/\s+/).slice(0, 3)) { + const cw = w.replace(/[!?.]+$/, ''); + if (cw && /^[A-ZÀ-ɏ]/.test(cw)) words.push(cw); + else break; + } + if (words.length >= 2) { + const name = cleanName(words.join(' ')); + if (looksLikePerson(name) && !out.includes(name)) out.push(name); + } + } + return out; +} + +// "Guest Bio:" / "Bio:" header followed by "Name is/works/..." paragraph. +function guestsFromBio(body) { + const out = []; + const hdr = body.match(/^(?:Guest Bio|Bio)\s*:?\s*$/im) || body.match(/(?:Guest Bio|Bio)\s*:/i); + if (!hdr) return out; + const after = body.slice(body.indexOf(hdr[0]) + hdr[0].length); + for (const para of after.split(/\n\s*\n/).slice(0, 2)) { + const m = para + .trim() + .match(/^(?:Dr\.\s+|Prof\.\s+)?([A-ZÀ-ɏ][\w'À-ɏ-]+(?:\s+[A-Z]\.)?(?:\s+[A-ZÀ-ɏ][\w'À-ɏ-]+){1,3})(?=\s+(?:is|was|are|has|works|joined|lives|serves|brings|currently|helps|leads|comes|spent|built|started|founded|created|focuses|specializes|manages|develops|writes|teaches|runs|hosts|holds|received|earned|wrote|published|blogs)\b|\s*,)/); + if (m) { + const name = cleanName(m[1]); + if (looksLikePerson(name) && !out.includes(name)) out.push(name); + } + } + return out; +} + +function extractGuests(title, body) { + const guests = []; + for (const g of [...guestsFromBio(body), ...guestsFromTitle(title)]) { + if (!guests.includes(g) && g !== HOST) guests.push(g); + } + return guests; +} + +// --- YAML ------------------------------------------------------------------ + +// Plain scalar unless the value would break YAML (matches the existing files, +// which leave titles with parens/apostrophes/& unquoted). +function yamlScalar(v) { + const s = String(v); + if (s === '' || /[:#]\s/.test(s) || /[:#]$/.test(s) || /^[\s>|*&!%@`"'\[\]{},]/.test(s)) { + return `"${s.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`; + } + return s; +} + +// --- Existing-file index --------------------------------------------------- + +function buildIndex() { + const idx = { urls: new Set(), guids: new Set(), episodes: new Set() }; + for (const file of fs.readdirSync(PODCAST_DIR)) { + if (!file.endsWith('.md') || file === '_index.md') continue; + const c = fs.readFileSync(path.join(PODCAST_DIR, file), 'utf-8'); + if (!c.includes('mcdn.podbean.com')) continue; // modern (Podbean) episodes only + const url = c.match(/^podcast_url:\s*"?([^"\r\n]+)"?/m); + if (url) idx.urls.add(url[1].trim()); + const guid = c.match(/^guid:\s*"?([^"\r\n]+)"?/m); + if (guid) idx.guids.add(guid[1].trim()); + const ep = c.match(/^episode:\s*(\d+)/m); + if (ep) idx.episodes.add(parseInt(ep[1], 10)); + } + return idx; +} + +// --- Build one episode file ------------------------------------------------ + +function buildEpisode(item) { + const enclosure = attr(item, 'enclosure', 'url').trim(); + if (!enclosure) return null; + + const rawTitle = tag(item, 'title').trim(); + const guidRaw = tag(item, 'guid').trim(); + const pubDate = tag(item, 'pubDate').trim(); + const itunesEp = parseInt(tag(item, 'itunes:episode'), 10) || null; + const contentHtml = tag(item, 'content:encoded') || tag(item, 'description'); + + const episode = resolveEpisode(enclosure, itunesEp); + const { date, iso, y, m } = parseDate(pubDate); + const slug = TITLE_PREFIX.toLowerCase().trim().replace(/\s+/g, '-') + '-' + slugify(rawTitle); + const filename = `${date}-${slug}.md`; + + const ytMatch = contentHtml.match(/youtu\.be\/([A-Za-z0-9_-]{6,})/); + const youtube = ytMatch ? ytMatch[1] : null; + + const body = stripBoilerplate(htmlToMarkdown(contentHtml)); + const guests = extractGuests(rawTitle, body); + const authors = [HOST, ...guests]; + + const fm = []; + fm.push(`title: ${yamlScalar(TITLE_PREFIX + rawTitle)}`); + fm.push(`author: ${yamlScalar(HOST)}`); + fm.push('authors:'); + for (const a of authors) fm.push(` - ${yamlScalar(a)}`); + fm.push(`date: "${iso}"`); + fm.push(`podcast_url: "${enclosure}"`); + if (episode != null) fm.push(`episode: ${episode}`); + if (youtube) fm.push(`youtube: ${youtube}`); + if (guidRaw) fm.push(`guid: ${yamlScalar(guidRaw)}`); + fm.push('aliases:'); + fm.push(` - /${y}/${m}/${slug}/`); + + const content = `---\n${fm.join('\n')}\n---\n\n${body}\n`; + return { filename, content, episode, enclosure, guid: guidRaw, title: rawTitle }; +} + +// --- Main ------------------------------------------------------------------ + +async function main() { + console.log(`Fetching ${FEED_URL} ...`); + const res = await fetch(FEED_URL); + if (!res.ok) throw new Error(`Feed fetch failed: ${res.status} ${res.statusText}`); + const xml = await res.text(); + + const items = xml.match(/[\s\S]*?<\/item>/g) || []; + console.log(`Feed items: ${items.length}`); + + const idx = buildIndex(); + console.log(`Existing modern episodes indexed: urls=${idx.urls.size} guids=${idx.guids.size} episodes=${idx.episodes.size}`); + + let added = 0; + let skipped = 0; + const writes = []; + + for (const item of items) { + const ep = buildEpisode(item); + if (!ep) { skipped++; continue; } + + const exists = + idx.urls.has(ep.enclosure) || + (ep.guid && idx.guids.has(ep.guid)) || + (ep.episode != null && idx.episodes.has(ep.episode)); + if (exists) { skipped++; continue; } + + const dest = path.join(PODCAST_DIR, ep.filename); + if (fs.existsSync(dest)) { skipped++; continue; } + + writes.push(ep); + // Reserve keys so a duplicate item in the same run can't double-write. + idx.urls.add(ep.enclosure); + if (ep.guid) idx.guids.add(ep.guid); + if (ep.episode != null) idx.episodes.add(ep.episode); + } + + writes.sort((a, b) => a.filename.localeCompare(b.filename)); + for (const ep of writes) { + console.log(`${DRY_RUN ? '[dry-run] ' : ''}+ ${ep.filename} (episode ${ep.episode ?? '?'})`); + if (!DRY_RUN) fs.writeFileSync(path.join(PODCAST_DIR, ep.filename), ep.content, 'utf-8'); + added++; + } + + console.log(`\n${DRY_RUN ? 'Would add' : 'Added'}: ${added} Skipped (already present): ${skipped}`); +} + +main().catch((err) => { + console.error('Sync failed:', err); + process.exit(1); +}); diff --git a/.github/workflows/podcast-sync.yml b/.github/workflows/podcast-sync.yml new file mode 100644 index 000000000..c278cd7be --- /dev/null +++ b/.github/workflows/podcast-sync.yml @@ -0,0 +1,38 @@ +name: Sync Podcast Episodes + +on: + schedule: + - cron: '0 12 * * 2' # Tuesdays 12:00 UTC, after the Monday release + workflow_dispatch: + +# The cadence is load-bearing: it must stay well under the window in which an +# episode could roll off the feed. See docs/adr/0003-incremental-podcast-sync.md. + +permissions: + contents: write + +jobs: + sync-podcast: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: Install dependencies + run: npm install node-fetch + + - name: Sync podcast feed + run: node .github/scripts/sync-podcast-feed.js + + - name: Commit new episodes + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add content/podcast + git diff --staged --quiet || git commit -m "Sync new podcast episodes from feed" + git push diff --git a/content/podcast/2026-04-06-the-powershell-podcast-intune-stack-and-the-art-of-showing-up-with-hailey-phillips.md b/content/podcast/2026-04-06-the-powershell-podcast-intune-stack-and-the-art-of-showing-up-with-hailey-phillips.md new file mode 100644 index 000000000..3d05237a6 --- /dev/null +++ b/content/podcast/2026-04-06-the-powershell-podcast-intune-stack-and-the-art-of-showing-up-with-hailey-phillips.md @@ -0,0 +1,33 @@ +--- +title: The PowerShell Podcast Intune Stack and the Art of Showing Up with Hailey Phillips +author: Andrew Pla +authors: + - Andrew Pla + - Hailey Phillips +date: "2026-04-06T14:00:00+00:00" +podcast_url: "https://mcdn.podbean.com/mf/web/nwfkzwyt38p4mtna/The_PowerShell_Podcast_episode_221_Hailey_Phillips_28w47h.mp3" +episode: 221 +youtube: L97ePN7UtGY +guid: powershellpodcast.podbean.com/a1895070-d4c2-3ebc-80a4-0e517b95f286 +aliases: + - /2026/04/the-powershell-podcast-intune-stack-and-the-art-of-showing-up-with-hailey-phillips/ +--- + +Andrew welcomes back Dual MVP and Intune aficionado Hailey Phillips for a wide-ranging conversation covering her project IntuneStack, the value of DevOps principles in endpoint management, and the mindset behind consistent skill-building. The two dig into conference culture, the importance of community, mentorship, and why showing up every day — even for just ten minutes — matters more than waiting for inspiration to strike. + +Key Takeaways: + +- IntuneStack in action: Hailey's CI/CD-influenced PowerShell project manages Intune policy deployment across dev, test, and prod groups using promotion gates rather than expensive separate tenants — a more resilient, consistent, and auditable approach to endpoint management. +- Consistency over inspiration: Whether it's PowerShell, the gym, or mentoring, Hailey's philosophy is the same: stop waiting to feel motivated and just start small. Ten minutes a day compounds over time, and momentum is something you build, not something you wait for. +- Community is a career asset: Conferences like PowerShell Summit and PSConfEU aren't just about the sessions — they're about building a support system. Having people who can sanity-check your thinking is one of the most underrated advantages in a tech career. + +Guest Bio: + +Hailey Phillips is a Systems Engineer, Microsoft MVP, and *Professional Pokémon Trainer*. She specializes in automation, endpoint management, and modern workplace strategy, bridging the gap between traditional IT and DevOps. Hailey’s work focuses on building pragmatic, scalable solutions using tools like PowerShell, Microsoft Graph, Intune, and Azure Arc. When she’s not deep in tech, you’ll probably find her skiing in the Cascades, lifting heavy things, or at a metalcore show with a strong cup of coffee in hand. + +Resource Links: + +- Intune Stack on GitHub - [https://github.com/AllwaysHyPe/IntuneStack](https://github.com/AllwaysHyPe/IntuneStack) +- Practical Automation with PowerShell by Matthew Dost - [https://www.manning.com/books/practical-automation-with-powershell](https://www.manning.com/books/practical-automation-with-powershell) +- GliderUI Cross-platform GUIs - [https://github.com/mdgrs-mei/GliderUI](https://github.com/mdgrs-mei/GliderUI) +- Hailey Phillips Website - [https://www.allwayshype.com/](https://www.allwayshype.com/) diff --git a/content/podcast/2026-04-13-the-powershell-podcast-powershell-wisdom-from-35-years-in-the-trenches-with-jeff-hicks.md b/content/podcast/2026-04-13-the-powershell-podcast-powershell-wisdom-from-35-years-in-the-trenches-with-jeff-hicks.md new file mode 100644 index 000000000..b95cfaec3 --- /dev/null +++ b/content/podcast/2026-04-13-the-powershell-podcast-powershell-wisdom-from-35-years-in-the-trenches-with-jeff-hicks.md @@ -0,0 +1,33 @@ +--- +title: The PowerShell Podcast PowerShell Wisdom from 35 Years in the Trenches with Jeff Hicks +author: Andrew Pla +authors: + - Andrew Pla + - Jeff Hicks +date: "2026-04-13T14:00:00+00:00" +podcast_url: "https://mcdn.podbean.com/mf/web/n7733z4v3hdh4bzt/The_PowerShell_Podcast_episode_222_Jeff_Hicks8fs2p.mp3" +episode: 222 +youtube: ceB-3QGbvBA +guid: powershellpodcast.podbean.com/a18d655c-b5f5-3717-8661-0fc2b63e02cf +aliases: + - /2026/04/the-powershell-podcast-powershell-wisdom-from-35-years-in-the-trenches-with-jeff-hicks/ +--- + +With PowerShell + DevOps Global Summit 2026 opening this Monday, April 13th, this episode brings back one of the most respected names in the PowerShell community: Jeff Hicks. Andrew sits down with Jeff to dig into what makes the Summit special, the organic community that grew from those earliest events, and what it actually feels like to watch people go from struggling beginners to confident PowerShell practitioners. They also get into the big question hanging over everyone in IT right now: what does AI actually mean for the future of PowerShell professionals? Jeff shares his take on the "squishy bits" of scripting that AI still can't replicate, why learning the core PowerShell paradigm matters more than ever, and how he personally uses AI as a collaborator rather than a shortcut. It's a conversation about community, craft, and what it means to actually know your tools. + +Key Takeaways: + +- Learn the foundation first, tools second. Jeff's consistent message over decades of teaching: don't start with Azure commands or specific modules. Start with the PowerShell paradigm — objects, the pipeline, managing at scale — and the rest becomes much easier to pick up over time. +- AI is a co-pilot, not a replacement. Jeff uses AI to get over specific technical hurdles, not to generate finished code. His concern isn't that AI will write bad scripts — it's that the next generation may skip the foundational learning that lets you recognize when AI gets it wrong. +- The PowerShell community is genuinely welcoming, and showing up matters. Whether it's Summit, a local user group, or Discord, getting into rooms with other PowerShell people can be a career changer. The hallway conversations are half the value. + +Guest Bio: + +Jeff Hicks is a veteran IT professional with 35 years of experience, a long-time Microsoft MVP, and one of the most recognized voices in the PowerShell community. He's the author and co-author of several foundational PowerShell books, a Pluralsight course creator, and the publisher of the premium newsletter *Behind the PowerShell Pipeline*. He's been teaching and writing about PowerShell since the very beginning and continues to focus on the human side of scripting — the parts that go beyond syntax and into craft. + +Resource Links: + +- Jeff Hicks' hub (links to everything): [https://jdhitsolutions.github.io](https://jdhitsolutions.github.io/) +- Behind the PowerShell Pipeline (newsletter & book on Leanpub): [https://leanpub.com/behind-the-pspipeline](https://leanpub.com/behind-the-pspipeline) +- Jeff's Pluralsight courses: [https://app.pluralsight.com/profile/author/jeff-hicks](https://app.pluralsight.com/profile/author/jeff-hicks) +- PowerShell Wednesday (weekly on PDQ's YouTube/Discord): [https://www.youtube.com/watch?v=5vdfFswmREQ&list=PL1mL90yFExsix-L0havb8SbZXoYRPol0B&pp=0gcJCbcEOCosWNin](https://www.youtube.com/watch?v=5vdfFswmREQ&list=PL1mL90yFExsix-L0havb8SbZXoYRPol0B&pp=0gcJCbcEOCosWNin) diff --git a/content/podcast/2026-04-20-the-powershell-podcast-the-powershell-summit-hallway-track-with-gilbert-sanchez-and-joshua-dearing.md b/content/podcast/2026-04-20-the-powershell-podcast-the-powershell-summit-hallway-track-with-gilbert-sanchez-and-joshua-dearing.md new file mode 100644 index 000000000..af3cf43d8 --- /dev/null +++ b/content/podcast/2026-04-20-the-powershell-podcast-the-powershell-summit-hallway-track-with-gilbert-sanchez-and-joshua-dearing.md @@ -0,0 +1,41 @@ +--- +title: The PowerShell Podcast The PowerShell Summit Hallway Track with Gilbert Sanchez and Joshua Dearing +author: Andrew Pla +authors: + - Andrew Pla + - Gilbert Sanchez + - Joshua Dearing +date: "2026-04-20T14:00:00+00:00" +podcast_url: "https://mcdn.podbean.com/mf/web/wzrpgen5m7un4zgf/The_PowerShell_Podcast_episode_223_Summit_Gilbert_and_Josh6bai9.mp3" +episode: 223 +youtube: XJAbZgOVMF4 +guid: powershellpodcast.podbean.com/e9a9e123-dc87-3c3f-b988-d10f9c8c4a10 +aliases: + - /2026/04/the-powershell-podcast-the-powershell-summit-hallway-track-with-gilbert-sanchez-and-joshua-dearing/ +--- + +This episode captures the energy of PowerShell Summit through two conversations, one with Gilbert Sanchez and one with Joshua Dearing. The discussion moves from open source maintenance and the future of PowerShell in AI workflows to the human side of technical communities, including burnout, neurodiversity, mentorship, and the value of showing up in person. It also highlights how PowerShell can change careers over time, not just by teaching syntax, but by opening doors to better communication, stronger community ties, and bigger technical thinking. + +Key Takeaways: + +· Community is often the unlock, not just the tooling. Both conversations reinforce that Summit’s real value is the people, the hallway conversations, and the sense that learning gets easier when you have others around you who are willing to help. + +· Sustainable technical growth matters more than short bursts of output. Gilbert talks about burnout, open source maintenance, and creating healthier ways to contribute, while Andrew connects that to ADHD, mental health, and building a career that can last. + +· PowerShell is a starting point for much bigger opportunities. Joshua’s story, from community member to module author, reflects a broader theme in the episode that small steps, taken consistently, can completely reshape what kind of work you can do and who you can become in the field. + +Guest Bio: + +Gilbert Sanchez is a Staff Software Development Engineer at Tesla, specifically working on PowerShell. Formerly known as "Señor Systems Engineer" at Meta. A loud advocate for DEI, DevEx, DevOps, and TDD. + +Resource Links: + +· PSake: [https://psake.dev](https://psake.dev) + +· Gilbert Sanchez links: [https://links.gilbertsanchez.com](https://links.gilbertsanchez.com) + +· Gilbert Sanchez blog: [https://gilbertsanchez.com](https://gilbertsanchez.com) + +Josh is a systems administrator with a philosophy degree and a helpdesk origin story. He's a speaker, open source contributor, creator of ModuleExplorer, and a PDQ Sysadmin Hall of Fame winner. He's a firm believer that the best script is the one you don't keep to yourself. + +· Joshua Dearing's website: [https://dearing.dev](https://dearing.dev) diff --git a/content/podcast/2026-04-23-the-powershell-podcast-powershell-devops-global-summit-bar-session-with-brian-quinn-scott.md b/content/podcast/2026-04-23-the-powershell-podcast-powershell-devops-global-summit-bar-session-with-brian-quinn-scott.md new file mode 100644 index 000000000..b2c9994a0 --- /dev/null +++ b/content/podcast/2026-04-23-the-powershell-podcast-powershell-devops-global-summit-bar-session-with-brian-quinn-scott.md @@ -0,0 +1,18 @@ +--- +title: The PowerShell Podcast PowerShell & DevOps Global Summit Bar session with Brian Quinn & Scott +author: Andrew Pla +authors: + - Andrew Pla + - Brian Quinn +date: "2026-04-23T14:00:00+00:00" +podcast_url: "https://mcdn.podbean.com/mf/web/2iuc6vh7dgstkzqa/The_PowerShell_Podcast_episode_224_Bar_seesion_Brian_Scott7rrf3.mp3" +episode: 224 +youtube: akrQSKoKjDI +guid: powershellpodcast.podbean.com/fef1839e-f013-3d8e-8615-be19118c8584 +aliases: + - /2026/04/the-powershell-podcast-powershell-devops-global-summit-bar-session-with-brian-quinn-scott/ +--- + +At the PowerShell and DevOps Global Summit, this after-dark bar session blends casual conversation with a real sense of why the event matters. Brian Quinn talks about returning for his second Summit, filling in PowerShell fundamentals, and bringing back practical skills like remoting, advanced functions, modules, testing, and version control to improve how his team handles identity and access management. + +Scott Lemonde reflects on what keeps drawing him back, not just the technical knowledge, but the community, the friendships, and the way Summit gives people confidence, perspective, and momentum in their careers. Across both conversations, the theme is clear: PowerShell is not just a tool, it is a shared journey of growth, automation, problem-solving, and finding your people in a field that can otherwise feel pretty isolating. diff --git a/content/podcast/2026-04-27-the-powershell-podcast-from-event-logs-to-ai-workflows-with-lucas-allman.md b/content/podcast/2026-04-27-the-powershell-podcast-from-event-logs-to-ai-workflows-with-lucas-allman.md new file mode 100644 index 000000000..c44b1d1c6 --- /dev/null +++ b/content/podcast/2026-04-27-the-powershell-podcast-from-event-logs-to-ai-workflows-with-lucas-allman.md @@ -0,0 +1,34 @@ +--- +title: The PowerShell Podcast From Event Logs to AI Workflows with Lucas Allman +author: Andrew Pla +authors: + - Andrew Pla + - Lucas Allman +date: "2026-04-27T14:00:00+00:00" +podcast_url: "https://mcdn.podbean.com/mf/web/bzpb3zc8jj9wkj5j/The_Powershell_Podcast_episode_225_Lucas_Allmanalpkz.mp3" +episode: 225 +youtube: kcjkCS0QN64 +guid: powershellpodcast.podbean.com/e40511b7-1482-374b-811a-323885008a3b +aliases: + - /2026/04/the-powershell-podcast-from-event-logs-to-ai-workflows-with-lucas-allman/ +--- + +Lucas Allman joins the PowerShell Podcast for a conversation that starts with practical beginner wins and builds into bigger questions about AI, learning, community, and career growth in IT. The episode covers hands-on PowerShell use cases like event logs, scheduled tasks, and writing functions directly in the terminal, then shifts into Lucas’s experience as a first-time PowerShell Summit speaker and his evolving perspective on AI as a tool for both productivity and learning. It lands on a strong human note, with Lucas reflecting on impostor syndrome, keeping up with change, and why curiosity and community still matter just as much as technical skill. + +Key Takeaways: + +· Event logs are a great early PowerShell win. Lucas walks through using Get-WinEvent to explore logs, filter for errors, search messages, and troubleshoot faster without waiting on the Event Viewer GUI. He also shares a practical tip for reusing XML or XPath filters from Event Viewer inside PowerShell scripts. + +· You can do more from the terminal than most people realize. Lucas explains how he writes full functions directly in the interactive shell, then saves them with a custom helper function so good code does not disappear when the session closes. It is a simple idea, but it opens the door to faster experimentation and building tools in the flow of work. + +· AI is changing how technical people work, but not eliminating the need for judgment. A big part of the Summit discussion centered on using AI as a collaborator, not a replacement. Lucas argues that the real opportunity is to offload repetitive work, learn faster, and free up more time for higher-value problem solving, while still applying technical knowledge and critical thinking to the results. + +Guest Bio: + +Lucas Allman is an IT automation specialist with a passion for building practical, scalable solutions using PowerShell. With deep experience in endpoint management, configuration as code, and Microsoft cloud services like Intune and Graph API, Lucas focuses on making complex workflows maintainable, secure, and efficient. He’s an advocate for knowledge sharing and enjoys helping others level up their scripting and automation skills through real-world examples and interactive problem-solving. He had ChatGPT write this bio and says it’s close enough. + +Resource Links: + +· Lucas Allman website: [https://lucasallman.com](https://lucasallman.com) + +· PowerShell.org GitHub organization: [https://github.com/powershellorg](https://github.com/powershellorg) diff --git a/content/podcast/2026-04-29-the-powershell-podcast-powershell-devops-global-summit-bar-session-with-josh-jeff.md b/content/podcast/2026-04-29-the-powershell-podcast-powershell-devops-global-summit-bar-session-with-josh-jeff.md new file mode 100644 index 000000000..228b3b5a5 --- /dev/null +++ b/content/podcast/2026-04-29-the-powershell-podcast-powershell-devops-global-summit-bar-session-with-josh-jeff.md @@ -0,0 +1,17 @@ +--- +title: The PowerShell Podcast PowerShell & DevOps Global Summit Bar session with Josh & Jeff +author: Andrew Pla +authors: + - Andrew Pla +date: "2026-04-29T14:00:00+00:00" +podcast_url: "https://mcdn.podbean.com/mf/web/bsf7fnxjaz4cbm32/The_PowerShell_Podcast_episode_226_Bar_session_Josh_Jeffa9m5m.mp3" +episode: 226 +youtube: NyT_A1hSH_M +guid: powershellpodcast.podbean.com/be20331e-0018-357f-848a-d0b04cad11bb +aliases: + - /2026/04/the-powershell-podcast-powershell-devops-global-summit-bar-session-with-josh-jeff/ +--- + +This episode of the PowerShell Podcast After Dark captures two candid bar-session conversations from the PowerShell and DevOps Global Summit, centered on community, career growth, and the real-world value of putting yourself out there. In the first segment, Josh Dearing talks about attending his first Summit, building PowerShell modules, learning from failure, and using automation to improve systems and processes in higher education. + +In the second, Jeff Wardlaw reflects on finally attending the event in person, the impact of meeting the people behind the tools and community, and the broader lessons around perspective, technical leadership, communication, and problem-solving. Across both conversations, the theme is clear, PowerShell is not just a toolset, it is a way into a generous technical community where curiosity, experimentation, and shared learning can meaningfully shape a career. diff --git a/content/podcast/2026-05-04-the-powershell-podcast-from-ise-anxiety-to-vs-code-every-day-with-paula-kingsley.md b/content/podcast/2026-05-04-the-powershell-podcast-from-ise-anxiety-to-vs-code-every-day-with-paula-kingsley.md new file mode 100644 index 000000000..560a4c5c5 --- /dev/null +++ b/content/podcast/2026-05-04-the-powershell-podcast-from-ise-anxiety-to-vs-code-every-day-with-paula-kingsley.md @@ -0,0 +1,33 @@ +--- +title: The PowerShell Podcast From ISE Anxiety to VS Code Every Day with Paula Kingsley +author: Andrew Pla +authors: + - Andrew Pla + - Paula Kingsley +date: "2026-05-04T14:00:00+00:00" +podcast_url: "https://mcdn.podbean.com/mf/web/9czrexzxa37njccw/The_PowerShell_Podcast_episode_227_Paula_Kingsley85o0v.mp3" +episode: 227 +youtube: WLNVCW7S8BE +guid: powershellpodcast.podbean.com/d63ede3f-e8ca-3b20-809a-8280ac95ae35 +aliases: + - /2026/05/the-powershell-podcast-from-ise-anxiety-to-vs-code-every-day-with-paula-kingsley/ +--- + +Paula Kingsley, a senior IT leader, longtime consultant, automation and PowerShell enthusiast, eight-time Microsoft MVP for Exchange Server, and happy generalist, joins Andrew for a wide-ranging conversation about her tech journey and what it actually looks like to grow from deep hands-on work into technology leadership. They kick things off with a topic near and dear to a lot of PowerShell folks: the ISE-to-VS Code migration. Paula was terrified of it, put it off for as long as she could, and now uses VS Code every single day. + +From there, the conversation opens up into what consulting taught her about solving problems, how being a generalist can be a genuine advantage, why documentation and communication matter as much as technical skill, and what it means to keep the human side of technology alive as you move up. Paula also drops some solid practical PowerShell wisdom along the way, from always including WhatIf support in your functions to the very important reminder that Get is safe and Set is something else entirely. + +Key Takeaways: + +- Making the jump from ISE to VS Code feels daunting, but the move is absolutely worth it. The secret is forcing yourself to open it first and just leaving it open until the habit takes hold. +- Being a generalist isn't a weakness. The ability to see across systems, communicate up and down, and translate technical work into business outcomes is a real and undervalued skill. +- Always build yourself an escape route. WhatIf and ShouldProcess aren't just best practices, they're the difference between a confident deployment and a very bad afternoon. + +Guest Bio: + +Paula Kingsley is an outcome-driven senior IT leader, technology operations and engineering expert, eight-time Microsoft MVP for Exchange Server, and self-described happy generalist. Her path into tech started with a liberal arts degree and eventually led through boutique IT consulting, enterprise infrastructure, global production operations, automation, cloud, AI, and a deep appreciation for PowerShell. Paula has built her career around solving problems, simplifying workflows, removing friction, and helping technical teams work better at scale. She is senior enough to shape strategy and steer practices, still hands-on enough to fix things herself, and yes, she even likes regex. You can find her on GitHub as lanwench and on LinkedIn. + +Resource Links: + +- Paula Kingsley on LinkedIn – [https://www.linkedin.com/in/paulakingsley/](https://www.linkedin.com/in/paulakingsley/) +- Paula Kingsley on GitHub – [https://github.com/lanwench](https://github.com/lanwench) diff --git a/content/podcast/2026-05-11-the-powershell-podcast-splatting-automation-and-chasing-the-sun-with-jess-pomfret.md b/content/podcast/2026-05-11-the-powershell-podcast-splatting-automation-and-chasing-the-sun-with-jess-pomfret.md new file mode 100644 index 000000000..0893c1158 --- /dev/null +++ b/content/podcast/2026-05-11-the-powershell-podcast-splatting-automation-and-chasing-the-sun-with-jess-pomfret.md @@ -0,0 +1,40 @@ +--- +title: The PowerShell Podcast Splatting, Automation, and Chasing the Sun with Jess Pomfret +author: Andrew Pla +authors: + - Andrew Pla + - Jess Pomfret +date: "2026-05-11T14:00:00+00:00" +podcast_url: "https://mcdn.podbean.com/mf/web/58srrrm2m2e6279x/The_PowerShell_Podcast_episode_228_Jess_Pomfretaryc1.mp3" +episode: 228 +youtube: M2XvvCKs1Ls +guid: powershellpodcast.podbean.com/86e92779-af7a-3378-82bc-ee4a4580f654 +aliases: + - /2026/05/the-powershell-podcast-splatting-automation-and-chasing-the-sun-with-jess-pomfret/ +--- + +Jess Pomfret returns for her third appearance on the PowerShell Podcast and brings the same energy that keeps people coming back. She and Andrew cover a lot of ground, starting with her upcoming "Chase the Sun" charity cycling event where she'll attempt to ride 205 miles coast-to-coast across the UK in a single day, starting at sunrise on the longest day of the year and racing the sun to the finish line. It's a big undertaking, and she's riding to raise money for Momentum in Fitness, a charity her wife works for that brings fitness opportunities to older adults, kids in non-traditional school settings, and children with cancer. + +On the technical side, Jess makes the case for PowerShell splatting as an underrated beginner concept that makes code dramatically more readable. She walks through the idea of pulling parameters out of a long command line, organizing them into a hash table, and passing that hash table to the command instead. It's one of those things experienced scripters take for granted, but seeing it for the first time is genuinely useful. + +The conversation also gets into Desired State Configuration (DSC), where Andrew and Jess dig into what it is, how it works, and why it matters for sysadmins who want to maintain consistent configuration across their environments. Jess also opens up about managing a packed schedule between her day job, speaking, podcasting, LinkedIn Learning courses, and serious bike training. Her answer is honest and relatable: she's still figuring it out, but Todoist and a very supportive partner help a lot. + +Key Takeaways: + +- Splatting is one of the most readable improvements you can make to your PowerShell code. Instead of chaining parameters into one long command, you load them into a hash table and pass that to your command with an @ symbol. Cleaner to write, easier to read, and especially useful when you're sharing code on a screen. +- DSC lets you define what a system should look like and PowerShell handles the work of getting it (and keeping it) there. It's a mindset shift from scripting manual steps to declaring an end state, and it's particularly powerful in large environments where consistency matters. +- Having a support system is one of the most underrated factors in being able to sustain a high-output career alongside community contributions. Whether it's people around you who help carry the load or finding your people in the data and PowerShell communities, you can't do it alone indefinitely. + +Guest Bio: + +Jess Pomfret is a Data Platform Engineer and a dual Microsoft MVP. She's been working with SQL Server since 2011, is a maintainer on the dbatools open source project, co-host of the Finding Data Friends podcast, and a LinkedIn Learning instructor. She grew up in the south-west of England and now lives in the US. Outside of tech, she's an avid cyclist, padel player, and a devoted fan of proper football. + +Resource Links: + +- Connect with Jess on LinkedIn: [https://www.linkedin.com/in/jpomfret](https://www.linkedin.com/in/jpomfret) +- Jess's blog: [https://jesspomfret.com](https://jesspomfret.com) +- Support Jess's Chase the Sun ride for Momentum in Fitness: [https://www.justgiving.com/page/jess-pomfret](https://www.justgiving.com/page/jess-pomfret) +- Finding Data Friends podcast on YouTube: [https://www.youtube.com/@findingdatafriends/videos](https://www.youtube.com/@findingdatafriends/videos) +- dbatools – PowerShell module for SQL Server automation: [https://dbatools.io](https://dbatools.io) +- Jess's previous episode on the PowerShell Podcast (Ep. 164): [https://powershellpodcast.podbean.com/e/from-proper-football-to-databases-with-jess-pomfret/](https://powershellpodcast.podbean.com/e/from-proper-football-to-databases-with-jess-pomfret/) +- Jess's first appearance on the PowerShell Podcast: [https://powershellpodcast.podbean.com/e/dbatools-with-jess-pomfret/](https://powershellpodcast.podbean.com/e/dbatools-with-jess-pomfret/) diff --git a/content/podcast/2026-05-18-the-powershell-podcast-powershell-after-dark-onramp-iot-and-finding-your-people.md b/content/podcast/2026-05-18-the-powershell-podcast-powershell-after-dark-onramp-iot-and-finding-your-people.md new file mode 100644 index 000000000..6b78e7f5a --- /dev/null +++ b/content/podcast/2026-05-18-the-powershell-podcast-powershell-after-dark-onramp-iot-and-finding-your-people.md @@ -0,0 +1,37 @@ +--- +title: "The PowerShell Podcast PowerShell After Dark: OnRamp, IoT, and Finding Your People." +author: Andrew Pla +authors: + - Andrew Pla +date: "2026-05-18T14:00:00+00:00" +podcast_url: "https://mcdn.podbean.com/mf/web/xqr624gfutsrmqgv/The_PowerShell_Podcast_Bar_sessions_2026_episode_2298xv9d.mp3" +episode: 229 +youtube: Y_GDB0e8xHY +guid: powershellpodcast.podbean.com/7ec40c08-acd7-3729-a542-8105caacda74 +aliases: + - /2026/05/the-powershell-podcast-powershell-after-dark-onramp-iot-and-finding-your-people/ +--- + +It's PowerShell After Dark. Recorded live at the PowerShell & DevOps Global Summit in Bellevue, Washington, host Andrew Pla takes his mic to the hotel bar for a series of candid conversations with attendees. The episode features four guests: Josh Gratton, an OnRamp scholarship recipient whose career pivot to junior systems engineer was fueled by PowerShell and the podcast; Mark Go, a first-time Summit speaker and attendee; Craig Mileham, a fellow podcast listener and Summit first-timer working in higher ed IT; and Matt Zaske, a longtime community member, conference speaker, and IoT enthusiast who ran a Home Assistant lightning demo. What connects all four conversations is the same thread Andrew keeps pulling on: community makes everything better. Beginners belong here. Reach out. Take the risk. Start now. + +Key Takeaways: + +- The OnRamp scholarship program is genuinely life-changing for early-career IT professionals. Josh Gratton's story, from service desk to systems engineer to Summit attendee, is a direct line from PowerShell to career transformation, and it started with applying for a scholarship he poured his heart into. +- Showing up in person changes something. Every guest in this episode described the in-real-life version of the PowerShell community as warmer, more welcoming, and more accessible than they expected. The gap between "online community" and "your people" closes fast when you're in the same room. +- Reaching out is not just encouraged, it's the move. Andrew makes the case clearly: the people who message him, who post in Discord, who ask questions in public, those are the ones he sees succeed. Suffering in silence is optional. So is waiting. + +Guest Bios: + +Josh Gratton is an IT professional who made a mid-career pivot from 15 years in a different field to the service desk, then leveraged PowerShell automation to earn a promotion to his company's systems engineering team. A 2026 OnRamp scholarship recipient, Josh attended his first PowerShell & DevOps Global Summit in Bellevue and left planning to present at a future Summit and bring a colleague along next year. + +Mark Go is an IT professional and active member of the PDQ Discord community who attended the 2026 PowerShell & DevOps Global Summit. He served as Andrew's cameraman during the Summit's After Dark session and is known in the community for his IoT work, including speaking at Summit. He's a returning podcast guest, Powershell Wednesday and Summit speaker. Mark brings a hardware-forward perspective to PowerShell, with interests in soldering and embedded systems. + +Craig Mileham is a PowerShell Podcast listener and Summit first-timer who works for an MSP in the higher ed space. He attended this year's Summit to absorb as much as possible and left energized to build internal tools for his help desk team and share what he learned at PowerShell Wednesday. This guy is really awesome + +Matt Zaske is an IT professional, conference speaker, and community member based in Minnesota. A regular presence at events like MMS, Matt is also an avid Home Assistant enthusiast who bridges the gap between PowerShell and IoT hardware. He ran a lightning demo at the 2026 Summit, taught attendees how to solder, and blogs regularly at [mzonline.com](http://mzonline.com). You can also find him on LinkedIn and Bluesky. 3d printing legend. GET ON HIS LEVEL + +Resource Links: + +- The PowerShell Podcast on [PDQ.com](http://PDQ.com): [https://www.pdq.com/resources/the-powershell-podcast/](https://www.pdq.com/resources/the-powershell-podcast/) +- PDQ Careers: [https://www.pdq.com/jobs/](https://www.pdq.com/jobs/) +- Matt Zaske's Blog: [https://www.mzonline.com](https://www.mzonline.com) diff --git a/content/podcast/2026-05-25-the-powershell-podcast-solving-problems-at-the-root-with-mark-littlefield.md b/content/podcast/2026-05-25-the-powershell-podcast-solving-problems-at-the-root-with-mark-littlefield.md new file mode 100644 index 000000000..1ded3c85a --- /dev/null +++ b/content/podcast/2026-05-25-the-powershell-podcast-solving-problems-at-the-root-with-mark-littlefield.md @@ -0,0 +1,40 @@ +--- +title: The PowerShell Podcast Solving Problems at the Root with Mark Littlefield +author: Andrew Pla +authors: + - Andrew Pla + - Mark Littlefield +date: "2026-05-25T14:00:00+00:00" +podcast_url: "https://mcdn.podbean.com/mf/web/6ymwa6ywqcw87ctk/The_PowerShell_Podcast_episode_230_Mark_Littlefieldasrzn.mp3" +episode: 230 +youtube: fo2V5LC-EZo +guid: powershellpodcast.podbean.com/fec8f163-1e75-3a7a-a04c-05aa831f4352 +aliases: + - /2026/05/the-powershell-podcast-solving-problems-at-the-root-with-mark-littlefield/ +--- + +In this episode, host Andrew Pla sits down with Mark Littlefield, VP of Product at PDQ, for a wide-ranging conversation about product management, the PowerShell community, and what it looks like to deeply learn a technical domain when you're not coming from a traditional sysadmin background. Mark shares his journey from tech support to product management, what drew him to PDQ and the challenges facing IT admins, and what surprised him about PowerShell once he started paying close attention. The two also dig into the history behind PDQ Connect's PowerShell Scanner, how product teams learn from customers, the art of storytelling as a PM and sysadmin skill, and more. + +Key Takeaways: + +- Product management and PowerShell automation share a core philosophy: solve problems at the root, not just on the surface. Whether you're writing a script or building a feature, the goal is to eliminate a challenge entirely rather than patch around it. +- Understanding your customer requires more than data — it requires immersion. Mark describes going deep into the sysadmin world through customer interviews, internal usage, and community engagement to truly understand the problems facing IT teams. +- Great storytelling is a transferable skill. Andrew draws a parallel between how Jeffrey Snover used the Monad Manifesto to get internal buy-in at Microsoft and how to use narrative to align teams and push ideas forward. + +Guest Bio: + +Mark Littlefield is the VP of Product at PDQ, where he leads product strategy and development for PDQ Connect and the broader PDQ product suite. With over 15 years of product management experience, Mark previously served as VP of Product Management at [InsideSales.com](http://InsideSales.com), where he oversaw product management and design across the platform. He holds a Bachelor of Science in Information Systems with a focus on Business Intelligence from Utah Valley University and is based in Salt Lake City, Utah. + +Resource Links: + +PowerShell Event: [https://www.pdq.com/save-time-with-powershell-pdq-connect/](https://www.pdq.com/save-time-with-powershell-pdq-connect/) + +PDQ Connect: [https://www.pdq.com/pdq-connect/](https://www.pdq.com/pdq-connect/) + +PDQ PowerShell Scanners GitHub repository: [https://github.com/pdqcom/PowerShell-Scanners](https://github.com/pdqcom/PowerShell-Scanners) + +The Monad Manifesto (Microsoft Learn): [https://learn.microsoft.com/en-us/powershell/scripting/developer/monad-manifesto?view=powershell-7.5](https://learn.microsoft.com/en-us/powershell/scripting/developer/monad-manifesto?view=powershell-7.5) + +Monad Manifesto blog post by Jeffrey Snover: [https://devblogs.microsoft.com/powershell/monad-manifesto-the-origin-of-windows-powershell/](https://devblogs.microsoft.com/powershell/monad-manifesto-the-origin-of-windows-powershell/) + +Mark Littlefield on LinkedIn: [https://www.linkedin.com/in/mark-littlefield/](https://www.linkedin.com/in/mark-littlefield/) diff --git a/content/podcast/2026-06-01-the-powershell-podcast-betting-on-yourself-with-frank-lesniak.md b/content/podcast/2026-06-01-the-powershell-podcast-betting-on-yourself-with-frank-lesniak.md new file mode 100644 index 000000000..3c86643e0 --- /dev/null +++ b/content/podcast/2026-06-01-the-powershell-podcast-betting-on-yourself-with-frank-lesniak.md @@ -0,0 +1,52 @@ +--- +title: The PowerShell Podcast Betting on Yourself with Frank Lesniak +author: Andrew Pla +authors: + - Andrew Pla + - Frank Lesniak +date: "2026-06-01T14:00:00+00:00" +podcast_url: "https://mcdn.podbean.com/mf/web/d6iaaxpfrwi6gfme/The_PowerShell_Podcast_episode_231_Frank_Lesniak6tsje.mp3" +episode: 231 +youtube: Eg-uEGaurmY +guid: powershellpodcast.podbean.com/a5c2a515-d435-3056-b16d-f71826b834d1 +aliases: + - /2026/06/the-powershell-podcast-betting-on-yourself-with-frank-lesniak/ +--- + +Frank Lesniak joins Andrew Pla for a wide-ranging conversation that covers Frank's newly minted Microsoft MVP status, his journey through PowerShell, and what it looks like to build a real presence in the tech community. Frank talks through the pipeline struggles that tripped him up early on, how his VB Script and object-oriented background made the shift to PowerShell's object model feel disorienting, and how AI has quietly changed the way he approaches scripting today. The conversation takes a thoughtful turn as Andrew and Frank dig into impostor syndrome, the value of conference speaking, and how showing up consistently in the community compounds into a career. Frank also shares an update on DuPage Animal Friends, the nonprofit he serves, which supports one of the country's highest-performing open-admission animal shelters. + +Key Takeaways: + +- The PowerShell pipeline is one of the most commonly cited stumbling blocks for newcomers, especially those coming from text-based scripting backgrounds. Learning to visualize what your objects look like at each stage of the pipeline, using tools like Get-Member, is a skill that pays dividends long term. +- Showing up at conferences and user groups, even when you feel underprepared, is how you build the reps that eventually make it feel natural. Frank's consulting background gave him a head start on presentation skills, and he's clear that no one is born polished. +- Community involvement and career growth are more connected than they might look from the outside. Engaging with people on GitHub, at events, and through open source creates a feedback loop that builds confidence and opens doors. + +Guest Bio: + +Frank Lesniak returns to The PowerShell Podcast, this time as a Microsoft MVP (Microsoft Azure, PowerShell). Frank is a Sr. Cybersecurity & Enterprise Technology Architect at West Monroe, where PowerShell runs through client work on corporate M&A: carve-outs, tenant-to-tenant migrations, identity consolidation, endpoint moves, and security posture improvement across Microsoft 365, Azure, Entra ID, Active Directory, Intune, Defender, and Windows. + +Beyond consulting, Frank speaks at technical conferences, mentors first-time speakers, and publishes open-source PowerShell standards and tooling, including PSStyleGuide, GloryRole, and PSConnMon. His public work threads least-privilege identity, cloud role mining, cross-platform observability, and high-quality AI-assisted development through standards, automated tests, and automated code quality reviews. + +Connect with Frank: [https://linktr.ee/franklesniak](https://linktr.ee/franklesniak) + +PSConnMon - PowerShell Network Monitoring - [https://github.com/franklesniak/PSConnMon/](https://github.com/franklesniak/PSConnMon/) + +GloryRole - Automating Least-Privlege Azure and Entra ID Directory Roles - [https://gloryrole.com](https://gloryrole.com) + +PowerShell Style Guide - [https://github.com/franklesniak/PSStyleGuide](https://github.com/franklesniak/PSStyleGuide) + +PowerShell Style Guide + Coding Agents Lightning Talk - [https://github.com/devops-collective-inc/pshsummit26/tree/main/PowerShellStyleGuideForCodingAgentsAndHumans-Lesniak](https://github.com/devops-collective-inc/pshsummit26/tree/main/PowerShellStyleGuideForCodingAgentsAndHumans-Lesniak) + +Coding Agent Accelerator Template Repo (Coming Soon!) - [https://github.com/franklesniak/copilot-repo-template](https://github.com/franklesniak/copilot-repo-template) + +ProStateKit - the DSC v3-Intune Starter Kit - [https://github.com/franklesniak/ProStateKit](https://github.com/franklesniak/ProStateKit) + +ProStateKit Promotional Commercial - [https://www.youtube.com/watch?v=cA5vMH522F0](https://www.youtube.com/watch?v=cA5vMH522F0) + +macOSLab - Automating Legit macOS VMs - [https://github.com/franklesniak/macOSLab](https://github.com/franklesniak/macOSLab) + +DuPage Animal Friends - [https://www.dupageanimalfriends.org/](https://www.dupageanimalfriends.org/) + +The PowerShell Podcast: [https://www.pdq.com/resources/the-powershell-podcast/](https://www.pdq.com/resources/the-powershell-podcast/) + +Previous episodes with Frank Lesniak: [https://powershellpodcast.podbean.com/?s=Frank+Lesniak](https://powershellpodcast.podbean.com/?s=Frank+Lesniak) diff --git a/content/podcast/2026-06-08-the-powershell-podcast-cookie-monster-has-entered-the-teams-chat-with-miriam-wiesner.md b/content/podcast/2026-06-08-the-powershell-podcast-cookie-monster-has-entered-the-teams-chat-with-miriam-wiesner.md new file mode 100644 index 000000000..0eeb5a8ef --- /dev/null +++ b/content/podcast/2026-06-08-the-powershell-podcast-cookie-monster-has-entered-the-teams-chat-with-miriam-wiesner.md @@ -0,0 +1,40 @@ +--- +title: The PowerShell Podcast Cookie Monster Has Entered the Teams Chat with Miriam Wiesner +author: Andrew Pla +authors: + - Andrew Pla + - Miriam Wiesner +date: "2026-06-08T14:00:00+00:00" +podcast_url: "https://mcdn.podbean.com/mf/web/eszch6eqngjwmfuc/The_PowerShell_Podcast_episode_232_PSConfEU_Miriam90dei.mp3" +episode: 232 +youtube: zxJOqcEwgWE +guid: powershellpodcast.podbean.com/f334613e-cce2-32d7-86ad-618b8daaee1a +aliases: + - /2026/06/the-powershell-podcast-cookie-monster-has-entered-the-teams-chat-with-miriam-wiesner/ +--- + +Recorded live at PSConfEU 2026, Andrew sits down with returning guest Miriam Wiesner, Senior Security Researcher at Microsoft, for a wide-ranging conversation on PowerShell security, cookie-based attacks, and the evolving threat landscape. Miriam walks through her two conference talks — one on Microsoft Teams session cookie hijacking (a follow-up to her 2025 Entra ID cookie talk, complete with Cookie Monster branding and actual handcuffs), and a joint session with Stéphane van Gulick on using Microsoft Defender's Live Response feature for incident investigation. The conversation also covers the current state of PowerShell security, why sophisticated attackers are moving away from PowerShell, and why defenders who haven't enabled script block logging and AMSI are leaving easy wins on the table. On top of the technical deep dive, Miriam and Andrew get into the human side of the conference community — nerves before presenting, imposter syndrome, and why showing up is already half the battle. + +Key Takeaways: + +- Cookie-based identity attacks are an active and growing threat. Microsoft Teams, SharePoint, and OneDrive share session cookies, meaning a single cookie theft can give an attacker broad access across your organization's collaboration tools — no re-authentication required. +- Sophisticated threat actors are moving away from PowerShell specifically because its security features work. Script block logging, AMSI, and Constrained Language Mode make PowerShell activity highly visible and detectable. If your org hasn't enabled these, you're handing attackers an easy path. +- Visibility beats prevention. You can't prevent what you can't see. Detection through proper logging is not a consolation prize — it's a core security strategy, and Microsoft Defender's Live Response feature gives teams a powerful way to investigate isolated endpoints without needing RDP or PowerShell remoting enabled. + +Guest Bio: + +Miriam Wiesner is a Senior Security Research Program Manager at Microsoft with over 15 years of experience in IT security, penetration testing, and security automation. She works on research behind Microsoft Defender and Sentinel and is the creator of widely used open source PowerShell security tools EventList and JEAnalyzer. Miriam is a sought-after speaker at major security and PowerShell conferences including Black Hat, PSConfEU, and MITRE ATT&CK Workshops. She's also the author of "PowerShell Automation and Scripting for Cybersecurity," published by Packt. Her conference speaker career started at PSConfEU 2018 and she's been a fixture of the community ever since. + +Resource Links + +Miriam's 2025 Cookies talk - [https://www.youtube.com/watch?v=8xDcq0pPNPs](https://www.youtube.com/watch?v=8xDcq0pPNPs) + +Book – PowerShell Automation and Scripting for Cybersecurity (Packt): [https://www.amazon.com/PowerShell-Automation-Scripting-Cybersecurity-Hacking/dp/1800566379](https://www.amazon.com/PowerShell-Automation-Scripting-Cybersecurity-Hacking/dp/1800566379) + +Miriam on LinkedIn: [https://www.linkedin.com/in/miriamwiesner](https://www.linkedin.com/in/miriamwiesner) + +Miriam on X/Twitter: [https://x.com/MiriamXyra](https://x.com/MiriamXyra) + +Miriam's GitHub (EventList, JEAnalyzer, and more): [https://github.com/miriamxyra](https://github.com/miriamxyra) + +Miriam's Website: [https://miriamxyra.com](https://miriamxyra.com) diff --git a/content/podcast/2026-06-15-the-powershell-podcast-powershell-universal-and-the-joy-of-building-with-adriano-carollo.md b/content/podcast/2026-06-15-the-powershell-podcast-powershell-universal-and-the-joy-of-building-with-adriano-carollo.md new file mode 100644 index 000000000..9665f7627 --- /dev/null +++ b/content/podcast/2026-06-15-the-powershell-podcast-powershell-universal-and-the-joy-of-building-with-adriano-carollo.md @@ -0,0 +1,36 @@ +--- +title: The PowerShell Podcast PowerShell Universal and the Joy of Building with Adriano Carollo +author: Andrew Pla +authors: + - Andrew Pla + - Adriano Carollo +date: "2026-06-15T14:00:00+00:00" +podcast_url: "https://mcdn.podbean.com/mf/web/2jkd8chfiijguxsv/The_PowerShell_Podcast_episode_233_Adriano_Carollobsy8r.mp3" +episode: 233 +youtube: qLYqUF9gD9s +guid: powershellpodcast.podbean.com/cb02124e-ece0-323b-9f79-b1cbba7bd022 +aliases: + - /2026/06/the-powershell-podcast-powershell-universal-and-the-joy-of-building-with-adriano-carollo/ +--- + +In this episode, Andrew chats with Adriano Carollo at PSConfEU about community, PowerShell Universal, AI, and what happens when you stop lurking and start talking to people. Adriano shares how PowerShell helped him grow from sysadmin into web apps, automation, and open source-style contribution, while Andrew reflects on learning, AI, and why enthusiasm still matters. + +Key Takeaways: + +· Community accelerates growth. Adriano came to PSConfEU after hearing Andrew encourage listeners to engage, and the payoff was immediate. + +· PowerShell Universal can open unexpected doors. Adriano describes using it daily to learn web development concepts like JavaScript, HTML, and React through PowerShell. + +· AI is most useful when it supports learning instead of replacing it. Both Andrew and Adriano talk about using AI for research, syntax help, documentation, and personal workflows while still valuing hands-on problem solving. + +Guest Bio: + +Adriano Carollo is a Berlin-based system administrator and PowerShell enthusiast who uses PowerShell Universal daily. He is active in the PowerShell Universal Discord community and is exploring automation, web apps, self-hosting, and entrepreneurship. + +Resource Links: + +- PDQ Connect:[https://www.pdq.com/pdq-connect/](https://www.pdq.com/pdq-connect/) +- PowerShell Scanner for PDQ Connect:[https://www.pdq.com/blog/the-powershell-scanner-has-arrived-in-pdq-connect/](https://www.pdq.com/blog/the-powershell-scanner-has-arrived-in-pdq-connect/) +- PowerShell Universal:[https://powershelluniversal.com/](https://powershelluniversal.com/) +- PSConfEU:[https://psconf.eu/](https://psconf.eu/) +- Adriano C. [https://linkedin.com/in/adriano-c-501203213](https://linkedin.com/in/adriano-c-501203213) diff --git a/content/podcast/2026-06-22-the-powershell-podcast-certificates-are-not-optional-with-leo-darcy.md b/content/podcast/2026-06-22-the-powershell-podcast-certificates-are-not-optional-with-leo-darcy.md new file mode 100644 index 000000000..34c02158a --- /dev/null +++ b/content/podcast/2026-06-22-the-powershell-podcast-certificates-are-not-optional-with-leo-darcy.md @@ -0,0 +1,34 @@ +--- +title: The PowerShell Podcast Certificates Are Not Optional with Leo D'Arcy +author: Andrew Pla +authors: + - Andrew Pla + - Leo D'Arcy +date: "2026-06-22T14:00:00+00:00" +podcast_url: "https://mcdn.podbean.com/mf/web/37dvttrnbngivnej/The_PowerShell_Podcast_episode_234_Leo_Darcyb7y8z.mp3" +episode: 234 +youtube: BidUaXtwUNM +guid: powershellpodcast.podbean.com/9bbb1171-951e-38ac-98a8-0327b55484c2 +aliases: + - /2026/06/the-powershell-podcast-certificates-are-not-optional-with-leo-darcy/ +--- + +Andrew sits down with Leo D'Arcy, cloud solutions architect and PSConfEU speaker, to talk certificates, PKI infrastructure, and why so many organizations get it so spectacularly wrong. Leo shares how a decade of consulting work in remote access solutions pulled him into the world of Active Directory Certificate Services whether he liked it or not, and how that hands-on experience turned into conference talks and a genuine specialty. The conversation covers the difference between self-signed certs and proper CA infrastructure, why code signing deserves more attention than it gets, and how integrating signing into a CI/CD pipeline is less painful than it sounds. They also get into the "developer-ization" of IT, the underrated value of consulting experience for career growth, and why communicating across teams is just as important as knowing your PowerShell. + +Key Takeaways: + +- Code signing through a CI/CD pipeline is a practical, scalable alternative to constrained language mode. By adding a signing step to your build process, you get cryptographic proof that scripts haven't been tampered with, without giving up flexibility in what you can run. +- Self-signed certificates are essentially the same as having no certificate at all. A proper PKI means having a chain of trust, a policy behind how certs are issued, and infrastructure that your organization actually manages and maintains. +- Technical depth only gets you so far. The people who advance in IT are the ones who can talk networking with network engineers, infrastructure with server teams, and business outcomes with leadership. Soft skills aren't a bonus, they're a multiplier. + +Guest Bio: + +Leo D'Arcy is a UK-based cloud solutions architect with nearly a decade of consulting background in Microsoft technologies, including Azure, remote access solutions, PKI, and Active Directory Certificate Services. He's a repeat speaker at PSConfEU and runs the Remote Access User Group community on Discord. He's currently focused on Azure landing zone architecture and large-scale PowerShell automation at a stakeholder advisory firm. + +Resource Links: + +- Leo on GitHub: [github.com/ld0614](http://github.com/ld0614) +- PSConfEU: [psconf.eu](http://psconf.eu) +- Leo on Bluesky: [https://bsky.app/profile/leodarcy.bsky.social](https://bsky.app/profile/leodarcy.bsky.social) +- Leo on LinkedIn: [https://www.linkedin.com/in/leodarcy/](https://www.linkedin.com/in/leodarcy/) +- Microsoft Remote Access User Group Discord: [https://discord.aovpndpc.com/](https://discord.aovpndpc.com/) diff --git a/docs/adr/0003-incremental-podcast-sync.md b/docs/adr/0003-incremental-podcast-sync.md index ea7690a61..4b0df0852 100644 --- a/docs/adr/0003-incremental-podcast-sync.md +++ b/docs/adr/0003-incremental-podcast-sync.md @@ -1,5 +1,32 @@ # Podcast sync: incremental RSS tail + one-time backfill, not a feed-driven archive +> **Update (2026-06-22) — the feed is not truncated to 10 items.** When the sync +> was actually built, the live feed +> (`feed.podbean.com/powershellpodcast/feed.xml`) returned the **complete archive +> (234 items, all of The PowerShell Podcast)**, not the 10-item window assumed +> below. This does not change the chosen design — the sync is **add-only** and +> never reconciles or deletes, so a full pass over the feed is safe — but it has +> three consequences: +> +> 1. **The one-time backfill (WS3) is subsumed by the first sync run.** Because +> the feed carries eps 221–234, the first run of the Action generated them +> directly; no separate YouTube/Podbean scrape was needed. +> 2. **The idempotency key is the enclosure URL, not the episode number.** Every +> existing modern file carries the enclosure as `podcast_url`; none carried a +> `guid`. Matching is enclosure-URL → `guid` → `episode`, in that order. +> 3. **`itunes:episode` is unreliable — it runs one ahead** of the repo's +> convention, which parses the episode number from the Podbean enclosure +> filename (`..._episode_NNN_...`). The sync derives `episode` from the +> filename to stay consistent with the existing 217 numbered files, using +> `itunes:episode` only to disambiguate the rare filename whose number has a +> glued-on suffix (`episode_2298xv9d`). +> +> The truncation-driven *cadence* concern below is now a safety margin rather than +> a hard constraint: even a long outage would not lose episodes while the feed +> carries the full archive. The cadence is still kept weekly so the section stays +> fresh and the add-only diffs stay small. **The anti-reconcile rule still +> stands** — the Action must never widen into a delete/reconcile pass. + [[The PowerShell Podcast]] is kept in step with the repo from its Podbean RSS feed (`feed.podbean.com/powershellpodcast/feed.xml`). The non-obvious constraint that shapes the whole design: **the feed is truncated to the 10 most recent items.** It is a diff --git a/docs/podcast-sync-plan.md b/docs/podcast-sync-plan.md index 6fadcd515..2602cf0f6 100644 --- a/docs/podcast-sync-plan.md +++ b/docs/podcast-sync-plan.md @@ -36,11 +36,12 @@ Add to each modern episode: matched against the **YouTube playlist** by episode number / title. Missing ⇒ no embed, template falls back to the icon. -## Workstream 3 — Backfill eps 221–224 (one-time) +## Workstream 3 — Backfill the gap (one-time) — _subsumed by WS4_ -These four sit **before** the current feed window and are gone from RSS. Recover -them from the **YouTube playlist / Podbean website** (title, date, description, -audio URL, youtube id) and generate episode files in the same format. +Originally scoped as a YouTube/Podbean scrape of episodes that had rolled off the +10-item feed window. **Not needed:** the live feed turned out to carry the full +archive (see ADR 0003 update), so the first WS4 run generated the entire gap +(eps 221–234) directly. No scrape was performed. ## Workstream 4 — Ongoing RSS sync (automated) @@ -49,14 +50,24 @@ audio URL, youtube id) and generate episode files in the same format. - **Trigger:** scheduled GitHub Action (weekly, Tuesday — after the Monday release), `workflow_dispatch` enabled. **Auto-commits to the branch**; Netlify rebuilds on push. Must run at least every ~10 weeks or feed items roll off. +- **Implemented:** `.github/scripts/sync-podcast-feed.js` (add-only) + + `.github/workflows/podcast-sync.yml` (weekly Tuesday, `workflow_dispatch`, + auto-commit). Run `node .github/scripts/sync-podcast-feed.js --dry-run` to + preview. - **Per feed item:** - 1. Match existing files by `guid`, else by `episode` number → skip if present. + 1. Match existing files by **enclosure URL**, else `guid`, else `episode` + number → skip if present. (All existing files carry `podcast_url`; none + carried `guid`, so the enclosure URL is the universal key.) 2. Filename `YYYY-MM-DD-.md`, date from `pubDate`, `aliases: /YYYY/MM//` (matches migrated convention). 3. `author: Andrew Pla`; guests extracted **conservatively** (high-confidence - only, never remove) — port the logic from `scripts/update-podcast-authors.py`. - 4. `podcast_url` = enclosure; `episode` = `itunes:episode`; `guid`; - `youtube` = `youtu.be` id from the notes; `duration` from `itunes:duration`. + only, never remove) — bio-section + `with ` title patterns ported from + `scripts/update-podcast-authors.py`. + 4. `podcast_url` = enclosure; `episode` = number **parsed from the enclosure + filename** (the repo convention — `itunes:episode` runs one ahead, see ADR + 0003); `guid`; `youtube` = `youtu.be` id from the notes. `duration` was + **omitted** to keep the synced frontmatter identical to the existing files + (no episode currently carries it). 5. Body: `content:encoded` HTML → markdown, **strip recurring boilerplate** (Andrew's links, PDQ Discord, Summit promo, redundant YouTube line) via a maintained strip-list; keep episode-specific resource links.