Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
156891 stories
·
33 followers

Microsoft GitHub is burning free CDs of your public code to troll PlayStation, and XBOX should take notes

1 Share

Less than two days after PlayStation confirmed physical game discs are going away, GitHub decided to bring one back. The Microsoft-owned code hosting platform posted on X that it would now let developers order a burned CD of their public GitHub repo, “physically yours, forever,” and linked out to a Microsoft Forms page to collect shipping details. While other companies also mocked Sony’s decision this week, GitHub is the only one that went this far, but is it too far?

GutHub is giving opportunity to obtain your public repo on a CD-ROM

GitHub’s CD offer is a joke, but it’s real and doesn’t last that long.

GitHub’s X post reads, “We heard you. And we agree. In light of recent developments in physical media, GitHub is proud to announce that you can now obtain your public repo on CD-ROM. Keep it. Lend it to friends. Pass it on to your children. Your code is physically yours, forever. Until you lose it, let’s be real.” It links to gh.io/cd, which opens a Microsoft Forms page titled “GitHub Presents Your Code, On a CD.”

The whole thing is an elaborate joke aimed at Sony, the same kind of gag Domino’s UK and KFC Spain ran with fake “digital only” pizza and chicken announcements this week. Except GitHub’s version comes with a real intake form asking for a GitHub username, a public repo URL, shipping address, and phone number.

Companies trolling PlayStation for deciding to stop selling physical discs

GitHub CDs are only for a 1000 “eligible submissions”

The Microsoft 365 form confirms this is a short, capped run. Signing up does not guarantee a disc, since only the first 1,000 eligible submissions get one, and only one CD per person is allowed.

GitHub says shipping could take a few weeks, and availability depends on the recipient’s country or region, so even if you rushed to fill the form, by the time the CD arrives, the joke would be long forgotten.

The offer window is short too, running from July 2 to July 6, 2026, four days total. On the privacy side, GitHub says it only uses the submitted name, email, phone number, and address to ship the disc, does not use that data for anything else, and deletes it once the CD ships.

GitHub's Your Code, On a CD Microsoft Form

The form itself asks for eight pieces of information: a GitHub username, the full URL of the public repo to burn, a confirmation checkbox that the submitter owns that repo and grants GitHub permission to press it, full name, email, country, shipping address, and phone number for carriers that require it on international orders.

Standard shipping fields, nothing unusual, aside from the fact that a Fortune 500 subsidiary is running it as a four-day joke.

GitHub CD tweet was amusing to some and borderline annoying to others

GitHub’s post had already crossed a million views within hours, and the replies split into two camps. One side found it funny. Developer Ruslan Khairullin called the X post’s closing line, about code being “physically yours, forever, until you lose it,” the best line GitHub has ever shipped.

Some users leaned into nostalgia, joking about listening to their repos on a Walkman or filing a request for punch cards and floppy disks instead.

The other side was not amused, and their complaints trace back to GitHub’s own reliability record of logging 257 incidents between May 2025 and April 2026, with 48 of them classified as major outages, largely driven by AI-generated commits and Actions that run overwhelming infrastructure that was not built for that load.

Developer Robert Hurst called the tweet a bad PR move that “wastes everyone’s time” while GitHub’s own problems go unaddressed.

In case you are wondering, like a few users who asked Grok, CD-Rs typically hold up for 10 to 30 years, which is not exactly forever, but who’s counting!

But we shouldn’t forget GitHub’s parent company, Microsoft, whose own Xbox division is reportedly weighing a disc-less next.

A CD giveaway is a strange flex when the entire industry is bleeding cash on AI

Cloud storage was supposed to be the answer to all of this. No discs to lose, or shelves to dust. Everything backed up and accessible from anywhere. Then AI happened, and everything got expensive.

Microsoft, Google, Amazon, and Meta are on pace to spend close to $700 billion combined on AI infrastructure this year alone.

Even as it jokes about CD-ROM, GitHub itself is suffering from scaling problems, since AI agent activity on the platform reportedly demands 30 times the load human developers ever generated.

Considering this, a four-day offer to burn 1,000 CDs costs GitHub almost nothing and says something true almost by accident.

Physical media never went away because people are nostalgic for jewel cases. It stuck around because a disc on a shelf does not care what a company’s quarterly earnings call looked like. Sony’s decision made that point already. GitHub just decided to package it into a joke before the joke stopped being funny.

