<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: shirtctl</title>
    <description>The latest articles on DEV Community by shirtctl (@shirtctl).</description>
    <link>https://dev.to/shirtctl</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%2Forganization%2Fprofile_image%2F1418%2F02aa17bf-6ee5-4039-adc1-67031d718f7c.png</url>
      <title>DEV Community: shirtctl</title>
      <link>https://dev.to/shirtctl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shirtctl"/>
    <language>en</language>
    <item>
      <title>Breaking News! Startup develops stronger architectural foundation by gathering requirements first!</title>
      <dc:creator>Anthony Wales</dc:creator>
      <pubDate>Thu, 07 Nov 2019 21:50:22 +0000</pubDate>
      <link>https://dev.to/shirtctl/breaking-news-startup-develops-stronger-architectural-foundation-by-gathering-requirements-first-84e</link>
      <guid>https://dev.to/shirtctl/breaking-news-startup-develops-stronger-architectural-foundation-by-gathering-requirements-first-84e</guid>
      <description>&lt;p&gt;The start of any project is exciting, and &lt;code&gt;shirtctl&lt;/code&gt; is no different. Last month Blair and I &lt;a href="https://dev.to/shirtctl/all-your-shirt-are-belong-to-us-55ji"&gt;announced&lt;/a&gt; we’re working a brand new project to bring continuous delivery to tech tees.&lt;/p&gt;

&lt;p&gt;We set out with a goal to help tech brands create and ship cool t-shirts reliably to their fans at any time. 👕👚&lt;/p&gt;

&lt;p&gt;From our experience, we know just how easy it is to get carried away with building technology solutions before we even understand our requirements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wDjGaPMi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/Hix8VmG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wDjGaPMi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/Hix8VmG.png" alt="Solutioning/Requirements Comic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article is a summary of the principles we developed throughout first #shirtday hack, and how they  informed certain architecture decisions. And since we’re building &lt;code&gt;shirtctl&lt;/code&gt; in the open, expect to see more posts about how we implement these as our project develops. &lt;/p&gt;

&lt;h2&gt;
  
  
  Our Mission:
&lt;/h2&gt;

&lt;p&gt;We make it super easy for companies to build their brand and connect with the community by harnessing the awesome power of t-shirts.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How:&lt;/strong&gt;  Our MVP: For &lt;code&gt;shirtctl&lt;/code&gt; to work, we need to be able to join brands and fans together for the reliable transfer of merchandise. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bkzO7kDc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/dYQBw5I.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bkzO7kDc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/dYQBw5I.png" alt="Process Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With our MVP defined, we had everything we need to consider what high level platform architecture decisions we would need to make to build a strong technology foundation. &lt;/p&gt;

&lt;h2&gt;
  
  
  Requirement Principles:
&lt;/h2&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    * [Flexibility](#Flexibility)
    * [Relentless Focus](#Relentless-Focus)
    * [Security in Depth](#Secure)
    * [Frugal by Design](#Frugal-Architecture)
    * [Easy to Consume](#Easy-to-Consume)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Flexibility
&lt;/h3&gt;

&lt;p&gt;We are going to make mistakes. Our path, like any startup, is unclear. Recognising that we are only a small team, we have to live and breath the fail-fast approach to bring &lt;code&gt;shirtctl&lt;/code&gt; to life as soon as possible.&lt;/p&gt;

&lt;p&gt;If we need to change directions, we need to be able to do so quickly without having to rebuild from scratch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H-6Bc4py--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1200/1%2AJZ9i7JzobVeZbhoOODuPyA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H-6Bc4py--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1200/1%2AJZ9i7JzobVeZbhoOODuPyA.png" alt="Fail Fast"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;a href="https://medium.com/@jocatorres/fail-fast-vs-learn-fast-f7912fdc12e4"&gt;Image Source&lt;/a&gt;



&lt;p&gt;&lt;strong&gt;Adopting Architectures:&lt;/strong&gt;&lt;br&gt;
Hybrid Cloud Architecture provides:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Rapid deployment.&lt;/li&gt;
&lt;li&gt;Horizontally scalable.&lt;/li&gt;
&lt;li&gt;Heavily automated.&lt;/li&gt;
&lt;li&gt;Standardisation.&lt;/li&gt;
&lt;li&gt;Minimum commitment (some services are billed per 100ms).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Continuous Delivery Architecture (Continuous Integration with Continuous Delivery):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Short software deployment cycles releasing software with greater speed and frequency.&lt;/li&gt;
&lt;li&gt;Incremental updates for patching and feature enhancement.&lt;/li&gt;
&lt;li&gt;Software release governance.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Relentless Focus
&lt;/h3&gt;

&lt;p&gt;We know our main goal is to connect tech brands and their fans, not to host and manage infrastructure. We don’t have time to do the Design, Build and Run of a new infrastructure and platform service. In addition, the management overhead of a single tenancy wouldn't be time or cost effective. We are trying to shift as much as possible to managed services so we can worry just about &lt;code&gt;shirtctl&lt;/code&gt; and leave the rest to the to the infrastructure experts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dnqAOv2e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://stxnext.com/media/filer_public_thumbnails/filer_public/64/0d/640d7abe-4899-4e28-8763-267737ef7737/serverless-architecture-comparisonpng__1920x1080_.png__680x383_q85_crop_subsampling-2_upscale.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dnqAOv2e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://stxnext.com/media/filer_public_thumbnails/filer_public/64/0d/640d7abe-4899-4e28-8763-267737ef7737/serverless-architecture-comparisonpng__1920x1080_.png__680x383_q85_crop_subsampling-2_upscale.jpg" alt="Serverless"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;a href="https://stxnext.com/blog/2017/12/06/serverless-computing-explained-comparing-features-and-pricing-saas-iaas-paas/"&gt;Image Source&lt;/a&gt;



&lt;p&gt;&lt;strong&gt;Adopting Architectures:&lt;/strong&gt;&lt;br&gt;
Managed Cloud Architecture:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Responsibility abstraction (just worry about the code, 'Serverless').&lt;/li&gt;
&lt;li&gt;Consumption based billing.&lt;/li&gt;
&lt;li&gt;Pre-architected building blocks.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Serverless Architecture provides; outsourcing as much responsibility as possible so we can just worry about the code.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Security in Depth
&lt;/h3&gt;

&lt;p&gt;With cyberattacks on the rise, and increasing consumer awareness of the risks of personal information being exposed, we need a modern approach to security that is simple and effective. We want to keep &lt;code&gt;shirtctl&lt;/code&gt; free of traditional approaches to security that are prone to failure and costly to design, build and manage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5zbpQ3Vw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/JETPq5E.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5zbpQ3Vw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/JETPq5E.png" alt="Secure"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;a href="https://www.actiac.org/system/files/ACT-IAC%20Zero%20Trust%20Project%20Report%2004182019.pdf"&gt;Image Source&lt;/a&gt;



&lt;p&gt;&lt;strong&gt;Adopting Architectures:&lt;/strong&gt;&lt;br&gt;
Zero Trust Security Model:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An alternative security model to not trust anything remediating the rudimentary fault in traditional strategies to only protect from the outside.  In this architecture, every pillar is verified.&lt;/li&gt;
&lt;li&gt;All communication paths need to be encrypted especially for micro-services.&lt;/li&gt;
&lt;li&gt;Validation and authentication are performed between all services.&lt;/li&gt;
&lt;li&gt;Low cost with minimal special tooling required.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Frugal by Design
&lt;/h3&gt;

&lt;p&gt;As a super interesting side-project, &lt;code&gt;shirtctl&lt;/code&gt; has no funding to splurge on unnecessary expenses. Just like a 1990’s startup using the garage as an office, we’re using modern architectures for their opportunities to save big on cost and time. As a public cloud consumer, we’re capitalising on the opportunities that cloud presents to pay for only what we consume.&lt;/p&gt;

&lt;p&gt;We don’t expect to ever have to invest big in infrastructure development projects to enable our data lake or deployment pipeline, and just like we see the biggest disruptors changing their markets, we’re hoping it works for tech tees too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hwrGeQ4C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://solutionsreview.com/data-integration/files/2018/10/oie_wFhUpS8vKVmY.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hwrGeQ4C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://solutionsreview.com/data-integration/files/2018/10/oie_wFhUpS8vKVmY.jpg" alt="Frugal Architecture"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;a href="https://solutionsreview.com/data-integration/consumption-based-pricing-why-2019-will-be-the-year-to-align-value-with-investment/"&gt;Image Source&lt;/a&gt;



&lt;p&gt;&lt;strong&gt;Adopting Architectures:&lt;/strong&gt;&lt;br&gt;
Public Cloud Architectures:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Consumption based billing with some products such as serverless allowing you to only pay for the CPU/RAM cycles used to run the code not the OS and below.&lt;/li&gt;
&lt;li&gt;Free tier pricing for certain services to help get you started allowing for experimentation with different technologies ensuring you pick the best one.&lt;/li&gt;
&lt;li&gt;Startup credits to be used on any service allowing you to try services that have costs associated.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Easy to Consume
&lt;/h3&gt;

&lt;p&gt;With our small team and non-existant budget, we need &lt;code&gt;shirtctl&lt;/code&gt; to be usable by as many people as possible. So we’re starting out with a web app at &lt;a href="https://shirtctl.com"&gt;https://shirtctl.com&lt;/a&gt;. We think you’ll like it when ready. A lot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zePexxXM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/600/0%2AQCqRjzCc_QPux8C7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zePexxXM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/600/0%2AQCqRjzCc_QPux8C7.png" alt="Multiplatform"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;a href="https://blog.kotlin-academy.com/lessons-from-my-first-multiplatform-kotlin-project-d4e311f15874?gi=af3e85f95689"&gt;Image Source&lt;/a&gt;



&lt;p&gt;&lt;strong&gt;Adopting Architectures:&lt;/strong&gt;&lt;br&gt;
Web App Architecture:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Availability to be accessed over the internet.&lt;/li&gt;
&lt;li&gt;Compatibility with many different platforms and devices.&lt;/li&gt;
&lt;li&gt;Very low time to get your product into the hands of your potential consumers.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>devops</category>
      <category>startup</category>
      <category>architecture</category>
      <category>requirements</category>
    </item>
    <item>
      <title>Building a super fast serverless container deployment pipeline on Google Cloud</title>
      <dc:creator>Blair Hudson</dc:creator>
      <pubDate>Wed, 06 Nov 2019 03:10:11 +0000</pubDate>
      <link>https://dev.to/shirtctl/building-a-super-fast-serverless-container-deployment-pipeline-on-google-cloud-251o</link>
      <guid>https://dev.to/shirtctl/building-a-super-fast-serverless-container-deployment-pipeline-on-google-cloud-251o</guid>
      <description>&lt;p&gt;One of our driving principles for &lt;code&gt;shirtctl&lt;/code&gt; is #frugalbydesign - we simply don’t want to be paying for anything that we don’t use.&lt;/p&gt;

&lt;p&gt;Our architecture needs to balance cost alongside other core capabilities like application security 🔒, design flexibility 💪 and developer collaboration 👩‍💻👨‍💻.&lt;/p&gt;

&lt;p&gt;In this post, we’ll be sharing the some of the details of our continuous deployment pipeline. We’ve combined BitBucket with Google's Cloud Build service, which deploys our applications onto Cloud Run in an average of 1-2 minutes per build!&lt;/p&gt;

&lt;p&gt;For development, we’ve also created a local build workflow to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Speed up local code iteration 🏎💨&lt;/li&gt;
&lt;li&gt;Minimise the number of Cloud Build jobs and Cloud Run revisions (#frugalbydesign) ☁️&lt;/li&gt;
&lt;li&gt;Keep our commit log tidy! 🧹&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s a high level view of our approach:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1DprbrVC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/kx1pod5sz2e8pj8bes2h.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1DprbrVC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/kx1pod5sz2e8pj8bes2h.jpeg" alt="shirtctl-ci-pipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let’s take a closer look at some of the major components. 🔎 &lt;/p&gt;

&lt;h2&gt;
  
  
  Speedy local builds
&lt;/h2&gt;

&lt;p&gt;Our MVP sign-ups API is a Python Flask app. It relies on a few various Python packages that provide the REST framework, email, storage and other capabilities. Right now it’s a simple &lt;code&gt;api.py&lt;/code&gt; file and a &lt;code&gt;requirements.txt&lt;/code&gt; that represents our package dependencies.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;Dockerfile&lt;/code&gt; for local and cloud deployment is purposefully identical, so we can focus on API development.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:slim&lt;/span&gt;

&lt;span class="c"&gt;# install python dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv /app/env
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;/app/env/bin/pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# configure port (Cloud Run requires 8080)&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; PORT=8080&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; $PORT&lt;/span&gt;

&lt;span class="c"&gt;# setup application runtime&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app/src&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; GOOGLE_APPLICATION_CREDENTIALS="/app/sa-key.json”&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; entrypoint.sh .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x entrypoint.sh

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; api.py .&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["sh", "-c", "./entrypoint.sh"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have a &lt;code&gt;localbuild.sh&lt;/code&gt; script that emulates Cloud Run deployment locally using Docker, which means we can iterate our development tasks very quickly without having to redeploy to Cloud Run.&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="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nv"&gt;REPO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; .git &lt;span class="si"&gt;$(&lt;/span&gt;git config &lt;span class="nt"&gt;--get&lt;/span&gt; remote.origin.url&lt;span class="si"&gt;))&lt;/span&gt;
&lt;span class="nv"&gt;BRANCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;--abbrev-ref&lt;/span&gt; HEAD&lt;span class="si"&gt;)&lt;/span&gt;

gcloud iam service-accounts keys create sa-key.json &lt;span class="se"&gt;\&lt;/span&gt;
 &lt;span class="nt"&gt;--iam-account&lt;/span&gt; service-account@project.iam.gserviceaccount.com
&lt;span class="nv"&gt;SA_KEY_FILE_BASE64&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;sa-key.json | &lt;span class="nb"&gt;base64&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

docker build &lt;span class="nt"&gt;-t&lt;/span&gt; shirtctl-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REPO&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BRANCH&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:latest &lt;span class="nb"&gt;.&lt;/span&gt;

docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;K_SERVICE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;localbuild &lt;span class="se"&gt;\&lt;/span&gt;
 &lt;span class="nt"&gt;-e&lt;/span&gt; SA_KEY_FILE_BASE64 &lt;span class="se"&gt;\&lt;/span&gt;
 &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="se"&gt;\&lt;/span&gt;
 &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;:/app/src &lt;span class="se"&gt;\&lt;/span&gt;
 shirtctl-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REPO&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BRANCH&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can “hot reload” 🔥 our changes to develop even faster! &lt;code&gt;entrypoint.sh&lt;/code&gt; determines at run time whether to run Flask or Gunicorn depending on the value of &lt;code&gt;$K_SERVICE&lt;/code&gt;. This way our Flask service restarts automatically when changes to the source code are detected:&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="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$SA_KEY_FILE_BASE64&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$GOOGLE_APPLICATION_CREDENTIALS&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$K_SERVICE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"localbuild"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FLASK_APP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"api.py"&lt;/span&gt;
    &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FLASK_DEBUG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
    /app/env/bin/flask run &lt;span class="nt"&gt;--host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0 &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PORT&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
    /app/env/bin/gunicorn &lt;span class="nt"&gt;--bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0:&lt;span class="nv"&gt;$PORT&lt;/span&gt; api:app
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  BitBucket to Cloud Source Repository
&lt;/h2&gt;

&lt;p&gt;Code is committed and pushed to a private BitBucket repo. Our branching structure is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⚙️ &lt;code&gt;dev&lt;/code&gt; for feature-based development (we can have as many of these as required!)&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;test&lt;/code&gt; where all feature dev branches are merged to (by pull request only)&lt;/li&gt;
&lt;li&gt;🚀 &lt;code&gt;prod&lt;/code&gt; where &lt;code&gt;test&lt;/code&gt; is released to (also by pull request only, with dual approval required)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The BitBucket repo is &lt;a href="https://cloud.google.com/source-repositories/docs/mirroring-a-bitbucket-repository"&gt;automatically synced to a Cloud Source Repository&lt;/a&gt; of the same name and branch structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying with Cloud Build
&lt;/h2&gt;

&lt;p&gt;Cloud Build allow &lt;a href="https://cloud.google.com/cloud-build/docs/running-builds/automate-builds"&gt;a build job to trigger on a push&lt;/a&gt; to our repo. This runs submits the &lt;code&gt;cloudbuild.yaml&lt;/code&gt; file from our repo to Cloud Build, which accomplishes the following steps for the current branch:&lt;/p&gt;

&lt;p&gt;Pulls the previous Docker image from Google Container Registry&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull gcr.io/&lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt;/&lt;span class="nv"&gt;$REPO_NAME&lt;/span&gt;-&lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Builds and tags a new Docker image from our &lt;code&gt;Dockerfile&lt;/code&gt; above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
 &lt;span class="nt"&gt;--cache-from&lt;/span&gt; gcr.io/&lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt;/&lt;span class="nv"&gt;$REPO_NAME&lt;/span&gt;-&lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;:latest &lt;span class="se"&gt;\&lt;/span&gt;
 &lt;span class="nt"&gt;-t&lt;/span&gt; gcr.io/&lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt;/&lt;span class="nv"&gt;$REPO_NAME&lt;/span&gt;-&lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;:&lt;span class="nv"&gt;$SHORT_SHA&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
 &lt;span class="nt"&gt;-t&lt;/span&gt; gcr.io/&lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt;/&lt;span class="nv"&gt;$REPO_NAME&lt;/span&gt;-&lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pushes the latest image to Google Container Registry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker push gcr.io/&lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt;/&lt;span class="nv"&gt;$REPO_NAME&lt;/span&gt;-&lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;:&lt;span class="nv"&gt;$SHORT_SHA&lt;/span&gt;
docker push gcr.io/&lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt;/&lt;span class="nv"&gt;$REPO_NAME&lt;/span&gt;-&lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploys the latest image to Cloud Run, and maps the appropriate domains to access the service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud beta run deploy &lt;span class="nv"&gt;$REPO_NAME&lt;/span&gt;-&lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
         &lt;span class="nt"&gt;--image&lt;/span&gt; gcr.io/&lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt;/&lt;span class="nv"&gt;$REPO_NAME&lt;/span&gt;-&lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;:&lt;span class="nv"&gt;$SHORT_SHA&lt;/span&gt;
gcloud beta run domain-mappings create &lt;span class="se"&gt;\&lt;/span&gt;
         &lt;span class="nt"&gt;--service&lt;/span&gt; &lt;span class="nv"&gt;$REPO_NAME&lt;/span&gt;-&lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
         &lt;span class="nt"&gt;--domain&lt;/span&gt; &lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;.&lt;span class="nv"&gt;$REPO_NAME&lt;/span&gt;.shirtctl.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all for now! Keep an eye on &lt;a href="https://shirtctl.com"&gt;shirtctl.com&lt;/a&gt; for our MVP sign-ups launch! 👕👚&lt;/p&gt;

</description>
      <category>googlecloud</category>
      <category>devops</category>
      <category>python</category>
      <category>git</category>
    </item>
    <item>
      <title>shirtctl --blog: a series on building a tech tee startup</title>
      <dc:creator>Blair Hudson</dc:creator>
      <pubDate>Thu, 31 Oct 2019 08:53:00 +0000</pubDate>
      <link>https://dev.to/shirtctl/all-your-shirt-are-belong-to-us-55ji</link>
      <guid>https://dev.to/shirtctl/all-your-shirt-are-belong-to-us-55ji</guid>
      <description>&lt;p&gt;Hey there and welcome to &lt;code&gt;shirtctl --blog&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is the very beginning of the official blog of &lt;code&gt;shirtctl&lt;/code&gt;! Pronounced “&lt;em&gt;shirt control&lt;/em&gt;”, we’re bringing continuous delivery to tech tees. 👕👚&lt;/p&gt;

&lt;h3&gt;
  
  
  Ok, what in the world are you talking about?
&lt;/h3&gt;

&lt;p&gt;In the world of DevOps, continuous delivery is an approach to building and shipping great software to users at any time, with a focus on reliability. 👨‍💻👩‍💻📦🚢&lt;/p&gt;

&lt;p&gt;In the world of tech merch, that means creating and shipping cool t-shirts reliably to fans at any time. 😎&lt;/p&gt;

&lt;h3&gt;
  
  
  So what is this blog about then?
&lt;/h3&gt;

&lt;p&gt;We’re building &lt;code&gt;shirtctl&lt;/code&gt; out in the open! &lt;/p&gt;

&lt;p&gt;In this blog we’ll be publishing a series of short posts around all of the product, user, architecture, engineering and design challenges we have. We'll be detailing the options we explore and how we make key decisions, all to show you the steps we take building &lt;code&gt;shirtctl&lt;/code&gt; from scratch as a cloud-native data-driven DevSecBizFinOps startup! 🚀&lt;/p&gt;

&lt;p&gt;And you can ask us anything along the way! (Just leave a comment.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Hmm... who are you anyway?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;shirtctl&lt;/code&gt; began in the warmth of down-under October 2019 by Sydneysiders &lt;a href="https://www.linkedin.com/in/blairhudson/"&gt;Blair Hudson&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/anthonyjwales/"&gt;Anthony Wales&lt;/a&gt;. Initially one of those &lt;em&gt;this-is-so-crazy-it-just-might-work ideas&lt;/em&gt;, we’re combining our experience across Australia’s technology sector to sprint 🏃‍♂️, hack 💻 and ship 📦 our way to tech tee haven. How exciting!&lt;/p&gt;

&lt;h3&gt;
  
  
  Wait, I’m still confused. What is your product?
&lt;/h3&gt;

&lt;p&gt;How would you like free tech tees delivered to your office every* month? &lt;/p&gt;

&lt;p&gt;🤩 Sounds good? We think so too!&lt;/p&gt;

&lt;p&gt;(*Assuming we can find something in your size. We think we can!)&lt;/p&gt;

&lt;h3&gt;
  
  
  You said free?
&lt;/h3&gt;

&lt;p&gt;We’re making it super easy for technology companies to build their brand and connect with the community by harnessing the awesome power of t-shirts. ✨ They provide the goods and cover shipping. You provide your size and office address. &lt;code&gt;shirtctl&lt;/code&gt; makes it all happen. Simple!&lt;/p&gt;

&lt;h3&gt;
  
  
  I love it! Where do I sign up?
&lt;/h3&gt;

&lt;p&gt;While we haven’t launched yet, we plan to start sign-ups for developers working in Sydney very soon. 🥳&lt;/p&gt;

&lt;p&gt;In true MVP style, devs will be able to sign-up using our awesome API and the programming language of their choice! Follow our blog (&lt;a href="https://dev.to/shirtctl"&gt;dev.to/shirtctl&lt;/a&gt;) and keep an eye on &lt;a href="https://shirtctl.com"&gt;shirtctl.com&lt;/a&gt; for docs to get started. &lt;/p&gt;

&lt;p&gt;Once we prioritise it (#agile), we’ll be building out a sign-up form for everyone else to join in on the free tee fun too (including the lazy devs)! 👫👬👭&lt;/p&gt;

&lt;h3&gt;
  
  
  I want to build my brand, how do I make tees available?
&lt;/h3&gt;

&lt;p&gt;Watch this space. &lt;code&gt;shirtctl&lt;/code&gt; is working with a small number of launch partners in Sydney to create a fantastic SX (we coined it, &lt;em&gt;shirt experience&lt;/em&gt; is the next big thing). Then we'll open up to all!&lt;/p&gt;

&lt;p&gt;If you’re really really interested to be involved early, reach out to us in the comments or using the links to our LinkedIn profiles above (since we haven’t prioritised building a contact form yet...).&lt;/p&gt;

&lt;p&gt;👕👚&lt;/p&gt;

</description>
      <category>devops</category>
      <category>design</category>
      <category>microservices</category>
      <category>startup</category>
    </item>
  </channel>
</rss>
