<?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: Ian Cleary (he/him)</title>
    <description>The latest articles on Forem by Ian Cleary (he/him) (@iancleary).</description>
    <link>https://forem.com/iancleary</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%2F247999%2F2a460f70-02fb-428b-be43-e6b1e06be518.jpeg</url>
      <title>Forem: Ian Cleary (he/him)</title>
      <link>https://forem.com/iancleary</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/iancleary"/>
    <language>en</language>
    <item>
      <title>Test and Publish a Python Package to PyPi using Poetry and GitHub Actions</title>
      <dc:creator>Ian Cleary (he/him)</dc:creator>
      <pubDate>Sat, 29 Aug 2020 19:46:51 +0000</pubDate>
      <link>https://forem.com/iancleary/test-and-publish-a-python-package-to-pypi-using-poetry-and-github-actions-186a</link>
      <guid>https://forem.com/iancleary/test-and-publish-a-python-package-to-pypi-using-poetry-and-github-actions-186a</guid>
      <description>&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;I created a python package cookiecutter showcasing two GitHub actions workflow files I've seen and used successfully to test and publish a Python package to PyPi using GitHub actions.&lt;/p&gt;

&lt;p&gt;The detailed explanation and python cookiecutter wrapper are the novel additions. 🎉   I found it difficult to just inspect open source projects work and put the pieces together.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So I hope this helps you (no matter your previous experience).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Please let me know what isn't clear!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started with this template
&lt;/h2&gt;

&lt;p&gt;There are two workflow files, each with their named purpose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Test&lt;/li&gt;
&lt;li&gt;Publish&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have an existing python project or are starting a new one, you can use your GitHub username and your project name as inputs into my Cookiecutter template!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;First, what is cookiecutter?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Cookiecutter
&lt;/h4&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/cookiecutter"&gt;
        cookiecutter
      &lt;/a&gt; / &lt;a href="https://github.com/cookiecutter/cookiecutter"&gt;
        cookiecutter
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A command-line utility that creates projects from cookiecutters (project templates), e.g. Python package projects, VueJS projects.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Cookiecutter&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://pypi.org/project/cookiecutter/" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/60a852b47296f5e1174157e81c1ca580e9939e84a375a14df273123ef2de2334/68747470733a2f2f696d672e736869656c64732e696f2f707970692f762f636f6f6b69656375747465722e737667" alt="pypi"&gt;&lt;/a&gt;
&lt;a href="https://pypi.org/project/cookiecutter/" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/a30c08d6b32c07fb8980f41f399d6051d9cc4c88b04a0d96956ed4fe350f1725/68747470733a2f2f696d672e736869656c64732e696f2f707970692f707976657273696f6e732f636f6f6b69656375747465722e737667" alt="python"&gt;&lt;/a&gt;
&lt;a href="https://github.com/cookiecutter/cookiecutter/actions"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rZxln-ei--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/cookiecutter/cookiecutter/actions/workflows/main.yml/badge.svg%3Fbranch%3Dmaster" alt="Build Status"&gt;&lt;/a&gt;
&lt;a href="https://codecov.io/github/cookiecutter/cookiecutter?branch=master" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/751022d2735fa4fc6ed3f7311a2006c92c7e9653e42c2cf51e91666298004188/68747470733a2f2f636f6465636f762e696f2f67682f636f6f6b69656375747465722f636f6f6b69656375747465722f6272616e63682f6d61737465722f6772617068732f62616467652e7376673f6272616e63683d6d6173746572" alt="codecov"&gt;&lt;/a&gt;
&lt;a href="https://join.slack.com/t/cookie-cutter/shared_invite/enQtNzI0Mzg5NjE5Nzk5LTRlYWI2YTZhYmQ4YmU1Y2Q2NmE1ZjkwOGM0NDQyNTIwY2M4ZTgyNDVkNjMxMDdhZGI5ZGE5YmJjM2M3ODJlY2U" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/effdf54749252848d75ab357c1c5407dc777226fbb02e97f0bd752ca858ef819/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f6f6b69656375747465722d4a6f696e2532306f6e253230536c61636b2d677265656e3f7374796c653d666c6174266c6f676f3d736c61636b" alt="slack"&gt;&lt;/a&gt;
&lt;a href="https://readthedocs.org/projects/cookiecutter/?badge=latest" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/a8ee24afd5527818ef86829ab2c139667c2ae1fc31adda3fc69d6edf062bcc08/68747470733a2f2f72656164746865646f63732e6f72672f70726f6a656374732f636f6f6b69656375747465722f62616467652f3f76657273696f6e3d6c6174657374" alt="docs"&gt;&lt;/a&gt;
&lt;a href="https://scrutinizer-ci.com/g/cookiecutter/cookiecutter/?branch=master" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/143367cc3e8fccca11c854fb5fea2349178ad5fa2af621153443be453a64cb04/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f672f636f6f6b69656375747465722f636f6f6b69656375747465722e737667" alt="Code Quality"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A command-line utility that creates projects from &lt;strong&gt;cookiecutters&lt;/strong&gt; (project
templates), e.g. creating a Python package project from a Python package project
template.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Documentation: &lt;a href="https://cookiecutter.readthedocs.io" rel="nofollow"&gt;https://cookiecutter.readthedocs.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/cookiecutter/cookiecutter"&gt;https://github.com/cookiecutter/cookiecutter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PyPI: &lt;a href="https://pypi.org/project/cookiecutter/" rel="nofollow"&gt;https://pypi.org/project/cookiecutter/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Free and open source software: &lt;a href="https://github.com/cookiecutter/cookiecutter/blob/master/LICENSE"&gt;BSD license&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://raw.githubusercontent.com/cookiecutter/cookiecutter/3ac078356adf5a1a72042dfe72ebfa4a9cd5ef38/logo/cookiecutter_medium.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qQcyhQ6L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/cookiecutter/cookiecutter/3ac078356adf5a1a72042dfe72ebfa4a9cd5ef38/logo/cookiecutter_medium.png" alt="Cookiecutter"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We are proud to be an open source sponsor of
&lt;a href="https://us.pycon.org/2016/sponsors/" rel="nofollow"&gt;PyCon 2016&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
Features&lt;/h2&gt;
&lt;p&gt;Did someone say features?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cross-platform: Windows, Mac, and Linux are officially supported.&lt;/li&gt;
&lt;li&gt;You don't have to know/write Python code to use Cookiecutter.&lt;/li&gt;
&lt;li&gt;Works with Python 3.6, 3.7, 3.8, 3.9 and PyPy3.&lt;/li&gt;
&lt;li&gt;Project templates can be in any programming language or markup format
Python, JavaScript, Ruby, CoffeeScript, RST, Markdown, CSS, HTML, you name it
You can use multiple languages in the same project template.&lt;/li&gt;
&lt;li&gt;Simple command line usage:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight highlight-source-shell position-relative js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Create project from the cookiecutter-pypackage.git repo template&lt;/span&gt;
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; You'll be prompted to enter values.&lt;/span&gt;
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Then it'll create your Python package in the current working directory,&lt;/span&gt;
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; based on those values.&lt;/span&gt;
$&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/cookiecutter/cookiecutter"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Make sure you have &lt;a href="https://www.python.org/downloads/"&gt;Python3&lt;/a&gt; installed!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Instructions to use iancleary/pypackage
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install &lt;/span&gt;cookiecutter
&lt;span class="c"&gt;# you can add the flag `--user` if you'd like&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;cookiecutter https://github.com/iancleary/pypackage
&lt;span class="c"&gt;# For the sake of brevity, repos on GitHub can just use the 'gh' prefix&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;cookiecutter gh:iancleary/pypackage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Poetry (virtual environment and publish to PyPi, all with one tool)&lt;/li&gt;
&lt;li&gt;black (linting/formatter)&lt;/li&gt;
&lt;li&gt;autoflake (removing unused packages)&lt;/li&gt;
&lt;li&gt;isort (dependency organization)&lt;/li&gt;
&lt;li&gt;mypy (static type checking)&lt;/li&gt;
&lt;li&gt;pytest (including test coverage)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pre-commit.com/"&gt;pre-commit&lt;/a&gt; (hooks on commit)&lt;/li&gt;
&lt;li&gt;GitHub Actions for CI/CD&lt;/li&gt;
&lt;li&gt;mkdocs for documentation (with material theme)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only &lt;strong&gt;Python 3.6+&lt;/strong&gt; is supported as required by the black, pydantic packages&lt;/p&gt;
&lt;h3&gt;
  
  
  Submission Category: Maintainer Must-Haves