The post Microsoft GitHub is burning free CDs of your public code to troll PlayStation, and XBOX should take notes appeared first on Windows Latest

Read the whole story
alvinashcraft
18 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

From Staying in Your Line to The Connected Product Owner—Two Patterns Every Scrum Master Should Recognize | Gunnar Fischer

1 Share

Gunnar Fischer: From Staying in Your Line to The Connected Product Owner—Two Patterns Every Scrum Master Should Recognize

The Great Product Owner: The Connected PO Who Makes Information Flow

Read the full Show Notes and search through the world's largest audio library on Agile and Scrum directly on the Scrum Master Toolbox Podcast website: http://bit.ly/SMTP_ShowNotes.

 

"This Product Owner didn't need to be the smartest person in the room, but everybody knew, okay, this is a really smart guy." - Gunnar Fischer

 

The best Product Owner Gunnar ever worked with was what he calls the connected PO. This person had a deep professional network—inside the company and with the customer—and could talk to anyone: a colleague, the client, a brand-new team member they were onboarding. They were socially sharp without being shallow. They could disagree clearly, even harshly, and then turn around and say, "now let's talk about something else," with kindness. When this PO said no, it was a no people respected; when they said yes, it was a yes people trusted, because everyone knew the PO could push back. The praise behind their back matched the praise in the room. They had a private life, too—not married to the job, which made them a more well-rounded human. But the specifically Product Owner skill Gunnar names is this: they could look at the product across different time horizons—what does it need to do in one month, three months, one year—and they kept juggling functionality, contracts, customer situation, and economic reality at the same time. Their technical background helped, but they understood the line: "It's not my job to be the technically most savvy guy, but I'm willing to share my knowledge with everybody." As Gunnar puts it, the difference between a subject matter expert and a Product Owner is that the Product Owner makes the information flow.

 

Self-reflection Question: Does your Product Owner make information flow across the team, the customer, and management—or are they hoarding context as the "expert"?

The Bad Product Owner: The Stay-in-Your-Line, Accept-Your-Fate PO

Read the full Show Notes and search through the world's largest audio library on Agile and Scrum directly on the Scrum Master Toolbox Podcast website: http://bit.ly/SMTP_ShowNotes.

 

"You manage the backlog, you do the customer calls, you write the user stories—but you were not involved in any of the bigger decisions." - Gunnar Fischer

 

The anti-pattern Gunnar sees most often isn't malice—it's resignation. Most Product Owners aren't given the access or the permissions they need to be successful, and so they accept their fate. They manage the backlog, take the customer calls, write the user stories, sometimes talk to management—but they aren't part of the bigger decisions: ROI on a feature, whether to build it at all, the product vision a year out. Management keeps those decisions to itself, and the accept-your-fate PO doesn't challenge that arrangement. They stay in their line. They don't push back when sales drops in an urgent request that ruins the plan. They don't challenge the developers when an estimate feels wrong. They become very protective of the things they can control—their privileges, their processes, the artifacts—and when the bad times come, they get thrown under the bus. Gunnar's diagnosis is direct: the role of a great PO is to have constructive, respectful disagreements at every level—with the client, with management, with the team—and to be okay disappointing people. "Once you see that people go down to the mechanics, then it's a really bad smell, I would say." Saying yes to everything doesn't make you safe; it makes you replaceable.

 

In this segment, we refer to Geoff Watts' Scrum Mastery and its line about the great Scrum Master being dispensable and wanted—a frame that applies to Product Owners just as well.

 

Self-reflection Question: Where in the past month did your Product Owner say "yes" when the right answer was a respectful "no, not yet"?

 

[The Scrum Master Toolbox Podcast Recommends]

🔥In the ruthless world of fintech, success isn't just about innovation—it's about coaching!🔥

Angela thought she was just there to coach a team. But now, she's caught in the middle of a corporate espionage drama that could make or break the future of digital banking. Can she help the team regain their mojo and outwit their rivals, or will the competition crush their ambitions? As alliances shift and the pressure builds, one thing becomes clear: this isn't just about the product—it's about the people.

 

🚨 Will Angela's coaching be enough? Find out in Shift: From Product to People—the gripping story of high-stakes innovation and corporate intrigue.

 

Buy Now on Amazon

 

[The Scrum Master Toolbox Podcast Recommends]

 

About Gunnar Fischer

 

Gunnar is the leader of the Chocolate Guild. Agile practitioner with a software developer background and a strong interest in people, intercultural contacts and the bigger picture. Gunnar's purpose is to teach and to learn, to grow as a person and to support others who want the same.

 

