<?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>Forem: Ricardo N Feliciano</title>
    <description>The latest articles on Forem by Ricardo N Feliciano (@felicianotech).</description>
    <link>https://forem.com/felicianotech</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%2F105644%2F30d38d2d-f95e-4316-a093-8847f6e2ba1a.jpg</url>
      <title>Forem: Ricardo N Feliciano</title>
      <link>https://forem.com/felicianotech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/felicianotech"/>
    <language>en</language>
    <item>
      <title>Introducing para: A package metrics tool</title>
      <dc:creator>Ricardo N Feliciano</dc:creator>
      <pubDate>Tue, 11 Aug 2020 16:00:00 +0000</pubDate>
      <link>https://forem.com/felicianotech/introducing-para-a-package-metrics-tool-pkd</link>
      <guid>https://forem.com/felicianotech/introducing-para-a-package-metrics-tool-pkd</guid>
      <description>&lt;p&gt;&lt;code&gt;para&lt;/code&gt; is short for Packages and Releases Analytics. It's a simple tool to solve a simple problem for those who release software via Snaps, Brew, GitHub Releases, etc. Metrics and availability.&lt;/p&gt;

&lt;p&gt;If you release software via Brew or GitHub Releases, &lt;code&gt;para&lt;/code&gt; lets you view metrics from those platforms so you can see how well those packages are doing. Here's an example of pulling the metrics for the static site generator &lt;a href="https://github.com/gothamhq/gotham"&gt;Gotham&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;Brew data:
The number of installs &lt;span class="k"&gt;in &lt;/span&gt;the last 30 days is: 4

GitHub data:
v0.6.0:
gotham-v0.6.0-linux-amd64-checksum.txt: 0
gotham-v0.6.0-linux-amd64.tar.gz: 2
gotham-v0.6.0-macos-amd64-checksum.txt: 0
gotham-v0.6.0-macos-amd64.tar.gz: 3
v0.5.0:
gotham-v0.5.0-linux-amd64-checksum.txt: 0
gotham-v0.5.0-linux-amd64.tar.gz: 2
gotham-v0.5.0-macos-amd64-checksum.txt: 0
gotham-v0.5.0-macos-amd64.tar.gz: 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Don't have a software project yet? No worries, &lt;code&gt;para&lt;/code&gt; is still helpful for you. When you're still in the naming phase, &lt;code&gt;para check&lt;/code&gt; will check if a name is available on Snap, Brew, Chocolatey, and NPM. This way you can easily find a name that's available without hacking to tack on a username or some other weird suffix to your project's name.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;para&lt;/code&gt; is still very much a work-in-progress with only an unpolished v0.1.0 release so far. Snap metrics isn't yet supported but it's on the roadmap. It's written in Go, packed as a raw binary, deb and snap, currently supports Linux and macOS on amd64, and is open source (MIT licensed).&lt;/p&gt;

&lt;p&gt;You can learn more and contribute at its &lt;a href="https://github.com/halseylabs/para"&gt;GitHub Repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>snap</category>
      <category>brew</category>
      <category>github</category>
      <category>opensource</category>
    </item>
    <item>
      <title>CircleCI is used throughout the Galaxy</title>
      <dc:creator>Ricardo N Feliciano</dc:creator>
      <pubDate>Tue, 05 May 2020 00:14:01 +0000</pubDate>
      <link>https://forem.com/felicianotech/circleci-is-used-throughout-the-galaxy-g45</link>
      <guid>https://forem.com/felicianotech/circleci-is-used-throughout-the-galaxy-g45</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--505_yHXy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h77yde11b4vycwjxd29u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--505_yHXy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h77yde11b4vycwjxd29u.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>circleci</category>
      <category>devops</category>
      <category>ci</category>
      <category>starwars</category>
    </item>
    <item>
      <title>Introducing DocsThursday: A Monthly Documentation "Party"</title>
      <dc:creator>Ricardo N Feliciano</dc:creator>
      <pubDate>Thu, 07 Feb 2019 17:49:17 +0000</pubDate>
      <link>https://forem.com/felicianotech/introducing-docsthursday-a-monthly-documentation-party-2fmb</link>
      <guid>https://forem.com/felicianotech/introducing-docsthursday-a-monthly-documentation-party-2fmb</guid>
      <description>&lt;p&gt;I love open source documentation and if you're reading this, maybe you do too.&lt;br&gt;
I have a personal mantra of "Inspire, Educate, Motivate" and documentation fits right into that.&lt;br&gt;
Documentation allows us to &lt;strong&gt;educate&lt;/strong&gt; others to a near infinite scale.&lt;/p&gt;

&lt;p&gt;You know, I partially owe my career to the free and accessible Linux server documentation that is available on the &lt;a href="https://www.linode.com/docs/"&gt;Linode Docs&lt;/a&gt; website.&lt;br&gt;
I'm a die-hard Ubuntu user but I can't tell you the countless times the &lt;a href="https://wiki.archlinux.org/"&gt;Arch Linux Wiki&lt;/a&gt; has helped me out of tight spots.&lt;/p&gt;

&lt;p&gt;Docs are invaluable.&lt;/p&gt;

&lt;p&gt;I want to &lt;strong&gt;motivate&lt;/strong&gt; more people to contribute and learn from one another on how we can make better contributions and better doc websites.&lt;br&gt;
&lt;a href="https://DocsThursday.com"&gt;DocsThursday&lt;/a&gt; is a party, campaign, workshop, or whatever you want to call it to create and contribute to open source documentation on the 3rd Thursday of every month.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why DocsThursday?
&lt;/h2&gt;

&lt;p&gt;There's nothing special about Thursdays.&lt;br&gt;
I could have done a Docs Wednesday or Friday but it wasn't as catchy and we all know Tuesdays are for tacos.&lt;br&gt;
So Thursday it is.&lt;/p&gt;

&lt;p&gt;DocsThursday is inspired by DigitalOcean's &lt;a href="https://hacktoberfest.digitalocean.com/"&gt;Hacktoberfest&lt;/a&gt;, &lt;a href="https://24pullrequests.com/"&gt;24 Pull Requests&lt;/a&gt;, and most importantly, Write the Docs's &lt;a href="https://www.writethedocs.org/conf/portland/2019/writing-day/"&gt;Writing Day&lt;/a&gt;.&lt;br&gt;
I'm trying to take the energy and productivity of Writing Day and replicate it more frequently at meetups local to you, with your co-workers within your company, and even online as a hackathon.&lt;/p&gt;

&lt;p&gt;Let's take 30 minutes, an hour or even more, just once a month in order to give some love to open source documentation.&lt;/p&gt;

&lt;p&gt;Interested? Check out the website, &lt;a href="https://DocsThursday.com"&gt;DocsThursday.com&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Would you like to help out?
&lt;/h2&gt;

&lt;p&gt;DocsThursday is brand new and I'm still figuring out what to do with it.&lt;br&gt;
The &lt;a href="https://github.com/felicianotech/docsthursday.com"&gt;website is open source&lt;/a&gt; and built with &lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt;.&lt;br&gt;
Feel free to open PRs to improve the website or open Issues to ask questions or start discussions.&lt;br&gt;
You can also start discussions/ask questions here in the comments or &lt;a href="https://twitter.com/FelicianoTech"&gt;message me on Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you've had these feelings or similar ideas, speak up!&lt;br&gt;
Let's do this together. 😄&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt; The first DocsThursday is February 21st.&lt;br&gt;
I run the Write the Docs NYC meetup and we're hosting an event in New York for DocsThursday.&lt;br&gt;
If you're around, &lt;a href="https://www.meetup.com/WriteTheDocsNYC/events/258747106/"&gt;check it out&lt;/a&gt;.&lt;br&gt;
If you're not, start one in your area on the 21st and I'll list it on the DocsThursday website for people to find.&lt;/p&gt;

</description>
      <category>documentation</category>
    </item>
    <item>
      <title>Hey open source maintainers! Empower your contributors with continuous integration</title>
      <dc:creator>Ricardo N Feliciano</dc:creator>
      <pubDate>Tue, 04 Dec 2018 17:00:00 +0000</pubDate>
      <link>https://forem.com/circleci/hey-open-source-maintainers-empower-your-contributors-with-continuous-integration-g8p</link>
      <guid>https://forem.com/circleci/hey-open-source-maintainers-empower-your-contributors-with-continuous-integration-g8p</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcircleci.com%2Fblog%2Fmedia%2FOpenSource_1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcircleci.com%2Fblog%2Fmedia%2FOpenSource_1.jpg" alt="OpenSource_1.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Surprisingly, many &lt;a href="https://circleci.com/docs/2.0/oss/" rel="noopener noreferrer"&gt;open source&lt;/a&gt; projects don't implement a &lt;a href="https://circleci.com/continuous-integration/" rel="noopener noreferrer"&gt;continuous integration&lt;/a&gt; (CI) solution. Perhaps your project is one of these. You might be thinking, "We don't need it, we know what we're doing," or even, "We're too small, we'll implement it later."&lt;/p&gt;

&lt;p&gt;When maintainers do use CI, it's often an insufficient implementation, such as using it for deployment without any testing.&lt;/p&gt;

&lt;p&gt;I should know; I've been guilty of this myself.&lt;/p&gt;

&lt;p&gt;But I want to show you that the decision to implement CI for an &lt;a href="https://circleci.com/docs/2.0/oss/" rel="noopener noreferrer"&gt;open source&lt;/a&gt; project is not about you. It's about providing the right tools for contributions. It's about enabling your project growing steadily with healthy code.&lt;/p&gt;

&lt;p&gt;Using CI in your &lt;a href="https://circleci.com/docs/2.0/oss/" rel="noopener noreferrer"&gt;open source&lt;/a&gt; projects will help empower your contributors to make better PRs more easily and help your project grow and thrive.&lt;/p&gt;

&lt;p&gt;Read on for four ways that CI can empower your &lt;a href="https://circleci.com/docs/2.0/oss/" rel="noopener noreferrer"&gt;open source&lt;/a&gt; contributors:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. CI will actually run tests
&lt;/h2&gt;

&lt;p&gt;This may seem obvious but it's quite important to mention.&lt;br&gt;
Maintainers that have invested time in thinking about testing for their project need to convey that to potential contributors.&lt;/p&gt;

&lt;p&gt;How? You could remind people to run tests:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In &lt;code&gt;README.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;In &lt;code&gt;CONTRIBUTING.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Or in a &lt;a href="https://help.github.com/articles/creating-a-pull-request-template-for-your-repository/" rel="noopener noreferrer"&gt;Pull Request (PR) template&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But even with those steps taken, how many people will actually read them and follow through? Running a project's tests with a CI provider like CircleCI means you don't have to worry about a contributor being lazy or forgetful. It's a safety net for the quality of your project's code.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. CI build failures are okay; use them as a teaching point
&lt;/h2&gt;

&lt;p&gt;It can be intimidating to contribute to an &lt;a href="https://circleci.com/docs/2.0/oss/" rel="noopener noreferrer"&gt;open source&lt;/a&gt; project for the first time. Let contributors know that PRs are welcome, but more importantly, that they don't need to get it right on the first try. If a PR status check turns red, great! The first thing you can do is make sure users know how to click over to the CI provider and check for the error (the test passing/failing link in the footer of a PR). Don't assume anything. Then you can give that person advice on how to fix the issue and give them time to do so. The idea here is that this is a teaching point. Remember: they may not knock out bugs at the same pace as you can. The contributor can learn and become stronger while this interaction sets the tone for your project and its community. Be friendly and fix things together.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. CI allows contributors to work on projects they may otherwise not be able to
&lt;/h2&gt;

&lt;p&gt;I'll explain this one with a real-world example. Let's look at the &lt;a href="https://github.com/CircleCI-Public/circleci-cli/" rel="noopener noreferrer"&gt;CircleCI CLI&lt;/a&gt;, an &lt;a href="https://circleci.com/docs/2.0/oss/" rel="noopener noreferrer"&gt;open source&lt;/a&gt; project that is compiled for both macOS and Linux. If a user was to report a bug that specifically affects the macOS build of the CLI I could try and fix it. As an Ubuntu Linux user, I can write the code and even cross-compile, but I can't actually test it to make sure the fix works. I don't have macOS.&lt;/p&gt;

&lt;p&gt;Enter CircleCI. &lt;/p&gt;

&lt;p&gt;I can open a PR with my fix and CircleCI will build and test it on a macOS machine. It has removed a technical barrier for me. Likewise, CI can lower friction for people wanting to open PRs on your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Don't require build secrets for non-deployment jobs
&lt;/h2&gt;

&lt;p&gt;When API tokens, SSH keys, etc. are involved in a build, &lt;a href="https://circleci.com/blog/managing-secrets-when-you-have-pull-requests-from-outside-contributors/" rel="noopener noreferrer"&gt;you don't want those build secrets getting into the wrong hands&lt;/a&gt;. This is understandable. Public projects on CircleCI have secrets turned off on forked PRs by default.&lt;/p&gt;

&lt;p&gt;We've got your back.&lt;/p&gt;

&lt;p&gt;What you can do is make an effort to allow forked PRs to reach a green build without those secrets in the first place. Commands that rely on secrets should be isolated to their own jobs or blocked with Bash logic. This way an outside PR will be able to run tests that pass and a project maintainer can come along and run integration tests or deployments in the &lt;code&gt;master&lt;/code&gt; branch or some other way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;An &lt;a href="https://circleci.com/docs/2.0/oss/" rel="noopener noreferrer"&gt;open source&lt;/a&gt; project equipped with a CI tool lowers the barrier to entry for contributions while raising the overall quality. Open source is as much about the people as it is the code. Empowered contributors are happier and more productive. This benefits the project which means everyone wins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;P.S.&lt;/em&gt;&lt;/strong&gt; CircleCI gives all users/projects a free build container. Did you know that we give &lt;a href="https://circleci.com/docs/2.0/oss/" rel="noopener noreferrer"&gt;open source&lt;/a&gt; projects, specifically, &lt;strong&gt;4 containers&lt;/strong&gt;? Still for free. &lt;a href="https://circleci.com/signup/" rel="noopener noreferrer"&gt;Let's build software together!&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>opensource</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Level up go test with gotestsum</title>
      <dc:creator>Ricardo N Feliciano</dc:creator>
      <pubDate>Wed, 21 Nov 2018 02:19:25 +0000</pubDate>
      <link>https://forem.com/circleci/level-up-go-test-with-gotestsum-4p0b</link>
      <guid>https://forem.com/circleci/level-up-go-test-with-gotestsum-4p0b</guid>
      <description>&lt;p&gt;Hey Gophers!&lt;/p&gt;

&lt;p&gt;One of the many great things about Go (Golang) is how simple it is to run tests. With the &lt;a href="https://circleci.com/blog/go-v1.11-modules-and-circleci/"&gt;changes we saw in Go v1.11&lt;/a&gt;, running tests is as simple as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# To test only your current module&lt;/span&gt;
go &lt;span class="nb"&gt;test&lt;/span&gt; ./...

&lt;span class="c"&gt;# To test your module as well as its direct and indirect dependencies&lt;/span&gt;
go &lt;span class="nb"&gt;test &lt;/span&gt;all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this post, I'm going to show you how we can make the output of &lt;code&gt;go test&lt;/code&gt; more useful for local development as well as for CircleCI.&lt;/p&gt;

&lt;h2&gt;
  
  
  gotestsum
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;gotestsum&lt;/code&gt; is a &lt;a href="https://en.wikipedia.org/wiki/Command-line_interface"&gt;CLI&lt;/a&gt; tool written in Go that runs &lt;code&gt;go test&lt;/code&gt; for you. It enhances the output, making it much more palatable. As described on its &lt;a href="https://github.com/gotestyourself/gotestsum"&gt;GitHub repository&lt;/a&gt;, it "runs tests, and prints friendly test output and a summary of the test run."&lt;/p&gt;

&lt;p&gt;Here's how it looks:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cIjF58DP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/nz68e561yg3zxg5cbhuk.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cIjF58DP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/nz68e561yg3zxg5cbhuk.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's pretty cool for local development, but what about using it for continuous integration (&lt;a href="https://circleci.com/continuous-integration/"&gt;CI&lt;/a&gt;)?&lt;/p&gt;

&lt;h2&gt;
  
  
  CircleCI / JUnit support
&lt;/h2&gt;

&lt;p&gt;Most CI providers support saving tests results in the JUnit format. What the CI provider does with it can vary, but this usually means accessing historical test data, cool charts and graphs, etc. CircleCI supports &lt;a href="https://circleci.com/docs/2.0/collect-test-data/"&gt;collecting test metadata&lt;/a&gt; as long as it's in JUnit format. Since &lt;code&gt;go test&lt;/code&gt; doesn't output in the JUnit format natively, we'll use &lt;code&gt;gotestsum&lt;/code&gt; to do that for us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gotestsum --junitfile unit-tests.xml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The command above will output your test results in the JUnit format. You can then tell CircleCI to use that file as test metadata via your CircleCI &lt;code&gt;config.xml&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    - store_test_results:
        path: /tmp/test-results
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Installing gotestsum
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Go v1.10 or later&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Installing locally
&lt;/h3&gt;

&lt;p&gt;As with most Go applications, running &lt;code&gt;gotestsum&lt;/code&gt; can be as simple as placing the binary on your &lt;code&gt;$PATH&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -sSL "https://github.com/gotestyourself/gotestsum/releases/download/v0.3.1/gotestsum_0.3.1_linux_amd64.tar.gz" | sudo tar -xz -C /usr/local/bin gotestsum 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above command installs v0.3.1 of &lt;code&gt;gotestsum&lt;/code&gt;, the most recent version as of this writing. If a new version is available, update the version number in the URL. You can also replace &lt;code&gt;linux&lt;/code&gt; in the URL with &lt;code&gt;darwin&lt;/code&gt; for macOS users. The binary packages available are for 64-bit x86 systems. See the next section to compile your own.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compiling a binary
&lt;/h3&gt;

&lt;p&gt;If you have a 32-bit system, ARM, or some other need, here's how to compile and install a custom binary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go get -u gotest.tools/gotestsum
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Installing on CircleCI
&lt;/h3&gt;

&lt;p&gt;If you are using a &lt;a href="https://hub.docker.com/r/circleci/golang/"&gt;Golang CircleCI Docker Convenience Image&lt;/a&gt; (&lt;code&gt;circleci/golang&lt;/code&gt;) then congratulations, &lt;code&gt;gotestsum&lt;/code&gt; is already pre-installed for you! If not, I'd suggest following the installing locally instructions and applying that to your CircleCI &lt;code&gt;config.yml&lt;/code&gt; file or, for a custom image, within a Dockerfile.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gotestsum&lt;/code&gt; is a project maintained by &lt;a href="https://github.com/dnephin"&gt;Daniel Nephin&lt;/a&gt;, an engineer at CircleCI.&lt;/p&gt;

</description>
      <category>go</category>
      <category>testing</category>
      <category>circleci</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Blog Posts vs Docs - Where to Place Content?</title>
      <dc:creator>Ricardo N Feliciano</dc:creator>
      <pubDate>Mon, 29 Oct 2018 14:10:10 +0000</pubDate>
      <link>https://forem.com/felicianotech/blog-posts-vs-docs---where-to-place-content-2h37</link>
      <guid>https://forem.com/felicianotech/blog-posts-vs-docs---where-to-place-content-2h37</guid>
      <description>

&lt;p&gt;Whether it's with a co-worker or someone I meet at a meetup, I tend to discuss one of three topics:&lt;br&gt;
Open Source, Community, or Documentation.&lt;br&gt;
When we talk docs, we end up talking Developer Relations / Advocacy, and content generation.&lt;br&gt;
Time and time again I've been asked the same question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How do I know if X should be a blog post or a Pull Request (PR) to documentation?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's not a simple question because it can depend on your company's/project's culture and the audience you have.&lt;/p&gt;

&lt;p&gt;That being said, I've answered this long enough times that I've put together questions you can ask yourself to determine where content can live.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is this commentary?
&lt;/h2&gt;

&lt;p&gt;If you're writing about software and you're providing lots of opinion or hype, it should be a blog post.&lt;br&gt;
Commentary doesn't belong in documentation.&lt;/p&gt;

&lt;p&gt;For example, early in 2017 I wrote a post for &lt;a href="https://circleci.com"&gt;CircleCI&lt;/a&gt; called &lt;a href="https://circleci.com/blog/why-are-developers-moving-to-yarn/"&gt;Why Developers Are Moving to Yarn&lt;/a&gt;.&lt;br&gt;
This post covered some of the technical abilities for both Yarn and npm, observaton research, and yet it was a blog post.&lt;br&gt;
This piece of content was a blog post because I was providing my opinion on why there was a lot of momentum swinging over to Yarn.&lt;br&gt;
I was capitalizing on active discussion in the blogosphere, which leads to the next question to ask yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is this current events or news?
&lt;/h2&gt;

&lt;p&gt;If you're writing about a new release of software, a feature that launched, or an impending End Of Life (EOL), it's a blog post.&lt;br&gt;
Of course, your documentation should cover the details of a new feature, but if you're announcing it with language such as, "this week feature X is now available", it should be a blog post.&lt;/p&gt;

&lt;p&gt;Notice how blog posts normally have a published date and docs don't.&lt;br&gt;
This is because blog posts should be "timely".&lt;br&gt;
Some &lt;em&gt;clever&lt;/em&gt; marketers will remove dates from their blogs to make their content appear evergreen.&lt;br&gt;
Don't do that, you're usually providing outdated information to the reader which isn't right.&lt;br&gt;
No body wants to read a newspaper from two months ago.&lt;/p&gt;

&lt;p&gt;The next two questions are probably the best distinctions between blog posts and docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do I want to maintain this?
&lt;/h2&gt;

&lt;p&gt;For both CircleCI's blog as well as my own, the most common type of post I make are guides / tutorials.&lt;br&gt;
I like to teach things.&lt;br&gt;
I believe these kind of posts can easily live in either a blog or documentation.&lt;br&gt;
The big question is are you (or a team) going to maintain it?&lt;br&gt;
The best way to explain this is with an example.&lt;/p&gt;

&lt;p&gt;Let's say you write a blog post for ACME company on how to integrate ACME's product with WordPress.&lt;br&gt;
Great, people may find it useful but the catch is WordPress is an active project.&lt;br&gt;
Inevitably the software will change, especially with regard to internal plugin APIs or external APIs.&lt;/p&gt;

&lt;p&gt;The guide you wrote can be invalid a mere few month later if WordPress happens to change something.&lt;br&gt;
I believe that content in documentation should always be maintained.&lt;br&gt;
If you write it, maintain it.&lt;br&gt;
If you accept a PR from a contributor, you now are responsible for maintaining that guide.&lt;/p&gt;

&lt;p&gt;If you plan on maintaining a guide, make it a doc.&lt;br&gt;
Otherwise, make it a blog post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Am I writing about the "why" or the "how"?
&lt;/h2&gt;

&lt;p&gt;Content that is information heavy and contain all the steps on &lt;strong&gt;how&lt;/strong&gt; to do something is a doc and belongs in documentation.&lt;br&gt;
Diving into the &lt;strong&gt;why&lt;/strong&gt; a feature works a certain way or why certain decisions were made tend to make for great blog posts.&lt;/p&gt;

&lt;p&gt;In my experience, people tend to visit docs in order to get started with a product or when they're having issues and they need a reference or user manual.&lt;br&gt;
They're in need of something specific so having content that is to the point with a high signal to noise ratio is very helpful.&lt;/p&gt;

&lt;p&gt;Blog posts tend to be reserved for when a person's in learning or discovery mode.&lt;br&gt;
They likely have time to read more "fluff" if it's entertaining, adds to their education, or adds more context for a better understanding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content Reusability
&lt;/h2&gt;

&lt;p&gt;There's no rule saying you can't make both a blog post and a doc!&lt;br&gt;
The most efficient Content Marketers and Developer Advocates do just that.&lt;/p&gt;

&lt;p&gt;Much of the content I create comes from working on a demo or a side projects.&lt;br&gt;
I take that code, experience, and learnings, and I distilled it down to it's core.&lt;br&gt;
I then make a version of it that would be useful as a blog post and then a version of it that would be useful as a doc or an addition to an existing doc.&lt;/p&gt;

&lt;p&gt;The same content can exists in multiple places.&lt;br&gt;
Just cater your approach and language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Ask about your content...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is it commentary?

&lt;ul&gt;
&lt;li&gt;Yes - it's a blog post&lt;/li&gt;
&lt;li&gt;No - it's a doc&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Is it current events or news? Is it "timely"?

&lt;ul&gt;
&lt;li&gt;Yes - its a blog post&lt;/li&gt;
&lt;li&gt;No - it's a doc&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Are you going to maintain it with updates?

&lt;ul&gt;
&lt;li&gt;Yes - it's a doc&lt;/li&gt;
&lt;li&gt;No - it's a blog post&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;What are you writing about?

&lt;ul&gt;
&lt;li&gt;The "why" - It's a blog post&lt;/li&gt;
&lt;li&gt;The "how" - It's a doc&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;


</description>
      <category>blogs</category>
      <category>documentation</category>
      <category>contentmarketing</category>
    </item>
    <item>
      <title>Would a Nonprofit Twitter Clone Work?</title>
      <dc:creator>Ricardo N Feliciano</dc:creator>
      <pubDate>Wed, 24 Oct 2018 15:34:14 +0000</pubDate>
      <link>https://forem.com/felicianotech/would-a-nonprofit-twitter-clone-work-1ggh</link>
      <guid>https://forem.com/felicianotech/would-a-nonprofit-twitter-clone-work-1ggh</guid>
      <description>

&lt;p&gt;Many people have said that Facebook has gotten so big it should be considered a public utility.&lt;br&gt;
I think this applies much more so to Twitter given the penetration and speed a single tweet can achieve for both local and global news.&lt;br&gt;
Forget major cities and tech hubs, even the most remote parts of the world get their news via tweets.&lt;/p&gt;

&lt;p&gt;This utility-like nature has been threatened and damaged many times before by decisions Twitter has made.&lt;br&gt;
Some of these decisions due to what's in their best interest as a for-profit business.&lt;br&gt;
They have an obligation to make money, I understand.&lt;/p&gt;

&lt;p&gt;But what if they didn't?&lt;/p&gt;

&lt;p&gt;Many, many, many (did I say many?) people have attempted to make Twitter clones.&lt;br&gt;
In the scope of this blog post, I see two large problems with these clones.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;They are for-profit startups.
Or worse, not businesses at all.
Too many VCs have invested money in Twitter to want to let it fail now by investing in a competing project.
Also, being for-profit brings the same troubles Twitter has now.
Balancing privacy concerns and user freedom with the need to make a buck.&lt;/li&gt;
&lt;li&gt;Many "clones" aren't really clones anyway.
These projects tend to create their own take on Twitter.
That's fair, that's their right as makers and entrepreneurs.
Personally, I mostly like the way Twitter works and would like an exact clone.
It's gotten as big as it has for a reason, right?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  So can we do it?
&lt;/h2&gt;

&lt;p&gt;How possible would it be to create an identical Twitter clone, where the backing company is a nonprofit or foundation?&lt;br&gt;
Where making money isn't one of the underlying goals but instead a sustainable communications and news platform for the world is?&lt;/p&gt;

&lt;p&gt;If I remember correctly, one of Twitter's largest problems in the past as been scaling their infrastructure.&lt;br&gt;
That remains an issue and for a nonprofit, paying for that infrastructure will be as well.&lt;/p&gt;

&lt;p&gt;Still, I'm excited about the thought of cloning Twitter into an actual, public, technology infrastructure.&lt;br&gt;
Even if it's just a pipe dream.&lt;/p&gt;


</description>
      <category>twitter</category>
      <category>nonprofit</category>
      <category>foss</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Install the Linode CLI on Linux via Snap</title>
      <dc:creator>Ricardo N Feliciano</dc:creator>
      <pubDate>Tue, 23 Oct 2018 21:38:33 +0000</pubDate>
      <link>https://forem.com/felicianotech/install-the-linode-cli-on-linux-via-snap-4o5m</link>
      <guid>https://forem.com/felicianotech/install-the-linode-cli-on-linux-via-snap-4o5m</guid>
      <description>

&lt;p&gt;If you run a Linux distribution (distro) and you want to install the brand new Linode CLI, here's an easy and safe way to do so via a snap package.&lt;/p&gt;

&lt;p&gt;Back in 2017 Linode &lt;a href="https://www.linode.com/community/questions/11221/linode-rest-api-v4-early-access"&gt;announced their new v4 API&lt;/a&gt;.&lt;br&gt;
This new API (still in development I believe) puts the old one to shame.&lt;br&gt;
It's much more "RESTful" than the old one and enables many more features that the old one simply didn't have.&lt;/p&gt;

&lt;p&gt;Building on the shoulders of the new API came the new &lt;a href="https://developers.linode.com/"&gt;Linode Developer Website&lt;/a&gt;, the new &lt;a href="https://linodians.com/blog/new-linode-manager-preview/"&gt;Linode Manager Preview&lt;/a&gt; available at &lt;a href="https://cloud.linode.com"&gt;https://cloud.linode.com&lt;/a&gt;, and of course, the new Linode CLI.&lt;/p&gt;

&lt;p&gt;The new Linode CLI, written in Python, is very useful.&lt;br&gt;
Its features and how to use them are detailed via &lt;a href="https://www.linode.com/docs/platform/api/using-the-linode-cli/"&gt;Linode Docs&lt;/a&gt;.&lt;br&gt;
While it can be installed via &lt;code&gt;pip&lt;/code&gt;, if you don't already have &lt;code&gt;pip&lt;/code&gt; installed or want a more secure way to run the CLI, you can install it via a snap.&lt;/p&gt;

&lt;p&gt;You can install the &lt;code&gt;linode-cli&lt;/code&gt; via snap for Ubuntu 16.04, Ubuntu 18.04+, elementary OS 5, Debian 9+, Fedora 28+, and more:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;snap &lt;span class="nb"&gt;install &lt;/span&gt;linode-cli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As with all snaps, it will be auto-updated and sandboxed from the rest of your system meaning secure.&lt;br&gt;
More information on why you should be using snaps &lt;a href="https://www.fossmint.com/what-are-ubuntu-snaps-and-how-are-they-important/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The source for this snap can be found &lt;a href="https://github.com/felicianotech/linode-cli-snap"&gt;here&lt;/a&gt; while the source for Linode's CLI itself can be found &lt;a href="https://github.com/linode/linode-cli"&gt;here&lt;/a&gt;.&lt;/p&gt;


</description>
      <category>linode</category>
      <category>linodecli</category>
    </item>
    <item>
      <title>Automate GitHub Releases with CircleCI</title>
      <dc:creator>Ricardo N Feliciano</dc:creator>
      <pubDate>Mon, 01 Oct 2018 16:56:01 +0000</pubDate>
      <link>https://forem.com/circleci/automate-github-releases-with-circleci-lke</link>
      <guid>https://forem.com/circleci/automate-github-releases-with-circleci-lke</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally posted on CircleCI's &lt;a href="https://circleci.com/blog/publishing-to-github-releases-via-circleci/"&gt;blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Releases is a GitHub feature that allows you to present significant snapshots of your code, marked with a git tag, in GitHub's nice UI. If you're not currently using releases, I want to show you why you might want to, and how to implement them automatically.&lt;/p&gt;

&lt;p&gt;With releases, you get what tags provide--a version number and description--but you also get a longer section for release notes and a place to store and display release artifacts. This means your software's binary, .deb, .rpm, and AppImage files will be hosted by GitHub for each release, providing a convenient place for users to install your software.&lt;/p&gt;

&lt;p&gt;In this post, I will show you how to create releases within CircleCI. For a more general overview, see &lt;a href="https://help.github.com/articles/creating-releases/"&gt;GitHub's doc on creating releases&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At its core, GitHub Releases is simply a GitHub feature layered on top of git tags. Let's break it down:&lt;/p&gt;

&lt;h3&gt;
  
  
  Git tags
&lt;/h3&gt;

&lt;p&gt;Git tags give you a version number to mark a specific git commit as well as a short description. Believe it or not, just pushing a git tag to GitHub will create a new release in the "Releases" tab of your project on GitHub. This is a barebones release that includes only the tag information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Releases
&lt;/h3&gt;

&lt;p&gt;Releases add to git tags by providing a longer, "rich" description, the ability to mark the tag as a normal release or a pre-release, and most importantly, the ability to upload artifacts such as binaries for that release. Uploading these artifacts from CircleCI is what we're going to walk through here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;p&gt;There are a few ways to publish artifacts from a CircleCI build to a GitHub Release:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;manually with &lt;code&gt;curl&lt;/code&gt; and the GitHub API&lt;/li&gt;
&lt;li&gt;using &lt;a href="https://github.com/aktau/github-release"&gt;GitHub Release&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;using &lt;a href="https://github.com/itchio/gothub"&gt;GotHub&lt;/a&gt; (a GitHub Release fork)&lt;/li&gt;
&lt;li&gt;and using &lt;a href="https://github.com/tcnksm/ghr"&gt;ghr&lt;/a&gt;, which is what we'll use in our example&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Using ghr
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;ghr&lt;/code&gt; command full details can be &lt;a href="https://github.com/tcnksm/ghr"&gt;found on GitHub&lt;/a&gt;, however, we really only need to learn one subcommand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete ${VERSION} ./artifacts/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command uploads specific artifacts, typically binaries, to our GitHub release on GitHub. Let's break this down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ghr -t ${GITHUB_TOKEN}&lt;/code&gt; - Here we start the command and pass it a GitHub token for authentication. This is a &lt;a href="https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/"&gt;GitHub Personal Access Token&lt;/a&gt; and not an OAuth token/key.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Specifically created via your personal GitHub account, you'll want to safeguard this token and only load it into the CircleCI environment via a &lt;a href="https://circleci.com/docs/2.0/env-vars/#setting-an-environment-variable-in-a-project"&gt;private environment variable&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME}&lt;/code&gt; - This is where we pass the GitHub user/org name and the repository name. Both values are passed via built-in CircleCI Environment Variables. No extra work is needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-c ${CIRCLE_SHA1}&lt;/code&gt; - Here we provide the Git commit hash (available in CircleCI as &lt;code&gt;$CIRCLE_SHA1&lt;/code&gt;) to &lt;code&gt;ghr&lt;/code&gt;. This tells it which commit, and thus tag, the release is for.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-delete&lt;/code&gt; - This deletes the git tag and release if it already exists.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;${VERSION}&lt;/code&gt; - We set the git tag/release version via a &lt;code&gt;$VERSION&lt;/code&gt; environment variable. This can be any variable you want or a string. Typically this is the same as the version of your software release.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;./artifacts/&lt;/code&gt; - Then we set the PATH to find the artifacts. In this case, everything in a directory called &lt;code&gt;artifacts&lt;/code&gt; inside the current directory.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Plain CircleCI 2.0 example
&lt;/h3&gt;

&lt;p&gt;We've walked through how to use &lt;code&gt;ghr&lt;/code&gt; to create a GitHub Release but let's see how it can look inside of a CircleCI 2.0 configuration file:&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;publish-github-release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;docker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;circleci/golang:1.8&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;attach_workspace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;at&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./artifacts&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Publish&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Release&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;GitHub"&lt;/span&gt;
          &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;go get github.com/tcnksm/ghr&lt;/span&gt;
            &lt;span class="s"&gt;VERSION=$(my-binary --version)&lt;/span&gt;
            &lt;span class="s"&gt;ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete ${VERSION} ./artifacts/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CI Builds CircleCI 2.0 example
&lt;/h3&gt;

&lt;p&gt;This is a CircleCI job called &lt;code&gt;publish-github-release&lt;/code&gt; that uses a &lt;a href="https://circleci.com/docs/2.0/circleci-images/#go-golang"&gt;CircleCI Go convenience image&lt;/a&gt;. Here's the breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using &lt;a href="https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs"&gt;workspaces&lt;/a&gt;, we pull in the binaries for our project from a previous job (not covered in this post).&lt;/li&gt;
&lt;li&gt;This job pulls and compiles &lt;code&gt;ghr&lt;/code&gt; via &lt;code&gt;go get&lt;/code&gt; (since &lt;code&gt;ghr&lt;/code&gt; is written in Go).&lt;/li&gt;
&lt;li&gt;It populates &lt;code&gt;$VERSION&lt;/code&gt; with the output of &lt;code&gt;my-binary --version&lt;/code&gt;, our example application for this post.&lt;/li&gt;
&lt;li&gt;We then use the &lt;code&gt;ghr&lt;/code&gt; command to upload the binaries in the &lt;code&gt;artifacts&lt;/code&gt; directory to GitHub.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can shave a few seconds off of the job above by using the &lt;a href="https://github.com/cibuilds/github"&gt;&lt;code&gt;ghr&lt;/code&gt; Docker image&lt;/a&gt; from &lt;a href="https://github.com/cibuilds"&gt;CI Builds&lt;/a&gt;. It's a lightweight Docker image that already has &lt;code&gt;ghr&lt;/code&gt; installed. Here's how the new example config would look:&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;publish-github-release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;docker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cibuilds/github:0.10&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;attach_workspace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;at&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./artifacts&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Publish&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Release&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;GitHub"&lt;/span&gt;
          &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;VERSION=$(my-binary --version)&lt;/span&gt;
            &lt;span class="s"&gt;ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete ${VERSION} ./artifacts/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Workflow example
&lt;/h3&gt;

&lt;p&gt;Here's an example of how one of the variations of the above job can be implemented within a &lt;a href="https://circleci.com/docs/2.0/workflows/"&gt;Workflow&lt;/a&gt; to publish tagged commits to GitHub releases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;workflows:
  version: 2
  main:
    jobs:
      - build:
          filters:
            tags:
              only: /^\d+\.\d+\.\d+$/
      - publish-github-release:
          requires:
            - build
          filters:
            branches:
              ignore: /.*/
            tags:
              only: /^\d+\.\d+\.\d+$/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we have CircleCI kick off the &lt;code&gt;publish-github-release&lt;/code&gt; job when a git tag is pushed. How exactly you choose when to publish a GitHub release is up to you, but here we'll do it with a SemVer-like git tag. We say SemVer-like because the tag regex we're using &lt;code&gt;/^\d+\.\d+\.\d+$/&lt;/code&gt; matches tags such as &lt;code&gt;1.2.3&lt;/code&gt; but doesn't take into account all of the rules of &lt;a href="https://semver.org/"&gt;SemVer&lt;/a&gt; (Semantic Versioning).&lt;/p&gt;

&lt;p&gt;For the sake of completeness, here's what a complete regex for SemVer would look like according to &lt;a href="https://rgxdb.com/r/40OZ1HN5"&gt;rgxdb.com&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/(?&amp;lt;=^[Vv]|^)(?:(?&amp;lt;major&amp;gt;(?:0|[1-9](?:(?:0|[1-9])+)*))[.](?&amp;lt;minor&amp;gt;(?:0|[1-9](?:(?:0|[1-9])+)*))[.](?&amp;lt;patch&amp;gt;(?:0|[1-9](?:(?:0|[1-9])+)*))(?:-(?&amp;lt;prerelease&amp;gt;(?:(?:(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?|(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?)|(?:0|[1-9](?:(?:0|[1-9])+)*))(?:[.](?:(?:(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?|(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?)|(?:0|[1-9](?:(?:0|[1-9])+)*)))*))?(?:[+](?&amp;lt;build&amp;gt;(?:(?:(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?|(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?)|(?:(?:0|[1-9])+))(?:[.](?:(?:(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?|(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?)|(?:(?:0|[1-9])+)))*))?)$/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>devops</category>
      <category>github</category>
      <category>circleci</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
