Retryable Publishing With Release Please Action
Hey guys! Let's dive into a cool feature request that can seriously level up your release process using the release-please-action. We're talking about making publishing more robust and retryable, especially when things don't go as planned the first time. Stick around, because this is going to be a game-changer for your workflows!
The Problem: No Easy Retries
So, here's the deal. The current setup with release-please-action has a bit of a snag. Imagine you've got a step that only runs when the release_created output is true. This is awesome when everything is smooth sailing, but what happens when it's not? Think about those moments when publishing fails – maybe due to an expired secret or some other hiccup. Right now, there's no straightforward way to retry that publish step because release_created will only ever be true once per release. Ouch, right?
Here’s a snippet of what that looks like in your workflow:
- name: Release Please
id: release-please
uses: actions/release-please-action@v4.4.0
# THIS IS NOT RETRYABLE 👇
- name: Publish Asset
if: steps.release-please.outputs.release_created
run: pnpm asset:publish
See the problem? If the Publish Asset step fails for any reason, you're stuck. The release_created output won't be true on subsequent runs, leaving you with no simple way to retry.
Proposed Solution: release_attached Output
Now, let's talk solutions! The idea here is to introduce a new boolean output parameter called release_attached. This parameter would be true in two scenarios:
- When the initial release is created.
- When the action is run on a commit that already has a release attached to it.
Basically, release_attached gives you a way to identify if a release is associated with the current commit, regardless of whether it was just created or already existed. And guess what? The release-please-action is already smart enough to figure out if there was a previous release on the current Git hash. Check out this log snippet from a retried build:
❯ Fetching releases with cursor undefined
❯ Found release for path ., v1.1.0-alpha.3
❯ release for path: ., version: 1.1.0-alpha.3, sha: 6b8ed5e613d8c6eba0d4f866b023bec8cbf94a74
This means the action already has the smarts to know if a release is attached. We just need to expose that information as an output!
Benefits of release_attached
- Retryable Workflows: The biggest win is the ability to create retryable publishing workflows. If your publish step fails, you can retry the workflow, and
release_attachedwill still be true, allowing the publish step to run again. - Idempotent Operations: This encourages building idempotent publishing mechanisms. You can safely retry without worrying about creating duplicate releases or assets.
- Flexibility: It provides more flexibility for power users who want to build more complex release processes.
Alternatives Considered
Okay, so you might be thinking, "Why not just write a custom script to detect whether the current commit has been released?" Well, that's definitely an option, and I've considered it. However, it's not ideal. Why reinvent the wheel when the release-please-action already has all the necessary information? Writing a custom script adds complexity and maintenance overhead, which we'd really like to avoid.
Use Cases and Examples
Let's make this real with some use cases and examples. Imagine you're publishing npm packages. Sometimes, the npm registry might be down, or your authentication might temporarily fail. With release_attached, you can retry the publishing step until it succeeds, ensuring your package eventually gets published.
Example Workflow
Here’s how you might use release_attached in your GitHub Actions workflow:
name: Release and Publish
on:
push:
branches:
- main
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Release Please
id: release-please
uses: actions/release-please-action@v4.4.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.js
if: steps.release-please.outputs.release_created || steps.release-please.outputs.release_attached
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install dependencies
if: steps.release-please.outputs.release_created || steps.release-please.outputs.release_attached
run: npm ci
- name: Build
if: steps.release-please.outputs.release_created || steps.release-please.outputs.release_attached
run: npm run build
- name: Publish to npm
if: steps.release-please.outputs.release_created || steps.release-please.outputs.release_attached
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
In this example, the Setup Node.js, Install dependencies, Build, and Publish to npm steps will run if either release_created or release_attached is true. This ensures that if the initial publish fails, you can retry the workflow, and it will still attempt to publish the package.
Handling Idempotency
To make this truly robust, you need to ensure your publishing step is idempotent. This means that running the step multiple times with the same inputs should produce the same result. For example, when publishing to npm, you can use the npm publish --access public command to ensure that the package is always published with public access, even if it was already published before.
Additional Context and Considerations
Now, I know what you might be thinking: "Re-publishing can be risky!" And you're right, it can be. That's why I'm not suggesting we replace release_created for simple use cases. Instead, I'm proposing an additional output for those of us who need more control and are willing to build a safe, idempotent, and retryable publishing mechanism. This gives power users the tools they need without adding unnecessary complexity for everyone else.
Potential Hazards and Mitigation
- Accidental Re-releases: Make sure your publishing steps are idempotent to avoid accidental re-releases with unintended changes. Version control and proper tagging are your friends here.
- Dependency Issues: If your re-publishing process involves updating dependencies, ensure that you're not introducing breaking changes unexpectedly. Thorough testing is key.
- Rate Limiting: Be mindful of rate limits on publishing platforms. Implement appropriate delays or back-off strategies to avoid getting throttled.
Real-World Benefits
Let's talk about why this matters in the real world. Imagine you're working on a critical open-source project. You've just tagged a new release, but the publishing step fails because of a temporary outage at your hosting provider. Without release_attached, you'd have to manually trigger the publishing process, which is a pain. With release_attached, you can simply retry the workflow and let the system take care of it.
Another scenario: you're part of a large enterprise team deploying software to multiple environments. The publishing process involves complex steps like code signing, artifact storage, and deployment to various servers. If any of these steps fail, you need a reliable way to retry the entire process. release_attached makes this possible, ensuring your software eventually reaches its destination.
Conclusion: Empowering Power Users
In conclusion, the release_attached output parameter is a small but mighty addition to the release-please-action. It empowers power users to build more robust, retryable, and idempotent publishing workflows without adding complexity for simpler use cases. By providing a way to detect whether a release is associated with the current commit, we can unlock a whole new level of automation and reliability in our release processes. So, let's make this happen and take our release workflows to the next level!
By implementing this feature, the release-please-action becomes even more valuable, especially for those of us dealing with complex release scenarios. It's a win-win for everyone involved, making our lives easier and our releases more reliable. Let's push for this and make our development workflows smoother than ever!