<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Pipery Guides on Pipery - Production-grade CI/CD pipelines</title><link>https://pipery.dev/post/</link><description>Recent Posts in Pipery Guides on Pipery - Production-grade CI/CD pipelines</description><generator>Hugo 0.161.1</generator><language>en-us</language><managingEditor>hello@pipery.dev (Pipery)</managingEditor><webMaster>hello@pipery.dev (Pipery)</webMaster><lastBuildDate>Mon, 04 May 2026 10:41:01 +0000</lastBuildDate><atom:link href="https://pipery.dev/post/index.xml" rel="self" type="application/rss+xml"/><item><title>Deploying to Cloud Run with Pipery Cloud Run CD</title><link>https://pipery.dev/post/deploying-to-cloud-run-with-pipery-cloudrun-cd/</link><pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate><author>hello@pipery.dev (Pipery)</author><dc:creator>Pipery</dc:creator><guid>https://pipery.dev/post/deploying-to-cloud-run-with-pipery-cloudrun-cd/</guid><description>Ship a container to Google Cloud Run with Pipery Cloud Run CD, including image push, deploy, traffic migration, health checks, and replayable logs.</description><content:encoded>&lt;p&gt;Once a service is built and tested, the next question is how to deploy it without turning your workflow into another custom shell project. &lt;code&gt;pipery-dev/pipery-cloudrun-cd&lt;/code&gt; gives you a reusable Cloud Run deployment step with the same observability story as the CI actions.&lt;/p&gt;
&lt;h2 id="minimal-workflow"&gt;Minimal workflow&lt;a class="anchor" href="#minimal-workflow"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;CD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;branches&lt;/span&gt;: [&lt;span style="color:#ae81ff"&gt;main]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;cd&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;uses&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;pipery-dev/pipery-cloudrun-cd@v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image_name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ghcr.io/acme/api&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;service_name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;api&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;region&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;europe-west1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;project_id&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;acme-platform-prod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;secrets&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;inherit&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="what-the-action-does"&gt;What the action does&lt;a class="anchor" href="#what-the-action-does"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The deployment path is straightforward:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;push the container image&lt;/li&gt;
&lt;li&gt;deploy with &lt;code&gt;gcloud run deploy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;migrate traffic&lt;/li&gt;
&lt;li&gt;run a status check&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="inputs-to-care-about-early"&gt;Inputs to care about early&lt;a class="anchor" href="#inputs-to-care-about-early"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;image_name&lt;/code&gt;: the image being deployed&lt;/li&gt;
&lt;li&gt;&lt;code&gt;image_tag&lt;/code&gt;: defaults to the current Git SHA, which is a sensible starting point&lt;/li&gt;
&lt;li&gt;&lt;code&gt;service_name&lt;/code&gt;: the Cloud Run service to update&lt;/li&gt;
&lt;li&gt;&lt;code&gt;region&lt;/code&gt; and &lt;code&gt;project_id&lt;/code&gt;: define the deployment target&lt;/li&gt;
&lt;li&gt;&lt;code&gt;traffic&lt;/code&gt;: useful when you want a more careful rollout&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="why-teams-like-this-pattern"&gt;Why teams like this pattern&lt;a class="anchor" href="#why-teams-like-this-pattern"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Cloud Run deployment is simple enough to start casually and tricky enough to drift over time. One team adds traffic handling, another adds status checks, another copies an old auth pattern. A shared action gives you the same deployment shape everywhere, and Pipery’s &lt;code&gt;psh&lt;/code&gt; logs make post-deploy debugging much calmer when a rollout does not behave the way you expected.&lt;/p&gt;
&lt;p&gt;Source and docs: &lt;a href="https://github.com/pipery-dev/pipery-cloudrun-cd" target="_blank" rel="external noopener noreferrer nofollow"&gt;pipery-cloudrun-cd&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Getting started with Pipery Docker CI</title><link>https://pipery.dev/post/getting-started-with-pipery-docker-ci/</link><pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate><author>hello@pipery.dev (Pipery)</author><dc:creator>Pipery</dc:creator><guid>https://pipery.dev/post/getting-started-with-pipery-docker-ci/</guid><description>Adopt Pipery Docker CI to lint Dockerfiles, scan images, build containers, run smoke tests, tag images, and push them through GitHub Actions.</description><content:encoded>&lt;p&gt;Container pipelines get messy quickly. &lt;code&gt;pipery-dev/pipery-docker-ci&lt;/code&gt; wraps the usual Docker CI sequence into one reusable action, with structured logging built in.&lt;/p&gt;
&lt;p&gt;Instead of hand-writing Docker login, build, scan, test, tag, and push steps in every repository, you can move that workflow into a single maintained action call.&lt;/p&gt;
&lt;h2 id="minimal-workflow"&gt;Minimal workflow&lt;a class="anchor" href="#minimal-workflow"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;CI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;branches&lt;/span&gt;: [&lt;span style="color:#ae81ff"&gt;main]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;pull_request&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ci&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;runs-on&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ubuntu-latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;uses&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;actions/checkout@v4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;uses&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;pipery-dev/pipery-docker-ci@v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image_name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ghcr.io/${{ github.repository }}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;registry_username&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${{ github.actor }}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;registry_password&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;github_token&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="what-it-handles"&gt;What it handles&lt;a class="anchor" href="#what-it-handles"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The action covers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Dockerfile linting with Hadolint&lt;/li&gt;
&lt;li&gt;SAST with Trivy config scanning&lt;/li&gt;
&lt;li&gt;SCA with Trivy image scanning&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker build&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;container smoke testing&lt;/li&gt;
&lt;li&gt;semantic versioning&lt;/li&gt;
&lt;li&gt;image tagging&lt;/li&gt;
&lt;li&gt;registry push&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="inputs-teams-usually-care-about-first"&gt;Inputs teams usually care about first&lt;a class="anchor" href="#inputs-teams-usually-care-about-first"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dockerfile&lt;/code&gt;: useful when the repo has more than one Dockerfile&lt;/li&gt;
&lt;li&gt;&lt;code&gt;image_name&lt;/code&gt;: the published registry path&lt;/li&gt;
&lt;li&gt;&lt;code&gt;build_args&lt;/code&gt;: pass image build arguments cleanly&lt;/li&gt;
&lt;li&gt;&lt;code&gt;platforms&lt;/code&gt;: define target platforms early if multi-arch matters&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tests_path&lt;/code&gt;: provide the smoke-test command you want run inside the container&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="where-the-observability-matters"&gt;Where the observability matters&lt;a class="anchor" href="#where-the-observability-matters"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Docker builds can fail for reasons that are annoyingly context-heavy: auth, missing files, cache misses, registry problems, and test commands that only fail inside the built image. Because Pipery captures each command as it runs, the failure is not trapped inside a giant opaque shell block. You get replayable, step-level logs in &lt;code&gt;pipery.jsonl&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That is the difference between “the image push step failed somewhere” and “this exact command failed with this exact output.”&lt;/p&gt;
&lt;p&gt;Source and docs: &lt;a href="https://github.com/pipery-dev/pipery-docker-ci" target="_blank" rel="external noopener noreferrer nofollow"&gt;pipery-docker-ci&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Getting started with Pipery npm CI</title><link>https://pipery.dev/post/getting-started-with-pipery-npm-ci/</link><pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate><author>hello@pipery.dev (Pipery)</author><dc:creator>Pipery</dc:creator><guid>https://pipery.dev/post/getting-started-with-pipery-npm-ci/</guid><description>Set up Pipery npm CI in a Node.js repository to run scanning, linting, tests, packaging, and npm release with structured pipeline logs.</description><content:encoded>&lt;p&gt;If your Node.js workflow keeps growing one shell step at a time, &lt;code&gt;pipery-dev/pipery-npm-ci&lt;/code&gt; is a clean place to stop and standardize it.&lt;/p&gt;
&lt;p&gt;This action is a complete CI workflow for npm and Yarn projects. It covers SAST, dependency scanning, linting, build, test, versioning, packaging, release, and reintegration, while every command is captured in &lt;code&gt;pipery.jsonl&lt;/code&gt; through &lt;code&gt;psh&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="when-to-use-it"&gt;When to use it&lt;a class="anchor" href="#when-to-use-it"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use &lt;code&gt;pipery-npm-ci&lt;/code&gt; when you want one reusable workflow for JavaScript or TypeScript repositories and you do not want to hand-maintain the usual install, lint, test, package, and publish sequence in every repo.&lt;/p&gt;
&lt;p&gt;It is especially helpful when your team wants:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the same CI behavior across several services&lt;/li&gt;
&lt;li&gt;predictable release behavior for npm packages&lt;/li&gt;
&lt;li&gt;searchable logs instead of long unstructured GitHub output&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="minimal-workflow"&gt;Minimal workflow&lt;a class="anchor" href="#minimal-workflow"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;CI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;branches&lt;/span&gt;: [&lt;span style="color:#ae81ff"&gt;main]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;pull_request&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ci&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;runs-on&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ubuntu-latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;uses&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;actions/checkout@v4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;uses&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;pipery-dev/pipery-npm-ci@v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;project_path&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;npm_token&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${{ secrets.NPM_TOKEN }}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;github_token&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="good-first-inputs-to-set"&gt;Good first inputs to set&lt;a class="anchor" href="#good-first-inputs-to-set"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;node_version&lt;/code&gt;: pin the runtime your app actually uses&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package_manager&lt;/code&gt;: set &lt;code&gt;npm&lt;/code&gt; or &lt;code&gt;yarn&lt;/code&gt; if you do not want auto-detection&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tests_path&lt;/code&gt;: narrow test execution when a repo needs it&lt;/li&gt;
&lt;li&gt;&lt;code&gt;version_bump&lt;/code&gt;: control default release behavior&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-happens-in-the-pipeline"&gt;What happens in the pipeline&lt;a class="anchor" href="#what-happens-in-the-pipeline"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The action runs:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;SAST with &lt;code&gt;njsscan&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;SCA with &lt;code&gt;npm audit&lt;/code&gt; or &lt;code&gt;yarn audit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;lint with ESLint&lt;/li&gt;
&lt;li&gt;build with your package manager&lt;/li&gt;
&lt;li&gt;tests&lt;/li&gt;
&lt;li&gt;semantic versioning&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npm pack&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;npm publish and SHA tagging&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That means the repo owner gets a full CI path without rewriting the same workflow skeleton again.&lt;/p&gt;
&lt;h2 id="why-pipery-helps-here"&gt;Why Pipery helps here&lt;a class="anchor" href="#why-pipery-helps-here"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Node pipelines often fail in the annoying middle: lockfile drift, a flaky test, a publish auth issue, an unexpected build script change. Pipery logs each executed command and its output in &lt;code&gt;pipery.jsonl&lt;/code&gt;, so you can inspect the exact step in the dashboard instead of reconstructing the failure by hand.&lt;/p&gt;
&lt;p&gt;Start with the action repo here: &lt;a href="https://github.com/pipery-dev/pipery-npm-ci" target="_blank" rel="external noopener noreferrer nofollow"&gt;pipery-npm-ci&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Getting started with Pipery Python CI</title><link>https://pipery.dev/post/getting-started-with-pipery-python-ci/</link><pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate><author>hello@pipery.dev (Pipery)</author><dc:creator>Pipery</dc:creator><guid>https://pipery.dev/post/getting-started-with-pipery-python-ci/</guid><description>Use Pipery Python CI to run Bandit, dependency scanning, Ruff, pytest, packaging, and PyPI release in one reusable GitHub Actions workflow.</description><content:encoded>&lt;p&gt;&lt;code&gt;pipery-dev/pipery-python-ci&lt;/code&gt; is the easiest way to give a Python repository a consistent CI pipeline without stitching together half a dozen actions and shell steps.&lt;/p&gt;
&lt;p&gt;It is designed for the common Python path: scan the code, audit dependencies, lint, build, test, package, and publish, while producing a structured &lt;code&gt;pipery.jsonl&lt;/code&gt; log for the whole run.&lt;/p&gt;
&lt;h2 id="when-it-fits-well"&gt;When it fits well&lt;a class="anchor" href="#when-it-fits-well"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This action is a good match when your repo is using setuptools, Poetry, or &lt;code&gt;uv&lt;/code&gt;, and you want one workflow that can grow from pull request validation into package release without being rewritten later.&lt;/p&gt;
&lt;h2 id="minimal-workflow"&gt;Minimal workflow&lt;a class="anchor" href="#minimal-workflow"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;CI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;branches&lt;/span&gt;: [&lt;span style="color:#ae81ff"&gt;main]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;pull_request&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ci&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;runs-on&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ubuntu-latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;uses&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;actions/checkout@v4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;uses&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;pipery-dev/pipery-python-ci@v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;project_path&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;pypi_token&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${{ secrets.PYPI_TOKEN }}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;github_token&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="inputs-worth-setting-early"&gt;Inputs worth setting early&lt;a class="anchor" href="#inputs-worth-setting-early"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;python_version&lt;/code&gt;: align CI with the runtime you support&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package_manager&lt;/code&gt;: choose &lt;code&gt;setuptools&lt;/code&gt;, &lt;code&gt;poetry&lt;/code&gt;, or &lt;code&gt;uv&lt;/code&gt; when you want explicit behavior&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tests_path&lt;/code&gt;: point pytest at the right subset when your repo needs it&lt;/li&gt;
&lt;li&gt;&lt;code&gt;registry&lt;/code&gt;: keep the default &lt;code&gt;pypi&lt;/code&gt; or adapt when your publish target changes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-the-action-covers"&gt;What the action covers&lt;a class="anchor" href="#what-the-action-covers"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The pipeline includes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;SAST with Bandit&lt;/li&gt;
&lt;li&gt;SCA with &lt;code&gt;pip-audit&lt;/code&gt; or &lt;code&gt;safety&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;linting with Ruff&lt;/li&gt;
&lt;li&gt;build&lt;/li&gt;
&lt;li&gt;pytest&lt;/li&gt;
&lt;li&gt;semantic versioning&lt;/li&gt;
&lt;li&gt;packaging with &lt;code&gt;python -m build&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;publish with Twine&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="why-it-is-useful-in-practice"&gt;Why it is useful in practice&lt;a class="anchor" href="#why-it-is-useful-in-practice"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Python repos tend to drift over time. One project uses Poetry, another uses plain setuptools, another quietly changed its test command months ago. Pipery gives you a common CI contract while still exposing the real command history through &lt;code&gt;psh&lt;/code&gt; and &lt;code&gt;pipery.jsonl&lt;/code&gt; when something fails.&lt;/p&gt;
&lt;p&gt;That makes it easier to adopt a standard without losing debuggability.&lt;/p&gt;
&lt;p&gt;Source and docs: &lt;a href="https://github.com/pipery-dev/pipery-python-ci" target="_blank" rel="external noopener noreferrer nofollow"&gt;pipery-python-ci&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Getting started with Pipery Terraform CI</title><link>https://pipery.dev/post/getting-started-with-pipery-terraform-ci/</link><pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate><author>hello@pipery.dev (Pipery)</author><dc:creator>Pipery</dc:creator><guid>https://pipery.dev/post/getting-started-with-pipery-terraform-ci/</guid><description>Use Pipery Terraform CI to run tfsec, dependency checks, tflint, validate, and plan for Terraform repositories with structured execution logs.</description><content:encoded>&lt;p&gt;Infrastructure repositories deserve the same level of repeatability as application repos. &lt;code&gt;pipery-dev/pipery-terraform-ci&lt;/code&gt; gives Terraform projects a shared CI pipeline that validates code, checks risk earlier, and leaves behind a structured log you can inspect later.&lt;/p&gt;
&lt;h2 id="minimal-workflow"&gt;Minimal workflow&lt;a class="anchor" href="#minimal-workflow"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;CI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;push&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;branches&lt;/span&gt;: [&lt;span style="color:#ae81ff"&gt;main]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;pull_request&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ci&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;uses&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;pipery-dev/pipery-terraform-ci@v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;project_path&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;secrets&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;inherit&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="what-it-runs"&gt;What it runs&lt;a class="anchor" href="#what-it-runs"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The action covers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;tfsec for SAST&lt;/li&gt;
&lt;li&gt;dependency scanning&lt;/li&gt;
&lt;li&gt;tflint&lt;/li&gt;
&lt;li&gt;&lt;code&gt;terraform validate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;terraform plan&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;versioning&lt;/li&gt;
&lt;li&gt;release handling&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="useful-inputs"&gt;Useful inputs&lt;a class="anchor" href="#useful-inputs"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;terraform_version&lt;/code&gt;: pin the CLI version used by the repo&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backend_config&lt;/code&gt;: provide backend settings cleanly&lt;/li&gt;
&lt;li&gt;&lt;code&gt;var_file&lt;/code&gt;: point at the right tfvars file&lt;/li&gt;
&lt;li&gt;&lt;code&gt;working_directory&lt;/code&gt;: useful when the Terraform root is not the repo root&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="why-this-helps-teams"&gt;Why this helps teams&lt;a class="anchor" href="#why-this-helps-teams"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Terraform workflows often grow hidden complexity around backends, environments, validation order, and plan behavior. A shared action makes the happy path repeatable across repos, while Pipery gives you the execution detail to understand a failed validate or plan run without digging through a long shell script.&lt;/p&gt;
&lt;p&gt;If your team is trying to standardize infrastructure checks before merge, this is a strong first action to adopt.&lt;/p&gt;
&lt;p&gt;Source and docs: &lt;a href="https://github.com/pipery-dev/pipery-terraform-ci" target="_blank" rel="external noopener noreferrer nofollow"&gt;pipery-terraform-ci&lt;/a&gt;.&lt;/p&gt;</content:encoded></item></channel></rss>