&lt;/h3&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://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/iancleary"&gt;
        iancleary
      &lt;/a&gt; / &lt;a href="https://github.com/iancleary/pypackage"&gt;
        pypackage
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Cookiecutter python package using Poetry, mypy, black, isort, autoflake, pytest, mkdocs, and GitHub Actions
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
ARCHIVED, pypackage&lt;/h1&gt;
&lt;p&gt;I no longer with to maintain this cookiecutter, please see &lt;a href="https://github.com/br3ndonland/template-python"&gt;br3ndonland/template-python&lt;/a&gt;'s template. While not a cookiecutter at the time of this writing, it has the tooling I was going for :)&lt;/p&gt;
&lt;p&gt;
    &lt;em&gt;Rapid python package setup with modern venv, dependencies, testing, docs, and CI&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="https://github.com/iancleary/pypackage/actions?query=workflow%3ATest"&gt;
    &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Gigh-S5e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/iancleary/pypackage/workflows/Test/badge.svg" alt="Test"&gt;
&lt;/a&gt;
&lt;a href="https://github.com/iancleary/pypackage/actions?query=workflow%3APublish"&gt;
    &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zVL_HZnq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/iancleary/pypackage/workflows/Publish/badge.svg" alt="Publish"&gt;
&lt;/a&gt;
&lt;a href="https://dependabot.com/" rel="nofollow"&gt;
    &lt;img src="https://camo.githubusercontent.com/c1f9e10eedf42ea707aba7f5ded26bf6bbad38c0d3f7fb9fc001e01c88887465/68747470733a2f2f666c61742e62616467656e2e6e65742f646570656e6461626f742f69616e636c656172792f70797061636b6167653f69636f6e3d646570656e6461626f74" alt="Dependabot Enabled"&gt;
&lt;/a&gt;
&lt;/p&gt;
&lt;h2&gt;
The Basic Idea&lt;/h2&gt;
&lt;p&gt;This is a template module collecting many utilities I have liked from other projects, to serve as a personal reference.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/tiangolo/pydantic-sqlalchemy/"&gt;https://github.com/tiangolo/pydantic-sqlalchemy/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/cookiecutter/cookiecutter"&gt;https://github.com/cookiecutter/cookiecutter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Getting started with this template&lt;/h2&gt;
&lt;div class="highlight highlight-source-shell position-relative js-code-highlight"&gt;
&lt;pre&gt;pip install --user cookiecutter
$ cookiecutter https://github.com/iancleary/pypackage
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; For the sake of brevity, repos on GitHub can just use the 'gh' prefix&lt;/span&gt;
$ cookiecutter gh:iancleary/pypackage&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Poetry (virtual environment and publish to PyPi, all with one tool)&lt;/li&gt;
&lt;li&gt;black (linting/formatter)&lt;/li&gt;
&lt;li&gt;autoflake (removing unused packages)&lt;/li&gt;
&lt;li&gt;isort (dependency organization)&lt;/li&gt;
&lt;li&gt;mypy (static type checking)&lt;/li&gt;
&lt;li&gt;pytest (including test coverage)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pre-commit.com/" rel="nofollow"&gt;pre-commit&lt;/a&gt; (hooks on commit)&lt;/li&gt;
&lt;li&gt;GitHub Actions for CI/CD&lt;/li&gt;
&lt;li&gt;mkdocs for documentation (with material theme)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Only &lt;strong&gt;Python 3.6+&lt;/strong&gt; is supported as…&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/iancleary/pypackage"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Test
&lt;/h2&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;Test&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;pull_request&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;synchronize&lt;/span&gt;&lt;span class="pi"&gt;]&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;test&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;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matrix&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="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;3.6&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;3.7&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;3.8&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;fail-fast&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&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;Set up 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@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;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.python-version }}&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 full python version&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;full-python-version&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 ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")&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 poetry&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 -fsS -o get-poetry.py https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py&lt;/span&gt;
          &lt;span class="s"&gt;python get-poetry.py -y&lt;/span&gt;
          &lt;span class="s"&gt;echo "::set-env name=PATH::$HOME/.poetry/bin:$PATH"&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;Configure poetry&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;poetry config virtualenvs.in-project &lt;/span&gt;&lt;span class="no"&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;Set up cache&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/cache@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;cache&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;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.venv&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }}&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;Ensure cache is healthy&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;steps.cache.outputs.cache-hit == 'true'&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;poetry run pip --version &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 || rm -rf .venv&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="s"&gt;poetry install&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&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;poetry run bash scripts/test.sh&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 coverage&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;codecov/codecov-action@v1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Publish
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Repo Secrets
&lt;/h3&gt;

&lt;p&gt;Go to your repo settings and add a &lt;code&gt;PYPI_TOKEN&lt;/code&gt; environment variable:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4E7ttXFk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fqyzb1n1phbkpzf8rife.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4E7ttXFk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fqyzb1n1phbkpzf8rife.png" alt="GitHub Actions PYPI_TOKEN secrets visual aid"&gt;&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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish&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="s"&gt;created&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;publish&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;Set up 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@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;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.7"&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 poetry&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 -fsS -o get-poetry.py https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py&lt;/span&gt;
          &lt;span class="s"&gt;python get-poetry.py -y&lt;/span&gt;
          &lt;span class="s"&gt;echo "::set-env name=PATH::$HOME/.poetry/bin:$PATH"&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;Configure poetry&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;poetry config virtualenvs.in-project &lt;/span&gt;&lt;span class="no"&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;Set up cache&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/cache@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;cache&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;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.venv&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }}&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;Ensure cache is healthy&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;steps.cache.outputs.cache-hit == 'true'&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;poetry run pip --version &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 || rm -rf .venv&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="s"&gt;poetry install&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;Publish&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;PYPI_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.PYPI_TOKEN }}&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;poetry config pypi-token.pypi $PYPI_TOKEN&lt;/span&gt;
          &lt;span class="s"&gt;bash scripts/publish.sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;That's it!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you make a release on GitHub, the publish workflow will run and deploy to PyPi! 🚀🎉😎&lt;/p&gt;
&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;I have used the cookiecutter successfully in my FastRF project&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/iancleary"&gt;
        iancleary
      &lt;/a&gt; / &lt;a href="https://github.com/iancleary/fastrf"&gt;
        fastrf
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      RF Design Server
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
fastrf&lt;/h1&gt;
&lt;p&gt;
    &lt;em&gt;FastRF is an application to create and track key system metrics&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="https://github.com/iancleary/fastrf/actions?query=workflow%3ATest"&gt;
    &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xLVEHOIO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/iancleary/fastrf/workflows/Test/badge.svg" alt="Test"&gt;
&lt;/a&gt;
&lt;a href="https://github.com/iancleary/fastrf/actions?query=workflow%3APublish"&gt;
    &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3qjkLfRn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/iancleary/fastrf/workflows/Publish/badge.svg" alt="Publish"&gt;
&lt;/a&gt;
&lt;a href="https://dependabot.com/" rel="nofollow"&gt;
    &lt;img src="https://camo.githubusercontent.com/b3a7c0d79a86b224a8d6c8dcc17828fd81f71069cd439909759c7bdbf1f098e2/68747470733a2f2f666c61742e62616467656e2e6e65742f646570656e6461626f742f69616e636c656172792f6661737472663f69636f6e3d646570656e6461626f74" alt="Dependabot Enabled"&gt;
&lt;/a&gt;
&lt;a href="https://codecov.io/gh/iancleary/fastrf" rel="nofollow"&gt;
    &lt;img src="https://camo.githubusercontent.com/566f2aa22a9bc9636189e83ea14cdbcbd6fc2d2fba1684f4b1d8fe5ab02de4bf/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f69616e636c656172792f6661737472663f636f6c6f723d253233333444303538" alt="Coverage"&gt;
&lt;/a&gt;
&lt;a href="https://pypi.org/project/fastrf" rel="nofollow"&gt;
    &lt;img src="https://camo.githubusercontent.com/6c1f4cc4c5e2143f6feabaa5616c587ca44794f2423c6f2e8d664fdbdec4e8f3/68747470733a2f2f696d672e736869656c64732e696f2f707970692f762f6661737472663f636f6c6f723d253233333444303538266c6162656c3d707970692532307061636b616765" alt="Package version"&gt;
&lt;/a&gt;
&lt;a href="https://pypi.org/project/fastrf/" rel="nofollow"&gt;
    &lt;img src="https://camo.githubusercontent.com/b256bda19b0b7ec863774e2a94cae1e4cc524a021c7a636f716e28a8eaba4013/68747470733a2f2f696d672e736869656c64732e696f2f707970692f707976657273696f6e732f6661737472662e737667" alt="Python Versions"&gt;
&lt;/a&gt;
&lt;/p&gt;
&lt;h2&gt;
The Basic Idea&lt;/h2&gt;
&lt;p&gt;Fastrf is a web server that makes it easy to create radio frequency (RF) gain line ups 📡, link budgets 🌎📡🛰️, and simulation models 🧪🧮 to caputre the performance of a RF system.&lt;/p&gt;
&lt;p&gt;This project will stand on the shoulders of some giants:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/tiangolo/fastapi/"&gt;https://github.com/tiangolo/fastapi/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/samuelcolvin/pydantic/"&gt;https://github.com/samuelcolvin/pydantic/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/scikit-rf/scikit-rf"&gt;https://github.com/scikit-rf/scikit-rf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Installing fastrf&lt;/h2&gt;
&lt;p&gt;Install the latest release:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell position-relative js-code-highlight"&gt;
&lt;pre&gt;pip install fastrf&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
Documentation&lt;/h2&gt;
&lt;p&gt;Documentation is hosted at &lt;a href="https://fastrf.org/" rel="nofollow"&gt;fastrf.org&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
Dependencies&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;pyproject.toml&lt;/code&gt; file is used by &lt;a href="https://python-poetry.org/" rel="nofollow"&gt;poetry&lt;/a&gt; to install dependencies into a virtual environment.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Poetry Command Line Interface Documnetation:
&lt;a href="https://python-poetry.org/docs/cli/" rel="nofollow"&gt;https://python-poetry.org/docs/cli/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Only &lt;strong&gt;Python 3.6+&lt;/strong&gt; is supported as required by the black, fastapi, pydantic packages&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This package was created with the &lt;a href="https://github.com/iancleary/pypackage"&gt;iancleary/pypackage&lt;/a&gt; cookiecutter.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/iancleary/fastrf"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;






&lt;p&gt;&lt;em&gt;Source Link for Banner Image: &lt;a href="https://medium.com/swlh/automate-python-testing-with-github-actions-7926b5d8a865"&gt;https://medium.com/swlh/automate-python-testing-with-github-actions-7926b5d8a865&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>actionshackathon</category>
      <category>python</category>
      <category>github</category>
    </item>
    <item>
      <title>Automating your desktop with Ansible</title>
      <dc:creator>Ian Cleary (he/him)</dc:creator>
      <pubDate>Sun, 03 May 2020 00:45:17 +0000</pubDate>
      <link>https://forem.com/iancleary/automating-your-desktop-with-ansible-20jk</link>
      <guid>https://forem.com/iancleary/automating-your-desktop-with-ansible-20jk</guid>
      <description>&lt;p&gt;Hello there,&lt;/p&gt;

&lt;p&gt;First off, I hope you are doing well 😊.&lt;/p&gt;




&lt;p&gt;When it comes to my laptop set up, I care about not having to think too much about my setup between machines. Especially when I want to get right to work, gaming, etc.&lt;/p&gt;

&lt;p&gt;For that reason, it is very comfortable for me to have the same base configuration on each machine (look, feel, keyboard shortcuts, core software, etc.).&lt;/p&gt;

&lt;p&gt;When I learned about infrastructure as code concept, I thought it would be a fun learning experience to try it on my desktop.&lt;/p&gt;

&lt;p&gt;Here is my story of the ways I found to help configure and maintain my desktop configuration.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Ansible Newbie: A true underdog story
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I found a cool bash script on the internet (&lt;em&gt;I didn't understand most of it&lt;/em&gt;) 🤷&lt;/li&gt;
&lt;li&gt;I modified cool bash script for my needs and it worked! 🚀&lt;/li&gt;
&lt;li&gt;I learned about Makefiles. 😄&lt;/li&gt;
&lt;li&gt;I proceeded to do everything with Makefiles. 🤩🤩🤩&lt;/li&gt;
&lt;li&gt;I got tired of running successive Make targets over and again 😐.&lt;/li&gt;
&lt;li&gt;I used Ansible at work and decided to take a course to learn more about it. 🤓&lt;/li&gt;
&lt;li&gt;I put off actually taking the plunge to use Ansible. 🕒🕕🕘🕛&lt;/li&gt;
&lt;li&gt;I finally took the plunge and decided to use Ansible for my configuration. ✔️&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Supported Ubuntu LTS Versions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu 18.04&lt;/li&gt;
&lt;li&gt;Ubuntu 20.04&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;There are no plans to ensure non-LTS versions are supported.&lt;br&gt;
Software support is LTS version dependent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why script this?
&lt;/h2&gt;

&lt;p&gt;While these changes don't take long to do, we could have a script check and assert that they are set the way you want, and change them if they are different than your desired state.&lt;/p&gt;

&lt;p&gt;Lets get into an example to see why I went this route.&lt;/p&gt;

&lt;h3&gt;
  
  
  GNOME Settings and configuration
&lt;/h3&gt;

&lt;p&gt;If you have ever install GNOME Tweak Tools, you've been exposed to some of these settings.  The Settings application exposes some of them as well.&lt;/p&gt;

&lt;p&gt;The settings are organized in a hierarchical manner&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;GNOME Preferences - Shell - Attach Modal Dialogues&lt;/span&gt;
  &lt;span class="na"&gt;dconf&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/org/gnome/shell/overrides/attach-modal-dialogs"&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;false"&lt;/span&gt;
    &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;present&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;GNOME Preferences - Nautilus - Clock Format&lt;/span&gt;
  &lt;span class="na"&gt;dconf&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/org/gnome/desktop/interface/clock-format"&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;'24h'"&lt;/span&gt;
    &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;present&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The two tasks above allow modal dialogues to be moved independently of the application (so you can see what is behind the dialog) and change the clock to 24 hour time.  &lt;/p&gt;

&lt;p&gt;The underlying tools that manage these settings are &lt;code&gt;dconf&lt;/code&gt; and &lt;code&gt;gsettings&lt;/code&gt;.  The &lt;code&gt;dconf-editor&lt;/code&gt; is a graphical application for editing these items.  &lt;code&gt;gsettings&lt;/code&gt; is a way to get, set, and query the schema of entries on the command line.&lt;/p&gt;

&lt;p&gt;The two Ansible tasks use &lt;code&gt;dconf&lt;/code&gt; to set the value for each key.  The &lt;code&gt;state: present&lt;/code&gt; flag tells ansible that we want the key/value pair to be present on our system.&lt;/p&gt;

&lt;h2&gt;
  
  
  What else can be configured and source controlled
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Core Software
&lt;/h3&gt;

&lt;p&gt;This isn't exactly the list of Ansible roles,&lt;br&gt;
but below is a list of what the software installs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ansible&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cherrytree&lt;/code&gt; (like OneNote for Linux)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://snapcraft.io/breaktimer" rel="noopener noreferrer"&gt;Breaktimer&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Visual Studio Code&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kite.com/" rel="noopener noreferrer"&gt;kite AI Autocompletion and Docs for Python&lt;/a&gt;, runs locally&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vscodium.com/" rel="noopener noreferrer"&gt;VSCodium&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/mixn/carbon-now-cli" rel="noopener noreferrer"&gt;carbon-cli&lt;/a&gt;
for beautiful images of my code - right inside my terminal,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Chromium&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker-compose&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://flameshot.js.org/#/" rel="noopener noreferrer"&gt;Flameshot&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;Flameshot keybinding to the Print Screen key using &lt;code&gt;gsettings&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Firefox&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Flatpak&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gh&lt;/code&gt; &lt;a href="https://github.com/cli/cli#installation-and-upgrading" rel="noopener noreferrer"&gt;GitHub CLI&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Nordvpn&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nodejs&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/phw/peek" rel="noopener noreferrer"&gt;Peek&lt;/a&gt; animated GIF screen recorder,&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.postman.com/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt; for API testing,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Protonmail-bridge&lt;/code&gt; &lt;a href="https://protonmail.com/bridge/install" rel="noopener noreferrer"&gt;https://protonmail.com/bridge/install&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;python3.6&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;python3.7&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;python3.8&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Signal Desktop&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Slack&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Snap&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Spotify&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Stacer&lt;/code&gt; &lt;a href="https://github.com/oguzhaninan/Stacer" rel="noopener noreferrer"&gt;https://github.com/oguzhaninan/Stacer&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Standard Notes&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Steam&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Sublime Text&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Telegram&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TickTick&lt;/code&gt; using &lt;a href="https://github.com/jiahaog/nativefier/" rel="noopener noreferrer"&gt;nativefier&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Timeshift&lt;/code&gt; &lt;a href="https://github.com/teejee2008/timeshift" rel="noopener noreferrer"&gt;https://github.com/teejee2008/timeshift&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Tresorit&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;yarn&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zsh&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Makefile help out
&lt;/h3&gt;

&lt;p&gt;I use Makefiles to help run existing Ansible roles or scripts to make editing/updating my configuration easier.&lt;/p&gt;

&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvif9crocr2owz2jk5v65.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvif9crocr2owz2jk5v65.png" alt="Makefile help output text for the repositories' code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  More details
&lt;/h3&gt;

&lt;p&gt;To give you a sense of more details around what some of the make targets do, below is my &lt;code&gt;group_vars/all.yml&lt;/code&gt; file at the time of this article.&lt;/p&gt;

&lt;p&gt;This file sets global variables for all hosts I want to run the playbook on.  In my case, this generally is just the local machine.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

---
docker_compose_version: 1.25.4
flameshot_version: 0.6.0
flatpak_applications:
  - "com.uploadedlobster.peek"
  # - "com.github.alainm23.planner" # not used
  - "com.valvesoftware.Steam"
  - "org.gnome.Evolution"
  - "ch.protonmail.protonmail-bridge"
  - "org.libreoffice.LibreOffice"
gh_version: 0.7.0
jetbrains_mono_version: 1.0.3
protonmail_bridge_version: 1.2.6-1
nodejs_version: "12.x"
nodejs_yarn_global_packages:
  - name: "@vue/cli"
  - name: "@gridsome/cli"
  - name: "nativefier"
  - name: "markdownlint-cli"
  - name: "carbon-now-cli"
snaps_chat:
  - "signal-desktop"
  - "telegram-desktop"
snaps_chat_classic:
  - "slack"
snaps_common:
  - "snap-store"
  - "breaktimer"
  - "cherrytree"
  - "drawio"
  # https://github.com/jgraph/drawio-desktop/issues/138,
  # snap 12.6.5 &amp;gt; flatpak 12.4 (as of 2020-02-28)
  - "spotify"
  - "ncspot"
  - "standard-notes"
snaps_development:
  - "postman"
snaps_development_classic:
  - "code"
  # - "codium" # Code without telemetry
  - "sublime-text"
snaps_web_browsers:
  - "chromium"
  - "firefox"
snaps_web_browsers_plugs:
  - plug: "home"
    app: "chromium"
code_extensions:
  ## Ansible
  - vscoss.vscode-ansible

  ## Docker and Remote Development
  - ms-azuretools.vscode-docker
  - ms-vscode-remote.remote-containers
  - ms-vscode-remote.remote-ssh
  - ms-vscode-remote.remote-ssh-edit
  # - ms-vscode-remote.remote-wsl
  - ms-vscode-remote.vscode-remote-extensionpack

  ## General Development
  - christian-kohler.path-intellisense
  - vscode-icons-team.vscode-icons
  - riccardoNovaglia.missinglineendoffile
  - shardulm94.trailing-spaces
  # - Shan.code-settings-sync

  ## Git Utilities
  - eamodio.gitlens
  - donjayamanne.githistory

  ## Markdown Linting
  - DavidAnson.vscode-markdownlint

  ## Python Development
  - ms-python.python
  - himanoa.Python-autopep8
  - njpwerner.autodocstring
  - wholroyd.jinja
  # Pyright Attribution to tiangolo and florimondmanca
  # https://twitter.com/tiangolo/status/1252891149708275713?s=21
  # &amp;gt; Disabled type checking in the extension settings as I rely on mypy,
  # &amp;gt; but autoimport and unused import colouring alone make it a
  # &amp;gt; 100% worthwhile companion on VSCode
  - ms-pyright.pyright

  ## Spellchecking
  - streetsidesoftware.code-spell-checker

  ## Travis-CI
  # - felixrieseberg.vsc-travis-ci-status # has issues with status resolution

  ## Vue.js Development
  - octref.vetur
  - dbaeumer.vscode-eslint
  - pranaygp.vscode-css-peek

  ## YAML
  - redhat.vscode-yaml # doesn't allow hostname in .travis.yml
stacer_version: 1.1.0
zsh_theme: robbyrussell
zsh_plugins:
  - ansible
  - aws
  - docker
  - docker-compose
  - git
  - pipenv


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Existing Machine
&lt;/h3&gt;

&lt;p&gt;For a walk through of my process on existing machine, please visit&lt;br&gt;
&lt;a href="https://ansible-desktop.iancleary.me/makefile" rel="noopener noreferrer"&gt;https://ansible-desktop.iancleary.me/makefile&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  New Machine Setup
&lt;/h2&gt;

&lt;p&gt;For a new machine, I run the following command&lt;br&gt;
to set up my computer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I like to do this during the initial configuration of the machine.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

wget &lt;span class="nt"&gt;-qO-&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
https://github.com/iancleary/ansible-desktop/raw/main/run.sh | &lt;span class="se"&gt;\&lt;/span&gt;
bash


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

&lt;/div&gt;

&lt;p&gt;This will prompt you for your &lt;code&gt;sudo&lt;/code&gt; password&lt;br&gt;
for the bash script and then once later for&lt;br&gt;
&lt;code&gt;ansible&lt;/code&gt;'s "BECOME PASSWORD" prompt.&lt;/p&gt;

&lt;p&gt;Voila! 🎉🎉🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Customization
&lt;/h3&gt;

&lt;p&gt;If you want to edit the variables, hit &lt;code&gt;CTRL + C&lt;/code&gt; at &lt;code&gt;ansible&lt;/code&gt;'s "BECOME PASSWORD" prompt.&lt;/p&gt;

&lt;p&gt;The script created two extra files that ensure that the &lt;code&gt;ansible-playbook&lt;/code&gt; will on your host name.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Both files are intentionally not version controlled.&lt;br&gt;
This allows hostname specific group_vars relative to the playbook.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;a private &lt;code&gt;.inventory&lt;/code&gt; file&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="c"&gt;#.inventory&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;hostname&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
127.0.0.1


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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;a group_vars file&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# group_vars/$(hostname)/all.yml&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;# You can copy and modify variables over from ../all.yml&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Then run &lt;code&gt;make all&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Voila (with your edits)! 🚀🚀🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;p&gt;Detailed documentation is hosted by Netlify at &lt;a href="https://ansible-desktop.iancleary.me" rel="noopener noreferrer"&gt;https://ansible-desktop.iancleary.me&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thanks
&lt;/h2&gt;

&lt;p&gt;I hope you enjoyed reading about my desktop configuration and feel free to use/modify/share.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/iancleary/ansible-desktop/" rel="noopener noreferrer"&gt;iancleary/ansible-desktop/&lt;/a&gt; is on GitHub and licensed &lt;a href="https://github.com/iancleary/ansible-desktop/blob/main/LICENSE" rel="noopener noreferrer"&gt;GPL-3.0&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you like it give it a star ⭐ and let me know if you have any questions!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Especially if you a suggestion for cool application or piece of software you use 😎😎😎.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Cheers,&lt;br&gt;
Ian&lt;/p&gt;

&lt;p&gt;Edit: Changed default branch from &lt;code&gt;master&lt;/code&gt; to &lt;code&gt;main&lt;/code&gt;&lt;/p&gt;

</description>
      <category>ansible</category>
      <category>desktop</category>
      <category>ubuntu</category>
      <category>gnome</category>
    </item>
    <item>
      <title>An introduction to CI/CD with Travis CI and Python</title>
      <dc:creator>Ian Cleary (he/him)</dc:creator>
      <pubDate>Sun, 08 Dec 2019 22:54:16 +0000</pubDate>
      <link>https://forem.com/iancleary/an-introduction-to-ci-cd-with-travis-ci-and-python-3025</link>
      <guid>https://forem.com/iancleary/an-introduction-to-ci-cd-with-travis-ci-and-python-3025</guid>
      <description>&lt;h2&gt;
  
  
  Automate the boring stuff with Continuous Integration (CI), Continuous Deployment (CD)
&lt;/h2&gt;

&lt;p&gt;I first learned about Travis-CI through venturing out into GitHub to checkout several open source projects. I've seen how they have continuous integration workflows set up test their code on every commit, branch, and pull request.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;That seemed so convenient so I went off to try it myself.&lt;br&gt;
I've documented what I've learned below to help get you started!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Choosing a continuous integration service
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What to consider when creating a Python3 CI/CD pipeline
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python Community on GitHub&lt;/strong&gt; - support for all python3 🐍 versions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose your testing framework&lt;/strong&gt; - Use it with any popular testing framework: pytest, unittest, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open vs. closed source&lt;/strong&gt; - I recommend whenever possible to choose an open source option. The below providers generally offer zero cost options for new open source projects with reasonable build 🛠 constraints. If you go closed source, you’re going to needs to fork over some 💵.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Common providers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Travis-CI&lt;/strong&gt; - my first and has served me well&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Circle CI&lt;/strong&gt; - seems to have a little saner syntax and finer configuration relative to Travis-CI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gitlab&lt;/strong&gt; - leans open source where the others are closed source&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Actions&lt;/strong&gt; - newer, native to GitHub, and offers Linux, Windows, and MacOS builds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My learning started with Travis-CI and am using it since I am familiar with it. I haven't done a detailed comparison of the tools and it fits the needs of simpler python CI/CD projects. I want to look into GitHub actions, now that it’s coming out of Beta.&lt;/p&gt;

&lt;p&gt;You are free to use what you prefer, feel is right, or would like to start with. This article is not a comparison, but rather an introduction into what the process looks like with one CI service.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Start small and build up what you learn. You will make progress, run into challenges, figure some out. Remember to sleep!!!!&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fiwxbx04ay5t9kasbn0dw.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fiwxbx04ay5t9kasbn0dw.jpg" alt="coding-feelings"&gt;&lt;/a&gt;&lt;br&gt;
Photo credit: &lt;a href="https://www.4geeksacademy.co/feelings-learning-coding/" rel="noopener noreferrer"&gt;4geeksacademy.co/feelings-learning-coding/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's an exhilirating, rewarding, and sometimes stressful day to day. 😬&lt;/p&gt;

&lt;p&gt;There isn't a wrong option on your path to learning more about these tools and process. Where you start doesn't have to be where you are in the future. My recommendation is that you pick one, don't over think it, and get it up and working!  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Put your work out there and connect with others.  You don't have to create something from scratch. You can help your favorite existing projects set up or improve their CI/CD pipeline.&lt;br&gt;
It's better when we build together. 🌎🌈🌍🚀🌏&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Knowledge compounds and you'll marvel at where you're at soon. 🗺️ 🚀 💻&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;You should have basic knowledge about Github, Python, testing frameworks, and how to use the &lt;a href="https://www.linode.com/docs/tools-reference/tools/using-the-terminal/" rel="noopener noreferrer"&gt;Terminal&lt;/a&gt;.  Knowledge of Pipenv (Pipfiles) and pytest is a plus, but not required.  CI/CD tools are a great way to learn both.  We will set up a Travis-CI account as well.&lt;/p&gt;




&lt;h2&gt;
  
  
  YAML Basics
&lt;/h2&gt;

&lt;p&gt;Most CI services interact with your repositories using a YAML configuration file.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In case you need a tune up on &lt;a href="https://en.wikipedia.org/wiki/YAML" rel="noopener noreferrer"&gt;YAML&lt;/a&gt;, here is a recommended link:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html" rel="noopener noreferrer"&gt;YAML Syntax, from Red Hat Ansible&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Note: Ansible uses the YAML format, and is is another useful tool. A more detailed guide is an encouraged topic for another time.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Travis-CI YAML Example
&lt;/h2&gt;

&lt;p&gt;Here is a full example &lt;code&gt;.travis.yml&lt;/code&gt; file from one of my projects. We will break down each section.&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="c1"&gt;# .travis.yml&lt;/span&gt;

&lt;span class="na"&gt;dist&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;xenial&lt;/span&gt;

&lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python&lt;/span&gt;

&lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pip&lt;/span&gt;

&lt;span class="na"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.6"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.7"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.8"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nightly"&lt;/span&gt;

&lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;allow_failures&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nightly"&lt;/span&gt;

&lt;span class="na"&gt;install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pip install pipenv --upgrade-strategy=only-if-needed&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pipenv install --dev&lt;/span&gt;

&lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;bash scripts/test.sh&lt;/span&gt;

&lt;span class="na"&gt;after_script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;bash &amp;lt;(curl -s https://codecov.io/bash)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Let's explain each section
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;dist&lt;/strong&gt; is where the Ubuntu Release codename is specified. &lt;code&gt;xenial&lt;/code&gt; is Ubuntu 16.04 LTS codename - see: &lt;a href="http://releases.ubuntu.com/" rel="noopener noreferrer"&gt;http://releases.ubuntu.com/&lt;/a&gt; for a full list.&lt;/p&gt;

&lt;p&gt;This specifies the  base operating system used for the rest of workflow.&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;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;language&lt;/strong&gt; is the programming language used. This tutorial uses python, but it very well could be &lt;code&gt;cpp&lt;/code&gt;, &lt;code&gt;go&lt;/code&gt;, &lt;code&gt;rust&lt;/code&gt;, etc.&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;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pip&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;cache&lt;/strong&gt; allows for python package versions to be stored between runs, to speed up sequential builds.  Cache can apply to more than just python packages.&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;python&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.6"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.7"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.8"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nightly"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;python&lt;/strong&gt;, given the above language specification, is a key for a sequence of python versions to perform builds against. Generally most CI tools use the latest bug release version for each minor version.  The build logs will tell you the specific versions.&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;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;allow_failures&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nightly"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;matrix&lt;/strong&gt; allows for modifications in the above build sequence.  In this case, the allow failures key is specifies a reference to the &lt;strong&gt;python&lt;/strong&gt; sequence above, and has the value of &lt;code&gt;"nightly"&lt;/code&gt;, meaning that that version is allowed to fail.  Think of it as early detection and future python development.  *Note: there are also development versions of each python version, such as &lt;code&gt;"3.8-dev"&lt;/code&gt;.  These are used when python version are in release candidate or beta stages.&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;install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pip install pipenv --upgrade-strategy=only-if-needed&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pipenv install --dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;install&lt;/strong&gt; is the first section that is performed inside each of the build targets (virtual environments for each of the python versions above).  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Each item in the sequence is executed &lt;strong&gt;&lt;em&gt;in order!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Pipenv and Pipfiles
&lt;/h3&gt;

&lt;p&gt;In this example, we are using &lt;code&gt;pipenv&lt;/code&gt; and a &lt;code&gt;Pipfile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Most Pipfiles have production dependencies and development dependencies. You will often find the packages required to run test cases or build documentation under the &lt;code&gt;dev-packages&lt;/code&gt; section.  Below is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;
name &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"pypi"&lt;/span&gt;
url &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://pypi.org/simple"&lt;/span&gt;
verify_ssl &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;dev-packages]
mypy &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
black &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
jupyter &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
better-exceptions &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
pytest &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
pytest-cov &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
isort &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
flit &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
autoflake &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
mkdocs &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
mkdocs-material &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;packages]
pydantic &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"==0.32.2"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command &lt;code&gt;pip install --dev&lt;/code&gt; installs all packages under &lt;code&gt;[packages]&lt;/code&gt; and &lt;code&gt;[dev-packages]&lt;/code&gt;.  &lt;code&gt;pip install&lt;/code&gt; would only install the  packages under &lt;code&gt;[packages]&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Requirement.txt files
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note: It is also common to use &lt;code&gt;pip&lt;/code&gt; with a &lt;code&gt;requirements.txt&lt;/code&gt; file.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python.org now recommends &lt;code&gt;pipenv&lt;/code&gt; as part of its general &lt;a href="https://packaging.python.org/guides/tool-recommendations/" rel="noopener noreferrer"&gt;tool recommendations&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optional aside about different virtual environment options
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Pipenv&lt;/code&gt; has the advantage of providing a mechanism to install your packages into a virtual environment without another package.  There are many alternative - one simple alternaive is &lt;code&gt;venv&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A newer alternative is &lt;code&gt;poetry&lt;/code&gt; (&lt;a href="https://poetry.eustace.io/" rel="noopener noreferrer"&gt;https://poetry.eustace.io/&lt;/a&gt;).  &lt;code&gt;poetry&lt;/code&gt; aims to facilitate what both requirements.txt and Pipfiles do not bundle, and that is released dependencies when deploying to PyPi.  You will typically see &lt;code&gt;flit&lt;/code&gt; and a &lt;code&gt;pyproject.toml&lt;/code&gt; file, or a &lt;code&gt;setup.py&lt;/code&gt; file with redundant depedency information.  That redundancy is what &lt;code&gt;poetry&lt;/code&gt; is aiming to improve upon.&lt;/p&gt;




&lt;h2&gt;
  
  
  Now lets help you get your CI/CD setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Get setup to install my python package project template
&lt;/h3&gt;

&lt;p&gt;Ensure you have a compatible python 🐍 environment on your computer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
python3 &lt;span class="nt"&gt;--version&lt;/span&gt;
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nt"&gt;--version&lt;/span&gt;
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; pytest &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are missing any of the above, you can add the packages to your main python install.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Recommended reading on Python &lt;a href="https://realpython.com/installing-python/#compiling-python-from-source" rel="noopener noreferrer"&gt;main install vs. altinstall&lt;/a&gt;. &lt;br&gt;
&lt;em&gt;If you only have or want one python3 version on your machine, there is no harm to run the following commands. There are nuances between Ubuntu versions (16.04 vs. 18.04 vs. latest) on which python3 version is the default install.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;python3-pip
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;python3-pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have confirmed your base python setup, let’s go ahead and ensure the pipenv and cookiecutter python packages are installed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--user&lt;/span&gt; pipenv
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--user&lt;/span&gt; cookiecutter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Create a Python project and setup the Pipenv virtual environment
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# make sure your path finds --user installs&lt;/span&gt;

&lt;span class="c"&gt;## add `export PATH="$HOME/.local/bin:$PATH"` &lt;/span&gt;
&lt;span class="c"&gt;## to your ~/.bashrc, ~/.zshrc file on linux&lt;/span&gt;

cookiecutter https://github.com/iancleary/pypackage
&lt;span class="c"&gt;# For the sake of brevity, repos on GitHub can just use the 'gh' prefix&lt;/span&gt;
cookiecutter gh:iancleary/pypackage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
`&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fill out the wizard!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;cd new-directory&lt;/code&gt; to change into the new directory you just created (replace &lt;code&gt;new-directory&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;pipenv&lt;/code&gt; to display it's options. Take a look at what’s offered.&lt;/p&gt;

&lt;p&gt;Next, run &lt;code&gt;pipenv install --dev&lt;/code&gt; to install the production and development dependecies specified in the &lt;code&gt;Pipfile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;pipenv shell&lt;/code&gt; to load the virtual environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Run the tests locally and make sure they pass
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;I recommend you open up VS code or your text editor of choice to view the folder structure&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Execute &lt;code&gt;./scripts/tests.sh&lt;/code&gt; from within the directory's Pipenv.&lt;/p&gt;

&lt;p&gt;This command executes a bash script that does several things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;runs &lt;code&gt;pytest&lt;/code&gt; to check test cases and check test coverage&lt;/li&gt;
&lt;li&gt;checks formatting with the &lt;code&gt;black&lt;/code&gt; package&lt;/li&gt;
&lt;li&gt;runs static type checking against your code base with &lt;code&gt;mypy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;checks import sorting from standard lib, your application, and custom packages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are all things that should be relegated to scripts to allow you to free your mind from simple formatting and other draining tasks.  Let it do that work for you!&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Push the directory to a remote git repo
&lt;/h3&gt;

&lt;p&gt;I recommend you follow the guide on the Github Help page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://help.github.com/en/github/importing-your-projects-to-github/adding-an-existing-project-to-github-using-the-command-line" rel="noopener noreferrer"&gt;Adding an existing project to GitHub using the command line&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Connect Travis-CI to the repo
&lt;/h3&gt;

&lt;p&gt;Again, the documentation of both GitHub and Travis-CI are great to follow for this step.&lt;/p&gt;

&lt;p&gt;Head over to &lt;a href="https://travis-ci.org/" rel="noopener noreferrer"&gt;Travis-CI&lt;/a&gt; and sign in with your GitHub account:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://help.github.com/en/enterprise/2.16/admin/developer-workflow/continuous-integration-using-travis-ci" rel="noopener noreferrer"&gt;https://help.github.com/en/enterprise/2.16/admin/developer-workflow/continuous-integration-using-travis-ci&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you login to Travis-CI and Enable GitHub Access, you'll want to configure Travis from your Github Settings page.&lt;/p&gt;

&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fgwuda1jsj92nv68n2nqs.png" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fgwuda1jsj92nv68n2nqs.png" alt="travis-ci-github-authorization"&gt;&lt;/a&gt;&lt;/p&gt;

&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fa2t0gzs16hu473xgmt6j.png" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fa2t0gzs16hu473xgmt6j.png" alt="travis-ci-github-configured-applications"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Now we are configured, let's start a build
&lt;/h3&gt;

&lt;p&gt;Make a simple change to the repo, either a commit, or open a new branch to start a build!&lt;/p&gt;

&lt;p&gt;Grab your 🍿 and let's watch the CI process start and complete! 😎&lt;/p&gt;

&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fhiod8dmjxhl3sneisggy.png" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fhiod8dmjxhl3sneisggy.png" alt="travis-ci-log"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s very cool to watch the process. &lt;br&gt;
The key to remember is the repeatability of the test suite.&lt;/p&gt;

&lt;p&gt;Once complete, you will have your new project added to the Travis-CI dashboard. The three red boxes below are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The connected repo that is currently selected.&lt;/li&gt;
&lt;li&gt;The action that started a build (commit or pull request)&lt;/li&gt;
&lt;li&gt;The build matrix visualized, with links to view more details.&lt;/li&gt;
&lt;/ol&gt;

&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fexzoh09mcel7pxcri8ih.png" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fexzoh09mcel7pxcri8ih.png" alt="travis-ci-dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Happy coding with CI/CD pipelines 🎉🙌
&lt;/h3&gt;

&lt;p&gt;Your setup should give you and others confidence that the code will work under those conditions. If it’s an open source repo, there is no taking your word for it. The logs are right there!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You will not want to go back to your life before it!&lt;br&gt;&lt;br&gt;
It is such a quality improvement!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Where to go from here?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Start offloading and automating your testing, deployments, and other activities.  There is so many opportunites to tie in different hooks or features, this is just the beginning.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Some examples of what else can you automate
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Pypi publishing
&lt;/h4&gt;

&lt;p&gt;I haven't done much in this space yet, but I've seen other projects successfully use the &lt;a href="https://flit.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;flit&lt;/a&gt; python package.&lt;/p&gt;

&lt;p&gt;If that is your next step, checkout &lt;code&gt;flit&lt;/code&gt;.  I know there are some other good tutorials out there to get started inside and outside of a CI/CD pipeline.&lt;/p&gt;

&lt;h4&gt;
  
  
  Jupyter Notebook image deployment with CI/CD to Docker Hub
&lt;/h4&gt;

&lt;p&gt;I've been using Jupyter notebooks and Docker more and more recently. I significantly improved the maintenance model of my personal image by setting up an automated testing and deployment pipeline using Travis CI. Check out my &lt;a href="https://github.com/iancleary/personal-notebook" rel="noopener noreferrer"&gt;personal Jupyter notebook&lt;/a&gt; repository!&lt;/p&gt;

&lt;p&gt;Checkout the Docker image is &lt;a href="https://hub.docker.com/r/iancleary/personal-notebook" rel="noopener noreferrer"&gt;iancleary/personal-notebook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
docker pull iancleary/personal-notebook&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Amazon EC2 instance deployments
&lt;/h4&gt;

&lt;p&gt;I also am in the process of learning how to leverage continuous deployment onto Amazon EC2 instances.&lt;/p&gt;

&lt;p&gt;You can find my notes on &lt;a href="https://github.com/iancleary/travis-ci-aws-notes" rel="noopener noreferrer"&gt;connecting AWS CodeDeploy and Travis CI&lt;/a&gt; using a Flask project.&lt;/p&gt;

&lt;p&gt;This example is a proof of concept, and I'm excited to use this workflow more in the future.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I learned a lot from &lt;a href="https://github.com/tiangolo/fastapi" rel="noopener noreferrer"&gt;https://github.com/tiangolo/fastapi&lt;/a&gt; and credit them as authors within my cookicutter pypackage &lt;a href="https://github.com/iancleary/pypackage/blob/master/%7B%7Bcookiecutter.repo_name%7D%7D/AUTHORS.md" rel="noopener noreferrer"&gt;AUTHORS.md&lt;/a&gt;.  This is not only nice to do, but is required by many open source licenses.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>python</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