You can link with Gunnar Fischer on LinkedIn.

 

You can also read Gunnar's writing on his blog, Leader of the Chocolate Guild.





Download audio: https://traffic.libsyn.com/secure/scrummastertoolbox/20260703_Gunnar_Fischer_F.mp3?dest-id=246429
Read the whole story
alvinashcraft
49 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Episode 579: The Headless Lifestyle

1 Share

This week, we discuss Anthropic's 18-day Fable timeout, whether AI is actually killing jobs, and OpenAI's trillion-dollar IPO problem. Plus, SoftBank's golden goose slides.

Watch the YouTube Live Recording of Episode 579

Runner-up Titles

  • Everything is Files
  • It’s just about meetings
  • Did you do the pre-meet?
  • Meetings
  • Judgement
  • Let it ride
  • If it’s hot, turn on the AC
  • I don’t have time for a towel.
  • Headless HEB

Rundown

Relevant to your Interests

Listener Feedback

Conferences

SDT News & Community

Recommendations





Download audio: https://aphid.fireside.fm/d/1437767933/9b74150b-3553-49dc-8332-f89bbbba9f92/bbe440e0-fec2-493a-bc1f-60ab12c41363.mp3
Read the whole story
alvinashcraft
56 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Switching the Aspire Community Toolkit to NuGet Trusted Publishing

1 Share

Recently I had to fix something that had become a bit too easy to ignore in the Aspire Community Toolkit: our NuGet publishing in CI had started failing, and the fix I wanted wasn’t “rotate the key and hope for the best.” If I was going to touch the release pipeline anyway, I wanted to move us onto NuGet’s newer trusted publishing model and stop depending on a long-lived API key stored in GitHub secrets.

That meant updating the workflows that publish our beta and stable packages: .github/workflows/dotnet-main.yml and .github/workflows/dotnet-release.yml. In our case those map to separate GitHub Environments as well, nuget-beta for mainline builds and nuget-stable for releases, so the supporting configuration needed to line up for both the beta path and the stable release path.

What we were changing

The old model was the familiar one:

1
2
- name: Publish to NuGet
  run: dotnet nuget push ./*.nupkg --source "https://api.nuget.org/v3/index.json" --api-key ${{ secrets.NUGET_PACKAGE_PUSH_TOKEN }}

It works until it doesn’t. Keys expire, get rotated, get copied around, or just become another piece of release infrastructure that nobody wants to touch because if it breaks you find out at the worst possible moment.

Trusted publishing is a much nicer fit for GitHub Actions. Instead of pre-provisioning a long-lived API key, the workflow exchanges GitHub’s OIDC token for a short-lived NuGet API key at runtime. So the runner only gets credentials for the duration of that job, and only if the workflow matches the trust policy configured in nuget.org.

The workflow changes

One detail that I think is worth calling out: we only changed the publish-nuget job in each workflow. The rest of dotnet-main.yml and dotnet-release.yml stayed exactly as they were. That made it much easier to reason about the migration because we were only changing the authentication mechanism, not refactoring the whole release pipeline at the same time.

The heart of the change was pretty small.

First, the publishing job needs permission to request an OIDC token:

1
2
3
4
5
publish-nuget:
  runs-on: ubuntu-latest
  permissions:
    id-token: write
    contents: read

That id-token: write permission is the important one. Without it, GitHub won’t mint the OIDC token that NuGet/login needs.

Then I replaced the static API key with NuGet/login@v1:

1
2
3
4
5
6
7
8
- name: NuGet login (OIDC)
  id: login
  uses: NuGet/login@v1
  with:
    user: ${{ secrets.NUGET_USER }}

- name: Publish to NuGet
  run: dotnet nuget push ./*.nupkg --source "https://api.nuget.org/v3/index.json" --api-key ${{ steps.login.outputs.NUGET_API_KEY }} --skip-duplicate

There are two details here that are easy to miss:

  1. NuGet/login still wants a username, so I added a NUGET_USER secret to the GitHub Environment used by the publishing job (nuget-beta for the main workflow and nuget-stable for the release workflow in our case). That value should be your existing nuget.org username, not some new service account you invent for the migration.
  2. The API key now comes from ${{ steps.login.outputs.NUGET_API_KEY }}, which is short-lived and scoped to that workflow run.

I also added --skip-duplicate, because package publishing jobs are exactly the sort of thing you end up re-running after fixing an unrelated failure. If the package is already on nuget.org, I want the rerun to be boring, not fatal.

The setup detail that bit me

The part that matters most isn’t actually in GitHub, it’s in nuget.org.

When you create the trusted publishing policy for a package, nuget.org wants to know exactly which GitHub repository and workflow file are allowed to publish it. And “exactly” really does mean exactly. The policy has to match the workflow filename, not just the repository or a rough pattern.

So if your beta packages are published by .github/workflows/dotnet-main.yml, that exact workflow path needs to be in the nuget.org policy for the nuget-beta environment. If your stable packages are published by .github/workflows/dotnet-release.yml, that needs its own matching policy for nuget-stable as well.

This is where I think people are most likely to get tripped up. It’s easy to assume that “the repo is trusted” or “the workflow name is close enough.” It isn’t. If the filename in nuget.org doesn’t match the workflow that’s actually running, the login step won’t be able to exchange the OIDC token for a NuGet API key.

Why I kept the old path around

I didn’t want to flip both publishing paths over and immediately delete the old secret-based setup.

Instead, I treated the beta flow as the proving ground. Once the trusted publishing path succeeded there, I had much higher confidence applying the same pattern to the stable release workflow. That’s also why I recommend keeping the old API key path available until you’ve seen the new flow complete successfully at least once.

The failure mode for trusted publishing is usually configuration, not code:

  • the wrong workflow filename in nuget.org
  • the wrong repository bound to the policy
  • missing id-token: write
  • forgetting the NUGET_USER environment secret
  • setting NUGET_USER to the wrong account name

Those are all easy mistakes to make, and much easier to recover from if you haven’t immediately torn out the previous publishing path.

For the same reason, I strongly recommend treating the old secret as a temporary safety net. Once you remove the old API-key-based path, getting back to a known-good state is a lot more annoying than just leaving it alone until the trusted publishing path has proved itself.

The practical setup checklist

If you’re doing this yourself, here’s the checklist I wish I’d had up front:

  1. Create a trusted publishing policy in nuget.org for each package flow you want to support.
  2. Make sure the policy references the exact GitHub repository and exact workflow filename.
  3. Add id-token: write to the publish job permissions.
  4. Add a NUGET_USER secret to the GitHub Environment used by that job.
  5. Use NuGet/login@v1 and publish with ${{ steps.login.outputs.NUGET_API_KEY }}.
  6. Add --skip-duplicate so reruns don’t fail unnecessarily.
  7. Keep the old API-key-based path around until the new flow has succeeded end-to-end.

How I validated it before the first publish

Before trusting the workflow change, I wanted to know that package creation itself wasn’t going to be the thing that failed. The local command I used for that sanity check was:

1
dotnet pack -c Release -o ./artifacts

That obviously doesn’t test the OIDC exchange with nuget.org, but it does confirm that the package output you’re about to hand to the workflow is sound. When you’re changing release automation, separating “can I create the package?” from “can the runner authenticate?” is a useful way to keep the blast radius small.

Why this is better

The immediate win was getting our CI publishing working again, but the longer-term improvement is operational. We no longer have a long-lived NuGet push key sitting around as a secret that we need to manage manually. Publishing is now tied to the workflow identity itself, which is exactly what I want for release automation.

It’s one of those changes that’s not especially flashy when you look at the diff, but it meaningfully tightens the supply chain story around package publishing. And if you’re already on GitHub Actions, it’s a pretty natural upgrade once you know where the sharp edges are.

If you want to see what this looked like in practice, the beta migration landed first in PR #1452, and the stable release follow-up went into PR #1453. That sequencing was deliberate: prove the pattern on the beta path, then roll it forward to the stable one once the moving parts were understood.

Honestly, the biggest lesson from this migration was that the YAML change is the easy part. The real work is making sure GitHub, nuget.org, and your workflow filenames all agree on who is allowed to publish what.

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

DWX 2026 Wrap-Up: Four Days of Innovation, Conversations, and Enterprise Document Solutions

1 Share
DWX 2026 was a great success for Text Control. We had the opportunity to meet with many developers, discuss document processing solutions, and showcase our latest innovations in document technology. In this wrap-up, we share our experiences and insights from the event.

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

Octopus Easy Mode - Ephemeral Environments

1 Share

In the previous post, you created a functional Kubernetes deployment project. In this post, you’ll create Ephemeral Environments to simulate the deployment of feature branches.

Prerequisites

  • An Octopus Cloud account. If you don’t have one, you can sign up for a free trial.
  • The Octopus AI Assistant Chrome extension. You can install it from the Chrome Web Store.

The Octopus AI Assistant will work with an on-premises Octopus instance, but it requires more configuration. The cloud-hosted version of Octopus doesn’t need extra configuration. This means the cloud-hosted version is the easiest way to get started.

Creating the project

Ephemeral environments support the creation and destruction of short-lived environments and their associated resources. These environments are often used to deploy feature-branch builds, allowing developers to interact with their work before it is merged into a mainline branch.

Paste the following prompt into the Octopus AI Assistant and run it:

Create a Kubernetes project called "K8s Web App with Ephemeral Environments", and then:
* Use client side apply in the Kubernetes step (the mock Kubernetes cluster only supports client side apply).
* Disable verification checks in the Kubernetes steps (the mock Kubernetes cluster doesn't support verification checks).
* Enable retries on the K8s deployment step.
* Add support for ephemeral environments, with the Parent Environment and Ephemeral Environment channel both called "Features"

---

Create a token account called "Mock Token".

---

Create a feed called "Docker Hub" pointing to "https://index.docker.io" using anonymous authentication.

---

Create a Kubernetes target with the tag "Kubernetes", the URL https://mockk8s.octopusdemos.com, attach it to the "Development", "Test", "Production" environments and the "Features" parent environment, using the health check container image "octopusdeploy/worker-tools:6.5.0-ubuntu.22.04" from the "Docker Hub" feed, using the token account, and the "Hosted Ubuntu" worker pool.

The document separator (---) is used to split the prompt into multiple sections. Each section is applied sequentially, which allows you to create different types of resources in a single prompt.

As we did in the last post, the AI Assistant creates a functional Kubernetes project pointing to a mock Kubernetes server.

We then added support for ephemeral environments, which requires:

  • A parent environment called Features
  • A channel that deploys to ephemeral environments, also called Features

Parent Environment Channel

Create a new deployment of the project, select the Features channel, and define the FeatureBranch custom field to the name of a feature branch like features/font-change:

New Release

The value assigned to the custom field is used as the name for the new environment. Any invalid characters, like the backslash, are automatically sanitized to provide a valid environment name.

The deployment is visible in the Ephemeral Environments section:

Ephemeral Environments

Because the Kubernetes step is configured to deploy resources to the namespace #{Octopus.Environment.Name | ToLower}, the ephemeral deployment creates resources in a namespace based on the ephemeral environment name, keeping it separate from the traditional deployments to the Development, Test, and Production environments.

You’ll also notice that the Kubernetes target was selected for the deployment because it was attached to the parent Features environment. This demonstrates how durable Octopus resources are linked to ephemeral environment deployments.

Runbooks can be used for those scenarios where you need to provision and deprovision the environment.

Run the following prompt to add two runbooks to the project:

Create a runbook called "Provision Environment" in the project "K8s Web App with Ephemeral Environments".
Allow the runbook to be run from the "Features" environment.
Add a "Run a kubectl script" step run against the target tag "Kubernetes" and echo the text "Provisioning the environment" from a bash script.
Run the step from the "Hosted Ubuntu" worker pool.

---

Create a runbook called "Deprovision Environment" in the project "K8s Web App with Ephemeral Environments".
Allow the runbook to be run from the "Features" environment.
Add a "Run a kubectl script" step run against the target tag "Kubernetes" and echo the text "Deprovisioning the environment" from a bash script.
Run the step from the "Hosted Ubuntu" worker pool.

In the Ephemeral Environments project section, open the Settings tab, and select the new runbooks from the Provisioning runbook and Deprovisioning runbook fields:

Ephemeral Environments Runbooks

Both runbooks must have a published snapshot. Open each runbook, click the Publish button, and click the Publish button again:

Publish Runbooks

Now, when you deploy to an ephemeral environment, the Provision Environment runbook is executed. After one week, the Deprovision Environment runbook is automatically executed, or you can manually deprovision an environment in the Ephemeral Environments section under the Overview tab:

Deprovision Environment

What just happened?

You created a sample Kubernetes project with:

  • A channel called Features to deploy to an ephemeral environment based on a custom field value
  • A Parent Environment called Features
  • A Kubernetes target linked to the Features parent environment
  • Two runbooks: one to provision the ephemeral environment, and another to deprovision it
Read the whole story
alvinashcraft
2 minutes ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories