<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: epassaro</title>
    <description>The latest articles on DEV Community by epassaro (@epassaro).</description>
    <link>https://dev.to/epassaro</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F153937%2F1a4b93de-c030-4bcb-9ace-6d22a0cc0e1e.png</url>
      <title>DEV Community: epassaro</title>
      <link>https://dev.to/epassaro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/epassaro"/>
    <language>en</language>
    <item>
      <title>Make your videos Twitter (X) compatible</title>
      <dc:creator>epassaro</dc:creator>
      <pubDate>Thu, 03 Aug 2023 16:00:28 +0000</pubDate>
      <link>https://dev.to/epassaro/make-your-videos-twitter-x-compatible-29od</link>
      <guid>https://dev.to/epassaro/make-your-videos-twitter-x-compatible-29od</guid>
      <description>&lt;p&gt;If you are getting stuck at 99% while updating videos to Twitter, try this solution. It just requires having &lt;code&gt;ffmpeg&lt;/code&gt; installed on the system and adding this function to your&lt;code&gt;.bashrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;twitterfix() { ffmpeg -i "$1" -c:v libx264 -crf 20 -preset slow -vf "crop=trunc(iw/2)*2:trunc(ih/2)*2, format=yuv420p" -c:a aac -movflags +faststart out.mp4 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usage example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ twitterfix my_video.mp4
$ ls
my_video.mp4 out.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>linux</category>
      <category>opensource</category>
      <category>ffmpeg</category>
    </item>
    <item>
      <title>[FIX] Read-only file system after waking up from suspend</title>
      <dc:creator>epassaro</dc:creator>
      <pubDate>Sun, 30 Jul 2023 20:35:23 +0000</pubDate>
      <link>https://dev.to/epassaro/fix-read-only-file-system-after-waking-up-from-suspend-kod</link>
      <guid>https://dev.to/epassaro/fix-read-only-file-system-after-waking-up-from-suspend-kod</guid>
      <description>&lt;p&gt;A new laptop has arrived and of course new problems arise after installing Linux. But this time the problem &lt;a href="https://dev.to/epassaro/fix-suspend-issues-on-dell-7405-2-in-1-3l1b"&gt;looked familiar&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This time I was working with an ASUS laptop with an Intel 11th Gen processor and an Intel NVMe SSD.&lt;/p&gt;

&lt;p&gt;First thing I did was checking if the evil &lt;code&gt;s2idle&lt;/code&gt; sleep mode was enabled, and I that was exactly the case.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat /sys/power/mem_sleep
[s2idle] deep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The S3 &lt;code&gt;deep&lt;/code&gt; mode was available, so this time I didn't need to patch the ACPI table. Then, I just added &lt;code&gt;"mem_sleep_default=deep"&lt;/code&gt; line to the &lt;code&gt;GRUB_CMDLINE_LINUX_DEFAULT&lt;/code&gt; parameter in &lt;code&gt;/etc/default/grub&lt;/code&gt; and updated GRUB according to my distribution.&lt;/p&gt;

&lt;p&gt;Now I can suspend and wake up the system without any problem!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Remove patterns in openSUSE</title>
      <dc:creator>epassaro</dc:creator>
      <pubDate>Mon, 19 Jun 2023 02:55:59 +0000</pubDate>
      <link>https://dev.to/epassaro/remove-patterns-in-opensuse-7mm</link>
      <guid>https://dev.to/epassaro/remove-patterns-in-opensuse-7mm</guid>
      <description>&lt;p&gt;To remove a pattern in openSUSE just type the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo zypper remove -u pattern:&amp;lt;pattern_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo zypper remove -u pattern:kvm_server pattern:kvm_tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>linux</category>
      <category>opensource</category>
      <category>opensuse</category>
    </item>
    <item>
      <title>Identify and Report Vulnerable Dependencies in Conda-Based Projects with GitHub Actions</title>
      <dc:creator>epassaro</dc:creator>
      <pubDate>Mon, 22 May 2023 22:01:40 +0000</pubDate>
      <link>https://dev.to/epassaro/identify-and-report-vulnerable-dependencies-in-conda-based-projects-with-github-actions-2bdh</link>
      <guid>https://dev.to/epassaro/identify-and-report-vulnerable-dependencies-in-conda-based-projects-with-github-actions-2bdh</guid>
      <description>&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;A GitHub Actions workflow that scans your Conda environment files for common vulnerabilities and exposures (CVE).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's worth mentioning that Dependabot does not have support for Conda environment files, and GitHub developers have stated that &lt;a href="https://github.com/dependabot/dependabot-core/issues/2227" rel="noopener noreferrer"&gt;there are no plans to add this feature&lt;/a&gt; in the foreseeable future.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Category Submission:
&lt;/h3&gt;

&lt;p&gt;DIY Deployments&lt;/p&gt;

&lt;h3&gt;
  
  
  App Link
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/epassaro/conda-deps-check" rel="noopener noreferrer"&gt;Workflow repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/epassaro/my-conda-repo/issues/1" rel="noopener noreferrer"&gt;Example repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Screenshots
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc31wnrcqq3c56cc1dack.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc31wnrcqq3c56cc1dack.png" alt="Example report" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Description
&lt;/h3&gt;

&lt;p&gt;Looking for a solution like Dependabot for your Conda-based project? Strengthen your repository's security with this reliable &lt;strong&gt;GitHub Actions reusable workflow!&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Implementing this workflow is straightforward. Just provide the path to your Conda environment file in YAML format, and let the workflow effortlessly handle the rest.&lt;/p&gt;

&lt;p&gt;Powered by &lt;a href="https://github.com/sonatype-nexus-community/jake" rel="noopener noreferrer"&gt;&lt;code&gt;jake&lt;/code&gt;&lt;/a&gt;, an open-source package from the &lt;a href="https://github.com/sonatype-nexus-community" rel="noopener noreferrer"&gt;Sonatype Community&lt;/a&gt;, this workflow checks your environments for vulnerable open-source packages using the trusted &lt;a href="https://ossindex.sonatype.org/" rel="noopener noreferrer"&gt;OSS Index&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;If any vulnerabilities are detected, the workflow will either open a new issue or update an existing one, listing the known CVEs and affected packages. &lt;/p&gt;

&lt;p&gt;Furthermore, you have the option to ignore specific CVEs by providing a text file. Customize your security measures according to your needs.&lt;/p&gt;

&lt;p&gt;And the best part is that this is not restricted just to Python packages! Packages in any progamming language are supported as far as they are distributed by the Conda package manager.&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Source Code
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/epassaro/conda-deps-check" rel="noopener noreferrer"&gt;https://github.com/epassaro/conda-deps-check&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Permissive License
&lt;/h3&gt;

&lt;p&gt;MIT License&lt;/p&gt;

&lt;h2&gt;
  
  
  Background (What made you decide to build this particular app? What inspired you?)
&lt;/h2&gt;

&lt;p&gt;The motivation to build this app stemmed from my personal experience as a solo developer working on Conda-based projects. It became evident that there was a significant gap in the availability of tools like Dependabot that could effectively address security concerns in this context.&lt;/p&gt;

&lt;p&gt;Driven by the desire to bolster the security of my own projects, I embarked on the task of developing tools that could offer similar functionality to Dependabot. Participating in this hackathon provided the perfect opportunity to jumpstart this endeavor.&lt;/p&gt;

&lt;p&gt;I am fully committed to the continuous improvement and expansion of these workflows beyond the hackathon.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I built it (How did you utilize GitHub Actions or GitHub Codespaces? Did you learn something new along the way? Pick up a new skill?)
&lt;/h3&gt;

&lt;p&gt;I built this workflow as a reusable solution, and it was my first time working with this type of workflow. While I had some familiarity with Azure Pipelines templates, reusable workflows offered a new and different experience. The beauty of reusable workflows is that they allow me to continue working on and adding features to the workflow, while making it easy for users to implement it in their repositories.&lt;/p&gt;

&lt;p&gt;One of the great advantages of this workflow is its flexibility. Users can run different versions of the workflow based on release tags, branches, or commit SHA, giving them the ability to customize it according to their specific needs.&lt;/p&gt;

&lt;p&gt;When it came to vulnerability scanning, I decided to use a specific version of &lt;code&gt;jake&lt;/code&gt; that goes beyond checking vulnerabilities in just Python packages. It extends its reach to cover all packages distributed in the Conda ecosystem, which is a significant advantage compared to &lt;a href="https://github.com/jhutchings1/conda-dependency-submission-action" rel="noopener noreferrer"&gt;other alternatives available&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;During the development process, I discovered the &lt;a href="https://github.com/github/advisory-database/" rel="noopener noreferrer"&gt;GitHub Advisory Database&lt;/a&gt;, which I wasn't previously aware of. This led me to create a nightly workflow that parses the database and generates a simple JSON file with package fixes for a given CVE. My plan is to use this information to enhance the generated report with more comprehensive details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources/Info
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/epassaro/ghadb-parser" rel="noopener noreferrer"&gt;epassaro/ghadb-parser&lt;/a&gt; - GitHub Advisory Database Parser&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/epassaro/ghadb-parser" rel="noopener noreferrer"&gt;epassaro/conda-deps-check-old&lt;/a&gt; - Previous version of this workflow, without using reusable workflows&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>githubhack23</category>
    </item>
    <item>
      <title>Build your LaTeX documents with GitHub Actions</title>
      <dc:creator>epassaro</dc:creator>
      <pubDate>Tue, 07 Dec 2021 01:36:18 +0000</pubDate>
      <link>https://dev.to/epassaro/build-your-latex-documents-with-github-actions-gdf</link>
      <guid>https://dev.to/epassaro/build-your-latex-documents-with-github-actions-gdf</guid>
      <description>&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;LaTeX is a high-quality typesetting system, and it's the de facto standard for the communication and publication of scientific documents.&lt;/p&gt;

&lt;p&gt;I think the Git version control system fits perfectly when it comes to collaborative, scientific writing. It's superior to the Google Docs style of Overleaf.&lt;/p&gt;

&lt;p&gt;Installing a full LaTeX system takes up a considerable amount time and space on your hard drive. I heard about &lt;a href="https://tectonic-typesetting.github.io/en-US/" rel="noopener noreferrer"&gt;Tectonic&lt;/a&gt; during the &lt;a href="https://packaging-con.org/" rel="noopener noreferrer"&gt;PackagingCon 2021&lt;/a&gt;  and immediately I knew that's the kind of stuff I want to deploy on GitHub Actions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Tectonic is a modernized, complete, self-contained TeX/LaTeX engine, powered by XeTeX and TeXLive. (...) Tectonic &lt;strong&gt;automatically downloads support files&lt;/strong&gt; so you don’t have to install a full LaTeX system in order to start using it. If you start using a new LaTeX package, Tectonic just pulls down the files it needs and continues processing. The underyling “bundle” technology allows for &lt;strong&gt;completely reproducible document compiles&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Choose one of the following options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open a &lt;a href="https://github.com/epassaro/texbuilder/issues/new/choose" rel="noopener noreferrer"&gt;&lt;strong&gt;Build request&lt;/strong&gt;&lt;/a&gt; and submit your LaTeX code.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/epassaro/texbuilder" rel="noopener noreferrer"&gt;&lt;strong&gt;Fork the repository&lt;/strong&gt;&lt;/a&gt;, apply your changes to &lt;code&gt;build/main.tex&lt;/code&gt; and open a pull request.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A link with your results will be posted on the corresponding issue/pull request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demo:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/epassaro/texbuilder/issues/1" rel="noopener noreferrer"&gt;https://github.com/epassaro/texbuilder/issues/1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/epassaro/texbuilder/pull/2" rel="noopener noreferrer"&gt;https://github.com/epassaro/texbuilder/pull/2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Wacky Wildcards&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/epassaro" rel="noopener noreferrer"&gt;
        epassaro
      &lt;/a&gt; / &lt;a href="https://github.com/epassaro/texbuilder" rel="noopener noreferrer"&gt;
        texbuilder
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Build and preview LaTeX documents with GitHub Actions
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;texbuilder&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;Build and preview LaTeX documents with GitHub Actions&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Open a &lt;a href="https://github.com/epassaro/texbuilder/issues/new/choose" rel="noopener noreferrer"&gt;&lt;strong&gt;Build request&lt;/strong&gt;&lt;/a&gt; and submit your LaTeX code.&lt;/li&gt;
&lt;li&gt;Fork this repository, apply your changes to &lt;code&gt;build/main.tex&lt;/code&gt; and open a pull request.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/epassaro/texbuilder" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/epassaro" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F153937%2F1a4b93de-c030-4bcb-9ace-6d22a0cc0e1e.png" alt="epassaro"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/epassaro/build-a-latex-document-by-opening-an-issue-or-pull-request-2gh6" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Build a LaTeX document by opening an issue (or pull request)&lt;/h2&gt;
      &lt;h3&gt;epassaro ・ Dec 7 '21&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#actionshackathon21&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#github&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#latex&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>actionshackathon21</category>
    </item>
    <item>
      <title>Build a LaTeX document by opening an issue (or pull request)</title>
      <dc:creator>epassaro</dc:creator>
      <pubDate>Tue, 07 Dec 2021 00:47:28 +0000</pubDate>
      <link>https://dev.to/epassaro/build-a-latex-document-by-opening-an-issue-or-pull-request-2gh6</link>
      <guid>https://dev.to/epassaro/build-a-latex-document-by-opening-an-issue-or-pull-request-2gh6</guid>
      <description>&lt;p&gt;I heard about &lt;a href="https://tectonic-typesetting.github.io/en-US/" rel="noopener noreferrer"&gt;Tectonic&lt;/a&gt; for the first time during the &lt;a href="https://packaging-con.org/" rel="noopener noreferrer"&gt;PackagingCon 2021&lt;/a&gt;  and immediately I knew that's the kind of stuff I want to deploy on GitHub Actions.&lt;/p&gt;

&lt;p&gt;LaTeX is a high-quality typesetting system, and it's the de facto standard for the communication and publication of scientific documents. Installing a full LaTeX system takes up a considerable amount time and space on your hard drive.&lt;/p&gt;

&lt;p&gt;Also, the reproducibility of these documents is not trivial. That's where Tectonic comes in:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Tectonic is a modernized, complete, self-contained TeX/LaTeX engine, powered by XeTeX and TeXLive. (...) Tectonic &lt;strong&gt;automatically downloads support files&lt;/strong&gt; so you don’t have to install a full LaTeX system in order to start using it. If you start using a new LaTeX package, Tectonic just pulls down the files it needs and continues processing. The underyling “bundle” technology allows for &lt;strong&gt;completely reproducible document compiles&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But... Why not just use Overleaf? Personally, I think the Git version control system fits perfectly when it comes to collaborative writing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The workflow
&lt;/h2&gt;

&lt;p&gt;This time, I wrote two different workflows: one to build from &lt;strong&gt;pull requests&lt;/strong&gt; and other to build from &lt;strong&gt;issues&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I'm going to focus on the second one, because the other is very similar and easier to follow.&lt;/p&gt;

&lt;p&gt;First, I created an &lt;a href="https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository" rel="noopener noreferrer"&gt;issue template&lt;/a&gt; to submit LaTeX code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F89l19gn41puxdyhw289w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F89l19gn41puxdyhw289w.png" alt=" " width="553" height="644"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, the workflow runs as you can see in the trigger section. Notice the job requires the &lt;code&gt;[Build]&lt;/code&gt; label on the issue title.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;issues&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;issues&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;opened&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;edited&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;REPO_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/${{ github.repository_owner }}/${{ github.event.repository.name }}&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;startsWith(github.event.issue.title, '[Build]')&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The latest version of Tectonic is installed. &lt;code&gt;dos2unix&lt;/code&gt; is required because the text from issue the body uses &lt;a href="https://www.datafix.com.au/BASHing/2019-03-17.html" rel="noopener noreferrer"&gt;CRLF&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;sudo apt-get install dos2unix&lt;/span&gt;

          &lt;span class="s"&gt;LAST_TAG=$(curl -s https://api.github.com/repos/tectonic-typesetting/tectonic/releases/latest | jq -r .tag_name)&lt;/span&gt;
          &lt;span class="s"&gt;VERSION="${LAST_TAG##tectonic@}"&lt;/span&gt;

          &lt;span class="s"&gt;wget -q https://github.com/tectonic-typesetting/tectonic/releases/latest/download/tectonic-$VERSION-x86_64-unknown-linux-gnu.tar.gz&lt;/span&gt;
          &lt;span class="s"&gt;tar -zxf tectonic-$VERSION-x86_64-unknown-linux-gnu.tar.gz -C /usr/local/bin&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The code from the body is extracted with a &lt;code&gt;sed&lt;/code&gt; command and built with Tectonic. The result is uploaded as an artifact.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Extract code&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;echo $ISSUE_BODY | dos2unix -c mac &amp;gt; issue_body.txt&lt;/span&gt;
          &lt;span class="s"&gt;sed -n '/%%build/, /%%dliub/{ /%%build/! { /%%dliub/! p } }' issue_body.txt &amp;gt; build/main.tex&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;ISSUE_BODY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event.issue.body }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build PDF&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tectonic -X compile build/main.tex&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build/main.pdf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Finally, the &lt;strong&gt;github-actions&lt;/strong&gt; bot post the result of the workflow run as a comment in the corresponding issue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftswl7dmpavnuj2vlj3dj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftswl7dmpavnuj2vlj3dj.png" alt=" " width="708" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Successive runs will update this comment, not creating new ones.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Find comment&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;peter-evans/find-comment@v1&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fc&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;issue-number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event.issue.number }}&lt;/span&gt;
          &lt;span class="na"&gt;comment-author&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;github-actions[bot]'&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always()&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Post comment (success)&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;peter-evans/create-or-update-comment@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;issue-number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event.issue.number }}&lt;/span&gt;
          &lt;span class="na"&gt;comment-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.fc.outputs.comment-id }}&lt;/span&gt;
          &lt;span class="na"&gt;edit-mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;replace&lt;/span&gt;
          &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;Hi, @${{ github.event.sender.login }}! :wave: &amp;lt;br&amp;gt;&lt;/span&gt;
            &lt;span class="s"&gt;The workflow run has **succeeded**. [**Click here**](${{ env.LOG_URL }}) to download your results.&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;LOG_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.REPO_URL }}/actions/runs/${{ github.run_id }}?check_suite_focus=true&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Post comment (failure)&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;peter-evans/create-or-update-comment@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;issue-number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event.issue.number }}&lt;/span&gt;
          &lt;span class="na"&gt;comment-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.fc.outputs.comment-id }}&lt;/span&gt;
          &lt;span class="na"&gt;edit-mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;replace&lt;/span&gt;
          &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;Sorry, @${{ github.event.sender.login }}! :disappointed: &amp;lt;br&amp;gt;&lt;/span&gt;
            &lt;span class="s"&gt;The workflow run has **failed**. [**Click here**](${{ env.LOG_URL }}) to see the build log.&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;LOG_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.REPO_URL }}/actions/runs/${{ github.run_id }}?check_suite_focus=true&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;failure()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Future improvements
&lt;/h2&gt;

&lt;p&gt;Currently, you need to download them and extract the ZIP file in order to see your results. This happens because workflows does not have access to the artifact ID while the job is running, and GitHub does not allow uploading unzipped archives.&lt;/p&gt;

&lt;p&gt;An alternative is pushing the PDF to a specific branch or folder, but populating the repository with binary files is not a good idea.&lt;/p&gt;
&lt;h2&gt;
  
  
  Get the code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/epassaro" rel="noopener noreferrer"&gt;
        epassaro
      &lt;/a&gt; / &lt;a href="https://github.com/epassaro/texbuilder" rel="noopener noreferrer"&gt;
        texbuilder
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Build and preview LaTeX documents with GitHub Actions
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;texbuilder&lt;/h1&gt;

&lt;/div&gt;

&lt;p&gt;Build and preview LaTeX documents with GitHub Actions&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Open a &lt;a href="https://github.com/epassaro/texbuilder/issues/new/choose" rel="noopener noreferrer"&gt;&lt;strong&gt;Build request&lt;/strong&gt;&lt;/a&gt; and submit your LaTeX code.&lt;/li&gt;
&lt;li&gt;Fork this repository, apply your changes to &lt;code&gt;build/main.tex&lt;/code&gt; and open a pull request.&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/epassaro/texbuilder" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>actionshackathon21</category>
      <category>github</category>
      <category>latex</category>
    </item>
    <item>
      <title>Keep your research reproducible with conda-pack and GitHub Actions</title>
      <dc:creator>epassaro</dc:creator>
      <pubDate>Sat, 27 Nov 2021 01:44:01 +0000</pubDate>
      <link>https://dev.to/epassaro/keep-your-research-reproducible-with-conda-pack-and-github-actions-339n</link>
      <guid>https://dev.to/epassaro/keep-your-research-reproducible-with-conda-pack-and-github-actions-339n</guid>
      <description>&lt;p&gt;Reproducibility is a major principle underpinning the scientific method, and scientific software is not an exception.&lt;/p&gt;

&lt;p&gt;Anaconda is a distribution of the Python and R programming languages for scientific computing with more than 25 million users. But, how reproducible is science made with Anaconda? And most important:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do you think you will be capable of reproducing the results your research in the next 10 years?&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Currently, the reproducibility of Anaconda environments &lt;a href="https://github.com/conda-forge/conda-forge.github.io/issues/787" rel="noopener noreferrer"&gt;is not guaranteed&lt;/a&gt;. &lt;code&gt;conda list --explicit&lt;/code&gt; provides just some kind of short term reproducibility.&lt;/p&gt;

&lt;p&gt;For example, if you use packages from non-standard channels, the owner could delete them at any moment. Also, the resolved URLs could vary due to changes in package labels or storage.&lt;/p&gt;

&lt;p&gt;There is an &lt;a href="https://github.com/conda/conda/issues/7248" rel="noopener noreferrer"&gt;ongoing debate&lt;/a&gt; about how to unify the different available tools to solve this problem. In this workflow, I propose a simple but effective way to keep your environments reproducible using GitHub Actions and &lt;a href="https://conda.github.io/conda-pack/" rel="noopener noreferrer"&gt;&lt;code&gt;conda-pack&lt;/code&gt;&lt;/a&gt;: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;conda-pack&lt;/code&gt; is a command line tool for creating archives of conda environments that can be installed on other systems and locations. This is useful for deploying code in a consistent environment —potentially where Python and/or conda isn’t already installed.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every time you publish a new release of your code (e.g. a paper) on GitHub, the environment is solved, packed and uploaded as an asset.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pack&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;published&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;BASENAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event.repository.name }}-${{ github.event.release.tag_name }}&lt;/span&gt; 

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Mambaforge&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;conda-incubator/setup-miniconda@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;miniforge-variant&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Mambaforge&lt;/span&gt;
            &lt;span class="na"&gt;miniforge-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;latest&lt;/span&gt;
            &lt;span class="na"&gt;environment-file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;environment.yml&lt;/span&gt;
            &lt;span class="na"&gt;activate-environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-env&lt;/span&gt;
            &lt;span class="na"&gt;use-mamba&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Freeze packages&lt;/span&gt;
        &lt;span class="na"&gt;shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash -l {0}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;conda env export -n my-env &amp;gt; $BASENAME.yml&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install conda-pack&lt;/span&gt;
        &lt;span class="na"&gt;shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash -l {0}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mamba install -c conda-forge conda-pack&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pack environment&lt;/span&gt;
        &lt;span class="na"&gt;shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash -l {0}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;conda pack -n my-env -o $BASENAME.tar.gz&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload assets&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AButler/upload-release-assets@v2.0&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;env.BASENAME&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}.{yml,tar.gz}'&lt;/span&gt;
          &lt;span class="na"&gt;repo-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;release-tag&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event.release.tag_name }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Finally, &lt;a href="https://conda.github.io/conda-pack/#commandline-usage" rel="noopener noreferrer"&gt;follow the instructions&lt;/a&gt; to deploy an identical environment at any point in the future.&lt;/p&gt;
&lt;h2&gt;
  
  
  Get the code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/epassaro" rel="noopener noreferrer"&gt;
        epassaro
      &lt;/a&gt; / &lt;a href="https://github.com/epassaro/repro-conda-envs" rel="noopener noreferrer"&gt;
        repro-conda-envs
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An example repository on how to keep Anaconda environments reproducible in the long term with GitHub Actions
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;repro-conda-envs&lt;/h1&gt;

&lt;/div&gt;

&lt;p&gt;An example repository on how to keep Anaconda environments reproducible in the long term with GitHub Actions&lt;/p&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/epassaro/repro-conda-envs" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>actionshackathon21</category>
      <category>research</category>
      <category>science</category>
    </item>
    <item>
      <title>Reproducible Anaconda environments with GitHub Actions</title>
      <dc:creator>epassaro</dc:creator>
      <pubDate>Sat, 27 Nov 2021 01:21:52 +0000</pubDate>
      <link>https://dev.to/epassaro/reproducible-anaconda-environments-with-github-actions-53i0</link>
      <guid>https://dev.to/epassaro/reproducible-anaconda-environments-with-github-actions-53i0</guid>
      <description>&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;Reproducibility is a major principle underpinning the scientific method, and scientific software is not an exception.&lt;/p&gt;

&lt;p&gt;Anaconda is a distribution of the Python and R programming languages for scientific computing with more than 25 million users. But, how reproducible is science made with Anaconda? And most important:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do you think you will be capable of reproducing the results your research in the next 10 years?&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Currently, the reproducibility of Anaconda environments &lt;a href="https://github.com/conda-forge/conda-forge.github.io/issues/787" rel="noopener noreferrer"&gt;is not guaranteed&lt;/a&gt;. &lt;code&gt;conda list --explicit&lt;/code&gt; provides just some kind of short term reproducibility.&lt;/p&gt;

&lt;p&gt;For example, if you use packages from non-standard channels, the owner could delete them at any moment. Also, the resolved URLs could vary due to changes in package labels or storage.&lt;/p&gt;

&lt;p&gt;There is an &lt;a href="https://github.com/conda/conda/issues/7248" rel="noopener noreferrer"&gt;ongoing debate&lt;/a&gt; about how to unify the different available tools to solve this problem.&lt;/p&gt;

&lt;p&gt;In this workflow, I propose a simple but effective way to keep your environments reproducible using GitHub Actions and &lt;a href="https://conda.github.io/conda-pack/" rel="noopener noreferrer"&gt;&lt;code&gt;conda-pack&lt;/code&gt;&lt;/a&gt;: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every time you publish a new release of your code (e.g. a paper) on GitHub, the environment is solved, packed and uploaded as an asset.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;DIY Deployments&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/epassaro" rel="noopener noreferrer"&gt;
        epassaro
      &lt;/a&gt; / &lt;a href="https://github.com/epassaro/repro-conda-envs" rel="noopener noreferrer"&gt;
        repro-conda-envs
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An example repository on how to keep Anaconda environments reproducible in the long term with GitHub Actions
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;repro-conda-envs&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;An example repository on how to keep Anaconda environments reproducible in the long term with GitHub Actions&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/epassaro/repro-conda-envs" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/epassaro" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F153937%2F1a4b93de-c030-4bcb-9ace-6d22a0cc0e1e.png" alt="epassaro"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/epassaro/keep-your-research-reproducible-with-conda-pack-and-github-actions-339n" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Keep your research reproducible with conda-pack and GitHub Actions&lt;/h2&gt;
      &lt;h3&gt;epassaro ・ Nov 27 '21&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#actionshackathon21&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#research&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#science&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>actionshackathon21</category>
    </item>
    <item>
      <title>Caching Anaconda environments on GitHub Actions</title>
      <dc:creator>epassaro</dc:creator>
      <pubDate>Wed, 24 Nov 2021 15:03:39 +0000</pubDate>
      <link>https://dev.to/epassaro/caching-anaconda-environments-on-github-actions-2d08</link>
      <guid>https://dev.to/epassaro/caching-anaconda-environments-on-github-actions-2d08</guid>
      <description>&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;One of the most time-consuming tasks on my workflows is the solving, download and installation of Anaconda environments. In some cases, just solving the dependencies can take up to 10 minutes depending on the platform you are building on.&lt;/p&gt;

&lt;p&gt;This workflow aims to save time and computational resources by caching deployed Anaconda environments using the &lt;a href="https://github.com/actions/cache" rel="noopener noreferrer"&gt;&lt;code&gt;actions/cache&lt;/code&gt;&lt;/a&gt; task and the &lt;a href="https://github.com/conda-incubator/setup-miniconda" rel="noopener noreferrer"&gt;&lt;code&gt;conda-incubator/setup-miniconda&lt;/code&gt;&lt;/a&gt; action.&lt;/p&gt;

&lt;p&gt;Shorter build times and better resource management will benefit not just your organization but also the environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Maintainer Must-Haves&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/epassaro" rel="noopener noreferrer"&gt;
        epassaro
      &lt;/a&gt; / &lt;a href="https://github.com/epassaro/cache-conda-envs" rel="noopener noreferrer"&gt;
        cache-conda-envs
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Speed up your builds by caching Anaconda environments on GitHub Actions
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;cache-conda-envs 🐍 ⚡&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;Speed up your builds by caching Anaconda environments on GitHub Actions&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/epassaro/cache-conda-envs" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;I'm glad to say that the results of my work have been &lt;a href="https://github.com/conda-incubator/setup-miniconda/pull/200" rel="noopener noreferrer"&gt;recently added&lt;/a&gt; to the &lt;code&gt;conda-incubator/setup-miniconda&lt;/code&gt; action's &lt;a href="https://github.com/conda-incubator/setup-miniconda#caching-environments" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; and should reach more developers soon.&lt;/p&gt;

&lt;p&gt;It's worth mentioning that the documentation of &lt;code&gt;actions/cache&lt;/code&gt; included examples for many package managers, but not for &lt;code&gt;conda&lt;/code&gt;. On the other hand, the &lt;code&gt;setup-miniconda&lt;/code&gt; documentation described a way to cache the downloaded packages, but that method makes pipelines even slower.&lt;/p&gt;

&lt;p&gt;Finally, I published a post describing the workflow step-by-step.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/epassaro" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F153937%2F1a4b93de-c030-4bcb-9ace-6d22a0cc0e1e.png" alt="epassaro"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/epassaro/caching-anaconda-environments-in-github-actions-5hde" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Reduce your build times on GitHub Actions by caching Anaconda environments&lt;/h2&gt;
      &lt;h3&gt;epassaro ・ Nov 8 '21&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#actionshackathon21&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>actionshackathon21</category>
    </item>
    <item>
      <title>Measure docstring coverage of Python packages with GitHub Actions</title>
      <dc:creator>epassaro</dc:creator>
      <pubDate>Fri, 19 Nov 2021 04:42:41 +0000</pubDate>
      <link>https://dev.to/epassaro/measure-docstring-coverage-of-python-packages-with-github-actions-1cp8</link>
      <guid>https://dev.to/epassaro/measure-docstring-coverage-of-python-packages-with-github-actions-1cp8</guid>
      <description>&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;Workflows that enforce &lt;a href="https://black.readthedocs.io/en/stable/integrations/github_actions.html" rel="noopener noreferrer"&gt;code style&lt;/a&gt; and &lt;a href="https://github.com/codecov/codecov-action" rel="noopener noreferrer"&gt;coverage&lt;/a&gt; are widely used on GitHub, but... what about code documentation?&lt;/p&gt;

&lt;p&gt;This workflow does the job by using the &lt;code&gt;docstr-coverage&lt;/code&gt; package.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Fails when the docstring coverage is lower than the score of the base branch (on pull requests) or the previous commit (on push). Files that made the job fail are blamed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pushing changes to the main branch updates the current coverage of the project by creating a dynamic badge with through the &lt;a href="https://shields.io/endpoint" rel="noopener noreferrer"&gt;shields.io&lt;/a&gt; endpoint.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is possible to define the range of the badge color based on the coverage results.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Maintainer Must-Haves&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/epassaro" rel="noopener noreferrer"&gt;
        epassaro
      &lt;/a&gt; / &lt;a href="https://github.com/epassaro/docstr-cov-workflow" rel="noopener noreferrer"&gt;
        docstr-cov-workflow
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Measure docstring coverage of Python packages with GitHub Actions
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;docstr-cov-workflow&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Measure docstring coverage of Python packages with GitHub Actions&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Usage&lt;/h3&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Copy &lt;code&gt;.github/workflows/docstr-cov.yml&lt;/code&gt; and  &lt;code&gt;.docstr.yaml&lt;/code&gt; to your repository.&lt;/li&gt;
&lt;li&gt;Tweak the configuration file following the &lt;a href="https://github.com/HunterMcGushion/docstr_coverage#config-file" rel="noopener noreferrer"&gt;package documentation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Login to &lt;a href="https://jsonbin.org" rel="nofollow noopener noreferrer"&gt;https://jsonbin.org&lt;/a&gt; and store the API key as a repository secret named &lt;code&gt;JSONBIN_APIKEY&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The workflow will fail if the coverage is lower than the score of the base branch (on &lt;code&gt;pull_request&lt;/code&gt;) or the previous commit (on &lt;code&gt;push&lt;/code&gt;), and files that made the job fail will be blamed.&lt;/li&gt;
&lt;li&gt;Pushing to &lt;code&gt;main&lt;/code&gt; branch updates the current coverage of the project by updating a nice badge.&lt;/li&gt;
&lt;li&gt;You can change the color range of the badge by tweaking the &lt;code&gt;RANGE&lt;/code&gt; variable at the top of the workflow. For example, &lt;code&gt;50..75&lt;/code&gt; means that coverage below &lt;code&gt;50&lt;/code&gt; will display a red badge, and above &lt;code&gt;75&lt;/code&gt; a green one.&lt;/li&gt;
&lt;li&gt;Remember to add the badge to your README.md&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Example&lt;/h3&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/36599f4fe9707b3be90a4ae203dcb76b0cf3c631bb1f21dd45561a4f06c3cf4b/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f75726c3d68747470733a2f2f6a736f6e62696e2e6f72672f657061737361726f2f646f637374722d636f762d776f726b666c6f772f6261646765732f646f637374722d636f76"&gt;&lt;img src="https://camo.githubusercontent.com/36599f4fe9707b3be90a4ae203dcb76b0cf3c631bb1f21dd45561a4f06c3cf4b/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f75726c3d68747470733a2f2f6a736f6e62696e2e6f72672f657061737361726f2f646f637374722d636f762d776f726b666c6f772f6261646765732f646f637374722d636f76" alt="docstr-cov"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Make changes to &lt;code&gt;example/base.py&lt;/code&gt; and see the workflow…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/epassaro/docstr-cov-workflow" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;An &lt;a href="https://github.com/tardis-sn/tardis/blob/master/.github/workflows/docstr-coverage.yml" rel="noopener noreferrer"&gt;older version&lt;/a&gt; of this workflow is currently used by &lt;a href="https://github.com/tardis-sn" rel="noopener noreferrer"&gt;TARDIS-SN&lt;/a&gt;, a Montecarlo radiative transfer code that creates synthetic spectra for supernovae.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/epassaro" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F153937%2F1a4b93de-c030-4bcb-9ace-6d22a0cc0e1e.png" alt="epassaro"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/epassaro/how-to-keep-track-of-docstring-coverage-of-python-packages-on-ci-41fc" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How to keep track of docstring coverage of Python packages on CI&lt;/h2&gt;
      &lt;h3&gt;epassaro ・ Nov 19 '21&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#actionshackathon21&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#python&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>actionshackathon21</category>
    </item>
    <item>
      <title>How to keep track of docstring coverage of Python packages on CI</title>
      <dc:creator>epassaro</dc:creator>
      <pubDate>Fri, 19 Nov 2021 04:13:11 +0000</pubDate>
      <link>https://dev.to/epassaro/how-to-keep-track-of-docstring-coverage-of-python-packages-on-ci-41fc</link>
      <guid>https://dev.to/epassaro/how-to-keep-track-of-docstring-coverage-of-python-packages-on-ci-41fc</guid>
      <description>&lt;p&gt;Months ago, a collaborator asked for a way to keep track of the docstring coverage of our Python package. We wanted to measure the current coverage of the docstrings in our code and prevent pull requests from decreasing that value. &lt;/p&gt;

&lt;p&gt;To solve this problem, a workflow needed to fulfill the following requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The workflow should fail if the coverage is lower than the score of the base branch (on &lt;code&gt;pull requests&lt;/code&gt;) or the previous commit (on &lt;code&gt;push&lt;/code&gt;), and files that made the job fail should be blamed.&lt;/li&gt;
&lt;li&gt;Pushing to main branch should update the current coverage of the project and display the result on a nice badge.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then, I found the excellent &lt;a href="https://github.com/HunterMcGushion/docstr_coverage" rel="noopener noreferrer"&gt;&lt;code&gt;docstr-coverage&lt;/code&gt;&lt;/a&gt; package that suited most of our needs, and in combination with GitHub Actions, &lt;a href="https://shields.io" rel="noopener noreferrer"&gt;shields.io&lt;/a&gt; and &lt;a href="https://jsonbin.org/" rel="noopener noreferrer"&gt;jsonbin.org&lt;/a&gt; I came up with a solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  jsonbin
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://jsonbin.org/" rel="noopener noreferrer"&gt;jsonbin.org&lt;/a&gt; is a personal key/value JSON store as a service.&lt;/p&gt;

&lt;p&gt;In this case, we use this service to create dynamic badges with the &lt;a href="https://shields.io/endpoint" rel="noopener noreferrer"&gt;shields.io endpoint&lt;/a&gt;. A small JSON dictionary is passed to the endpoint and the badge is created on-the-go. Thus, we avoid to push a new badge to the repository each time the coverage changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"schemaVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docstr-cov"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"75%"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You will need to sign in to &lt;strong&gt;jsonbin&lt;/strong&gt; with your GitHub account and store the token as a repository secret named &lt;code&gt;JSONBIN_APIKEY&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuration file
&lt;/h2&gt;

&lt;p&gt;Place a file named &lt;code&gt;.docstr.yml&lt;/code&gt; at the root of your repository.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;your_package&lt;/span&gt;
&lt;span class="na"&gt;verbose&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="c1"&gt;# int (0-3)&lt;/span&gt;
&lt;span class="na"&gt;skip_magic&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;True&lt;/span&gt;
&lt;span class="na"&gt;skip_file_doc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;True&lt;/span&gt;
&lt;span class="na"&gt;skip_init&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;True&lt;/span&gt;
&lt;span class="na"&gt;skip_class_def&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;False&lt;/span&gt;
&lt;span class="na"&gt;skip_private&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;True&lt;/span&gt;
&lt;span class="na"&gt;follow_links&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;True&lt;/span&gt;
&lt;span class="na"&gt;percentage_only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For more information, see the &lt;a href="https://github.com/HunterMcGushion/docstr_coverage#config-file" rel="noopener noreferrer"&gt;package documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  The workflow
&lt;/h2&gt;

&lt;p&gt;This workflow should work out the box. It's not necessary to tweak any environment variable, but you can choose different values for &lt;code&gt;RANGE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, a &lt;code&gt;RANGE&lt;/code&gt; of &lt;code&gt;50..75&lt;/code&gt; means that coverage below &lt;code&gt;50&lt;/code&gt; will display a red badge, and above &lt;code&gt;75&lt;/code&gt; a green one. It works exactly like Codecov!&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docstr-cov&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;RANGE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;50..75&lt;/span&gt;
  &lt;span class="na"&gt;ENDPOINT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://jsonbin.org/${{ github.repository_owner }}/${{ github.event.repository.name }}&lt;/span&gt;
  &lt;span class="na"&gt;TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.JSONBIN_APIKEY }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;At the job level, the steps are easy to follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Commits to compare (&lt;code&gt;HEAD&lt;/code&gt; and &lt;code&gt;BASE&lt;/code&gt;) are chosen depending on the event trigger: &lt;code&gt;HEAD&lt;/code&gt; of the branch vs. previous commit on &lt;code&gt;push&lt;/code&gt; events, or &lt;code&gt;HEAD&lt;/code&gt; of the PR vs. base of the branch on &lt;code&gt;pull_request&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Get coverage score on &lt;code&gt;BASE&lt;/code&gt; and &lt;code&gt;HEAD&lt;/code&gt;. Fails if HEAD score is lower.&lt;/li&gt;
&lt;li&gt;Blame files (if failed).
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;check&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;fetch-depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Python&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3.x&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install docstr-coverage&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pip install docstr-coverage&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Get SHAs&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;if [[ ${{ github.event_name }} == 'push' ]]; then&lt;/span&gt;
            &lt;span class="s"&gt;echo "BASE=$(git rev-parse HEAD^)" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
            &lt;span class="s"&gt;echo "HEAD=$(git rev-parse HEAD)" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;

          &lt;span class="s"&gt;elif [[ ${{ github.event_name }} == 'pull_request' ]]; then&lt;/span&gt;
            &lt;span class="s"&gt;echo "BASE=${{ github.event.pull_request.base.sha }}" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
            &lt;span class="s"&gt;echo "HEAD=${{ github.event.pull_request.head.sha }}" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;

          &lt;span class="s"&gt;else&lt;/span&gt;
            &lt;span class="s"&gt;echo "Unexpected event trigger"&lt;/span&gt;
            &lt;span class="s"&gt;exit 1&lt;/span&gt;
          &lt;span class="s"&gt;fi&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Get base coverage&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git checkout $BASE&lt;/span&gt;
          &lt;span class="s"&gt;echo "BASE_COV=$(docstr-coverage -p)" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test head coverage&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git checkout $HEAD&lt;/span&gt;
          &lt;span class="s"&gt;docstr-coverage --fail-under=$BASE_COV&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Blame&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git diff --name-only $(git merge-base $BASE $HEAD) | \&lt;/span&gt;
          &lt;span class="s"&gt;xargs docstr-coverage --accept-empty&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;failure()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Only on &lt;code&gt;push&lt;/code&gt; events:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get coverage (rounded)&lt;/li&gt;
&lt;li&gt;Set the color label according to &lt;code&gt;RANGE&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Post results to &lt;strong&gt;jsonbin&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Make the endpoint public.&lt;/li&gt;
&lt;li&gt;Print the badge URL.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Get new coverage&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "NEW_COV=$(printf "%.f" $(docstr-coverage -p))" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always() &amp;amp;&amp;amp; github.event_name == 'push'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set label color&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;if [[ $NEW_COV -ge $(echo {${{ env.RANGE }}} | awk '{print $NF;}') ]]; then&lt;/span&gt;
            &lt;span class="s"&gt;echo "COLOR=green" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
          &lt;span class="s"&gt;elif [[ $NEW_COV -lt $(echo {${{ env.RANGE }}} | awk '{print $1;}') ]]; then&lt;/span&gt;
            &lt;span class="s"&gt;echo "COLOR=red" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
          &lt;span class="s"&gt;else&lt;/span&gt;
            &lt;span class="s"&gt;echo "COLOR=orange" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
          &lt;span class="s"&gt;fi&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always() &amp;amp;&amp;amp; github.event_name == 'push'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Post results&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;curl -X POST $ENDPOINT/badges/docstr-cov \&lt;/span&gt;
          &lt;span class="s"&gt;-H "authorization: token $TOKEN" \&lt;/span&gt;
          &lt;span class="s"&gt;-d "{ \"schemaVersion\": 1, \"label\": \"docstr-cov\", \&lt;/span&gt;
                &lt;span class="s"&gt;\"message\": \"$NEW_COV%\", \"color\": \"$COLOR\" }"&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always() &amp;amp;&amp;amp; github.event_name == 'push'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set public endpoint&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;curl -X PUT $ENDPOINT/_perms -H "authorization: token $TOKEN"&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always() &amp;amp;&amp;amp; github.event_name == 'push'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Show badge URL&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "https://img.shields.io/endpoint?url=$ENDPOINT/badges/docstr-cov"&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always() &amp;amp;&amp;amp; github.event_name == 'push'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The badge should be updated dynamically on every push to &lt;code&gt;main&lt;/code&gt;. Remember to add it to your README.md.&lt;/p&gt;
&lt;h2&gt;
  
  
  Get the code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/epassaro" rel="noopener noreferrer"&gt;
        epassaro
      &lt;/a&gt; / &lt;a href="https://github.com/epassaro/docstr-cov-workflow" rel="noopener noreferrer"&gt;
        docstr-cov-workflow
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Measure docstring coverage of Python packages with GitHub Actions
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;docstr-cov-workflow&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;Measure docstring coverage of Python packages with GitHub Actions&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Usage&lt;/h3&gt;
&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Copy &lt;code&gt;.github/workflows/docstr-cov.yml&lt;/code&gt; and  &lt;code&gt;.docstr.yaml&lt;/code&gt; to your repository.&lt;/li&gt;
&lt;li&gt;Tweak the configuration file following the &lt;a href="https://github.com/HunterMcGushion/docstr_coverage#config-file" rel="noopener noreferrer"&gt;package documentation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Login to &lt;a href="https://jsonbin.org" rel="nofollow noopener noreferrer"&gt;https://jsonbin.org&lt;/a&gt; and store the API key as a repository secret named &lt;code&gt;JSONBIN_APIKEY&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The workflow will fail if the coverage is lower than the score of the base branch (on &lt;code&gt;pull_request&lt;/code&gt;) or the previous commit (on &lt;code&gt;push&lt;/code&gt;), and files that made the job fail will be blamed.&lt;/li&gt;
&lt;li&gt;Pushing to &lt;code&gt;main&lt;/code&gt; branch updates the current coverage of the project by updating a nice badge.&lt;/li&gt;
&lt;li&gt;You can change the color range of the badge by tweaking the &lt;code&gt;RANGE&lt;/code&gt; variable at the top of the workflow. For example, &lt;code&gt;50..75&lt;/code&gt; means that coverage below &lt;code&gt;50&lt;/code&gt; will display a red badge, and above &lt;code&gt;75&lt;/code&gt; a green one.&lt;/li&gt;
&lt;li&gt;Remember to add the badge to your README.md&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Example&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/36599f4fe9707b3be90a4ae203dcb76b0cf3c631bb1f21dd45561a4f06c3cf4b/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f75726c3d68747470733a2f2f6a736f6e62696e2e6f72672f657061737361726f2f646f637374722d636f762d776f726b666c6f772f6261646765732f646f637374722d636f76"&gt;&lt;img src="https://camo.githubusercontent.com/36599f4fe9707b3be90a4ae203dcb76b0cf3c631bb1f21dd45561a4f06c3cf4b/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f75726c3d68747470733a2f2f6a736f6e62696e2e6f72672f657061737361726f2f646f637374722d636f762d776f726b666c6f772f6261646765732f646f637374722d636f76" alt="docstr-cov"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make changes to &lt;code&gt;example/base.py&lt;/code&gt; and see the workflow…&lt;/p&gt;
&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/epassaro/docstr-cov-workflow" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>actionshackathon21</category>
      <category>python</category>
    </item>
    <item>
      <title>A RTD-like documentation pipeline for GitHub Actions</title>
      <dc:creator>epassaro</dc:creator>
      <pubDate>Mon, 15 Nov 2021 16:14:23 +0000</pubDate>
      <link>https://dev.to/epassaro/a-rtd-like-documentation-pipeline-for-github-actions-4ci1</link>
      <guid>https://dev.to/epassaro/a-rtd-like-documentation-pipeline-for-github-actions-4ci1</guid>
      <description>&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;In the recent years, lot of Python packages moved their documentation pipelines from third party services like ReadTheDocs to GitHub Pages, but some useful features were missing in the process.&lt;/p&gt;

&lt;p&gt;This workflow intends to be a full featured replacement for RTD on GitHub Actions, giving back the control of the documentation deployment process to developers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Support of &lt;code&gt;pip&lt;/code&gt; and &lt;code&gt;conda&lt;/code&gt; dependency files.&lt;/li&gt;
&lt;li&gt;Build and deploy branches under &lt;code&gt;/branches/&amp;lt;branch&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Build and deploy tags under &lt;code&gt;/tags/&amp;lt;tag&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Secure build and preview of pull requests under &lt;code&gt;/pull/&amp;lt;number&amp;gt;&lt;/code&gt; via labels.&lt;/li&gt;
&lt;li&gt;Manual trigger for branches.&lt;/li&gt;
&lt;li&gt;Select branch to deploy the site (default: &lt;code&gt;gh-pages&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Redirect the main domain to &lt;code&gt;/latest&lt;/code&gt; or &lt;code&gt;/stable&lt;/code&gt; (default: &lt;code&gt;/latest&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Redirect the &lt;code&gt;/stable&lt;/code&gt; subdomain to the latest SemVer tag, or the &lt;code&gt;stable&lt;/code&gt; branch (if exists).&lt;/li&gt;
&lt;li&gt;Automatic removal of pages from closed/merged pull requests, and deleted branches or tags.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Not supported:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Multi-language builds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live demo:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://epassaro.github.io/actions-rtd-workflow" rel="noopener noreferrer"&gt;https://epassaro.github.io/actions-rtd-workflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://epassaro.github.io/actions-rtd-workflow/latest" rel="noopener noreferrer"&gt;https://epassaro.github.io/actions-rtd-workflow/latest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://epassaro.github.io/actions-rtd-workflow/stable" rel="noopener noreferrer"&gt;https://epassaro.github.io/actions-rtd-workflow/stable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://epassaro.github.io/actions-rtd-workflow/pull/1" rel="noopener noreferrer"&gt;https://epassaro.github.io/actions-rtd-workflow/pull/1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://epassaro.github.io/actions-rtd-workflow/tag/v0.1.0" rel="noopener noreferrer"&gt;https://epassaro.github.io/actions-rtd-workflow/tag/v0.1.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;DIY Deployments&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/epassaro" rel="noopener noreferrer"&gt;
        epassaro
      &lt;/a&gt; / &lt;a href="https://github.com/epassaro/actions-rtd-workflow" rel="noopener noreferrer"&gt;
        actions-rtd-workflow
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A RTD-like documentation pipeline for GitHub Actions
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;actions-rtd-workflow&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;A RTD-like documentation pipeline for GitHub Actions&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Features&lt;/h3&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Support of &lt;code&gt;pip&lt;/code&gt; and &lt;code&gt;conda&lt;/code&gt; dependency files.&lt;/li&gt;
&lt;li&gt;Build and deploy branches under &lt;code&gt;/branches/&amp;lt;branch&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Build and deploy tags under &lt;code&gt;/tags/&amp;lt;tag&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Secure build and preview of pull requests under &lt;code&gt;/pull/&amp;lt;number&amp;gt;&lt;/code&gt; via labels.&lt;/li&gt;
&lt;li&gt;Manual trigger for branches.&lt;/li&gt;
&lt;li&gt;Select branch to deploy the site (default: &lt;code&gt;gh-pages&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Redirect the main domain to &lt;code&gt;/latest&lt;/code&gt; or &lt;code&gt;/stable&lt;/code&gt; (default: &lt;code&gt;/latest&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Redirect the &lt;code&gt;/stable&lt;/code&gt; subdomain to the latest SemVer tag, or the stable branch (if exists).&lt;/li&gt;
&lt;li&gt;Automatic removal of pages from closed/merged pull requests, and deleted branches or tags.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Not supported&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;Multi-language builds.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Live demo&lt;/h3&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://epassaro.github.io/actions-rtd-workflow" rel="nofollow noopener noreferrer"&gt;https://epassaro.github.io/actions-rtd-workflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://epassaro.github.io/actions-rtd-workflow/latest" rel="nofollow noopener noreferrer"&gt;https://epassaro.github.io/actions-rtd-workflow/latest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://epassaro.github.io/actions-rtd-workflow/stable" rel="nofollow noopener noreferrer"&gt;https://epassaro.github.io/actions-rtd-workflow/stable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://epassaro.github.io/actions-rtd-workflow/pull/1" rel="nofollow noopener noreferrer"&gt;https://epassaro.github.io/actions-rtd-workflow/pull/1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://epassaro.github.io/actions-rtd-workflow/tag/v0.1.0" rel="nofollow noopener noreferrer"&gt;https://epassaro.github.io/actions-rtd-workflow/tag/v0.1.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/epassaro/actions-rtd-workflow" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/epassaro" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F153937%2F1a4b93de-c030-4bcb-9ace-6d22a0cc0e1e.png" alt="epassaro"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/epassaro/deploy-your-package-documentation-on-github-pages-in-the-rtd-style-preview-prs-and-more-ogf" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Deploy your package documentation on GitHub Pages in the RTD style: preview PRs, and more!&lt;/h2&gt;
      &lt;h3&gt;epassaro ・ Nov 15 '21&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#actionshackathon21&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#github&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>actionshackathon21</category>
    </item>
  </channel>
</rss>
