Just do it! Automate your CI/CD pipeline, have a single passing test, and have a deployment script that publishes your project to a staging environment, then a production environment.

Another option is to embrace trunk-based development and just have a production environment and deploy your code using feature flags.

The point is to take the time upfront to set up your automated delivery pipeline first before you start to write code.

Before hyper, I was part of a team building a new software application and during the development process, everything was going great in our local environment. We were knocking out features left and right and our tests were verifying everything. As time went on, we would demo our work to our stakeholders, they would see the progress, but continue to make adjustments. These adjustments made the usability of the software better, but they impacted our capacity as the delivery date became closer. We shifted into another gear and began to implement the adjustments to the software application. Now it is time to ship our product, no sweat, we just push our code to the staging environment, then the production environment.

Code push "take one", 404 (Resource not found), what? How can that be? Is the database running? Is it accessible by the application? Is the application running? Check the logs, oh it's missing a dependency that happened to be installed on the local machine. Code push "take two", success! no more 404, but authentication does not work, I can't sign up. WTF, oh crap, we need to create a new OAuth2 service for both staging and production, because the callback URL needs to point to the actual environment. Code push take three, another issue, anyway, eventually we get the app deployed by the delivery date, but the process was a process of stress. And because the timeline was so tight we completely lost focus of documenting our deployment process or the time to create robust delivery scripts.

What is the answer? It's obvious, hire an SRE (Site Reliability Engineer) to do this for you right? Well, that will work, but that SRE needs to know everything about your app and technical stack, they need the time to understand what decisions you made and why you made them, then they need to start to dynamically create the deployment scripts, etc. Which will take time, and for many teams this is a valid process. But, I would like to recommend another approach, how about "ship your app first", before one line of business logic is written. Take the time upfront to create the environments and write the automated deployment scripts and wire everything up end to end. Put a coming soon page up for your app.

Why ship first?

Simple, automation is easier to get right when not under duress. For example, all of your tasks are complete, everything works on your machine, the reviews have gone great and the stakeholders are excited to see your deliverable in a production environment. They think it will only take a minute, a push of the button to promote your incredible code to a production environment that meets all the performance and security requirements.

Guess what?  The CI/CD setup always takes time, even for simple things, it takes time and there are always issues that come up between your dev environment and the staging and production environments, you may find the tests don't run in the CI because they are missing some unexpected dependency. Or you may find that the SSL Cert is not generating because y0u don't have the correct DNS configuration and you need operations to configure it and they are busy with other issues. You may find that the Redis production server you were promised months ago is not ready yet. This creates drama and anxiety and leads to pressure and frustration.

Just ship it! 🐿

I have found, taking the time to set up CI/CD before writing code saves a lot of time and effort and reduces frustration at the point of delivery. Give it a try! You will be surprised.

CI (Github actions)

on:
  push:
    branches: "**"
    tags-ignore: "*"

jobs:
  test-deno:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        deno-version: [1.x]
    steps:
      - uses: actions/checkout@v2
      - name: Use Deno ${{matrix.deno-version}}
        uses: denoland/setup-deno@v1
        with:
          deno-version: ${{matrix.deno-version}}
      - run: make
        env:
          CI: true

CD (Github actions)

jobs:
  publish-nest:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: denoland/setup-deno@v1
        with:
          deno-version: v1.x
      - run: deno install -A -f --unstable --no-check https://x.nest.land/eggs@0.3.6/eggs.ts
      - run: |
          export PATH="/home/runner/.deno/bin:$PATH"
          eggs link ${{ secrets.NESTAPIKEY }}
          eggs publish --yes

What if I am adding a new feature to an existing product?

This is one of the best things about automation is the ability to use feature flags, create your new module and any dependencies with no code, but hidden behind a feature flag, and ship it! Make sure you can push changes in real-time, now all you have to do is write and test your feature, have the code reviewed, and BAM! you are done! "Easy peasy lemon squeezy!" 🍋

"Ship first, code later"

It may feel different, but it is not that hard and once you see the benefits you will jump for joy because you will no longer fear that push of code, it is done, you just have to make it work, which is the easy part 😀!

Not convinced? Trust the science!

A DevOps study conducted with 5,000 developer teams assessing the quality and performance, and it turns out the teams that ship code multiple times a day have a higher quality score than teams that ship code weekly, monthly or quarterly. To dive deeper read Accelerate - https://www.amazon.com/Accelerate-Software-Performing-Technology-Organizations/dp/1942788339 or google DORA metrics. It will be time worth investing. While you are reading, ship your code, go ahead right now and push that developing code behind a feature flag, and know, that when it works on your machine, it will work in production! 🐿

BONUS: Pro Tip

Develop in the cloud! By developing in the cloud, you keep your development environment clean and similar to the deployment environment. We use https://gitpod.io for our development environment and the result is frictionless experiences.

⚡️hyper can help you ship! Spin up Data, Cache, Search, Storage, and Queue Services with a single click! Check it out at https://hyper.io

Glossary

404 - Resource not found - an http status code that is returned when the server is unable to provide a response for the given request.

OAuth2 - OAuth2 is a standard authentication and authorization specification that enables users to register and log in to applications using secure identity management services, so that they do not have to share/enter identity information in the application unless the choose to.

CI/CD Pipeline - Continuous Integration and Continuous Delivery are quality automation tools, that all applications should to distribute software to users. Continuous Integration is the process of constantly integrating developers code into the main code branch while developing the application. Continuous Delivery is the process of shipping the application when new code is applied, reviewed and approved.

Feature flags - are identifiers that enable/disable features by configuration.