<?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: Bruno Luiz Silva</title>
    <description>The latest articles on DEV Community by Bruno Luiz Silva (@brunoluiz).</description>
    <link>https://dev.to/brunoluiz</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%2F487563%2Fac92651e-ac2b-494c-bc59-4c6406e06980.jpeg</url>
      <title>DEV Community: Bruno Luiz Silva</title>
      <link>https://dev.to/brunoluiz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brunoluiz"/>
    <language>en</language>
    <item>
      <title>The forgotten art of HTML redirects, without either HTTP 301 or JavaScript</title>
      <dc:creator>Bruno Luiz Silva</dc:creator>
      <pubDate>Thu, 17 Jun 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/brunoluiz/the-forgotten-art-of-html-redirects-without-either-http-301-or-javascript-4fnd</link>
      <guid>https://dev.to/brunoluiz/the-forgotten-art-of-html-redirects-without-either-http-301-or-javascript-4fnd</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b0V9iHKS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2021/jun/redirect-users-client-side-only/cover.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b0V9iHKS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2021/jun/redirect-users-client-side-only/cover.jpg" alt="Photo by Javier Allegue Barros on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the first things API developers learn is HTTP codes. Usually, people already saw some 404 around, but soon they learn about the uses of 2xx, 4xx and 5xx codes. Probably you, insidious reader, realised I jumped the 3xx series.&lt;/p&gt;

&lt;p&gt;Most first time developers never hear about 3xx, but probably because most haven’t gone through some scenario requiring it. There are many codes in this series, but the code of interest here is HTTP 301. If a developer wants to redirect users, returning 301 will indicate to the client that the resource was moved permanently to a new address (specified in the response).&lt;/p&gt;

&lt;p&gt;HTTP 301 can be useful in many cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redirect URLs if there was a major URL change in a website (xyz.com/blog/2020/01/some-title to xyz.com/some-title).&lt;/li&gt;
&lt;li&gt;Create redirect flows for auth (OAuth; redirect on user log-out).&lt;/li&gt;
&lt;li&gt;Shorten URLs (redirect xyz.com/foo to foo.com).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These can only be returned by HTTP servers. But, there are times you might not want to maintain an HTTP server. You might have a static generated website, where you want to redirect old URLs to new URLs (due to SEO), or just have shortened URLs together with your static website.&lt;/p&gt;

&lt;p&gt;Instead of setting up and maintaining an HTTP server, or relying on some third party to set up the redirects for your static site (example: Netlify or Vercel redirect configs), you can use static (HTML) files instead.&lt;/p&gt;

&lt;p&gt;One could use JavaScript to set &lt;code&gt;window.location=https://foo.bar&lt;/code&gt;, but this might not work as some people are browsing with JavaScript disabled nowadays. The real answer lies on &lt;code&gt;&amp;lt;meta http-equiv="refresh" /&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It works as an HTTP redirect code, but it is done completely on the client-side. This feature was introduced back &lt;a href="https://www.w3.org/TR/WCAG20-TECHS/H76.html"&gt;in Netscape 1.1, back in 1995&lt;/a&gt; and &lt;a href="https://ogp.me/"&gt;there is a bit more explanation on the W3C website&lt;/a&gt;. It is still recommended to use HTTP redirects instead of this, but static websites might not have this choice sometimes (content hosted on Github Pages, for example).&lt;/p&gt;

&lt;p&gt;To try it out, create an HTML file with the following code and then open it in the browser. The browser should load the file and redirect straight to the target URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Bruno L. Silva - Twitter&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"refresh"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"0; url=https://twitter.com/brunoluiz"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As promised, this is plain HTML. But, creating files like this can get a bit annoying. Besides, if you host this file in Github Pages and share the link around, the metadata of the target URL will not be present (example: &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;, &lt;a href="https://ogp.me/"&gt;OpenGraph&lt;/a&gt; and &lt;a href="https://developer.twitter.com/en/docs/twitter-for-websites/cards/guides/getting-started"&gt;Twitter Card&lt;/a&gt; meta tags). This means Facebook, Twitter, messengers and others will not render a card with the target details.&lt;/p&gt;

&lt;p&gt;To avoid the manual work of copying metadata around and setting these files manually, I’ve created a tool called &lt;a href="https://github.com/brunoluiz/urlzap"&gt;URLZap&lt;/a&gt;. Based on a YAML config, it creates HTML files with all the required metadata and the redirect HTML meta tag. There are details on how to use it, both through CLI or Github Actions, &lt;a href="https://github.com/brunoluiz/urlzap"&gt;on the project’s page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The YAML configuration and output files will looks like the snippets below.&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;# Example configuration file to be used with: urlzap generate --config ./config.yaml&lt;/span&gt;
&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;./output'&lt;/span&gt;
&lt;span class="na"&gt;urls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;github&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Example output at ./output/github/index.html --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;GitHub: Where the world builds software · GitHub&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"canonical"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://github.com"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"robots"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"noindex"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"refresh"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"0; url=https://github.com"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"GitHub is where over 65 million developers shape the future of software, together. Contribute to the open source community, manage your Git repositories, review code like a pro, track bugs and features, power your CI/CD and DevOps workflows, and secure code before you commit it."&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"fb:app_id"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"1401488693436528"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:image:src"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://github.githubassets.com/images/modules/site/social-cards/github-social.png"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:site"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"@github"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:card"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"summary_large_image"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"GitHub: Where the world builds software"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"GitHub is where over 65 million developers shape the future of software, together. Contribute to the open source community, manage your Git repositories, review code like a pro, track bugs and feat..."&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://github.githubassets.com/images/modules/site/social-cards/github-social.png"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image:alt"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"GitHub is where over 65 million developers shape the future of software, together. Contribute to the open source community, manage your Git repositories, review code like a pro, track bugs and feat..."&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:site_name"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"GitHub"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:type"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"object"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"GitHub: Where the world builds software"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:url"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://github.com/"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"GitHub is where over 65 million developers shape the future of software, together. Contribute to the open source community, manage your Git repositories, review code like a pro, track bugs and feat..."&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image:type"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"image/png"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image:width"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"1200"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image:height"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"620"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As mentioned on the W3C page, it is recommended that developers use HTTP 301 instead of this strategy. But there are some valid use cases in which you might end up using this strategy. With or without URLZap, anyone hosting websites statically should be able to have redirects without having to maintain or pay a web server. It can be hosted virtually anywhere, and all browsers support it.&lt;/p&gt;

&lt;p&gt;And well, it is always interesting to find different ways to do things we take for granted 🙃&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Getting good code reviews from peers</title>
      <dc:creator>Bruno Luiz Silva</dc:creator>
      <pubDate>Mon, 28 Sep 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/brunoluiz/getting-good-code-reviews-from-peers-26fj</link>
      <guid>https://dev.to/brunoluiz/getting-good-code-reviews-from-peers-26fj</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yuMn_-k8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2020/sep/getting-good-code-reviews/cover.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yuMn_-k8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2020/sep/getting-good-code-reviews/cover.jpg" alt="Photo by Glenn Carstens-Peters on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every software developer, soon after pushing code to the repository, has this urge to ping the team to ask for code review. But, I dare to say: don’t do it! Most likely some adjusments and checks can still be done, especially if this is your first push for this feature.&lt;/p&gt;

&lt;p&gt;The following guidelines might help you to get better and faster code reviews.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Disclaimer: I am using some Github terminology (Pull Request, Draft PR), but it should apply to other repository hosting services.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Be your first reviewer and tester
&lt;/h1&gt;

&lt;p&gt;As mentioned, many might be eager to ask for reviews straight away. But what if your first reviewer was you? Check the code for usual issues, such as unnecessary comments, intricated logic or even some test script you wrote and committed by accident (who never?).&lt;/p&gt;

&lt;p&gt;Check your tests and run the test suite, if the team has one (if it doesn’t, perhaps it is time to add one). Or even try it with a few manual tests. It will guarantee the feature doesn’t contain a breaking change or any other funny behaviour.&lt;/p&gt;

&lt;p&gt;It will clear the way for teammates to focus on what matters for the feature.&lt;/p&gt;

&lt;h1&gt;
  
  
  Create small Pull Requests
&lt;/h1&gt;

&lt;p&gt;Sometimes we might end-up including too much code in one Pull Request. Splitting it into small ones will make reviewers lives easier.&lt;/p&gt;

&lt;p&gt;It will narrow down the scope, and it might raise some interesting discussions before going ahead with more implementations. Besides, smaller amounts of code are faster to review and understand 🙂.&lt;/p&gt;

&lt;p&gt;Examples of splittable code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updates on schemas or any type model, as the team might want to discuss it before going ahead&lt;/li&gt;
&lt;li&gt;Tooling updates (scripts or shared libs/SDK), as it might be of interest of other people outside the team&lt;/li&gt;
&lt;li&gt;If there is a story ticket with sub-tasks, use the sub-tasks as a guide for opening pull requests&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Use comments to open discussions
&lt;/h1&gt;

&lt;p&gt;Most repository hosting services have tools to allow developers to comment in pull requests. As you review your code, these are some points you might want to discuss:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Discuss if an implementation is the best approach to the problem or if it is consistent with similar features&lt;/li&gt;
&lt;li&gt;Discuss if &lt;a href="https://en.wikipedia.org/wiki/Programming_idiom"&gt;the code is idiomatic&lt;/a&gt; for the language or framework&lt;/li&gt;
&lt;li&gt;Point-out to possible breaking changes or disruptive codes (example: possible data loss)&lt;/li&gt;
&lt;li&gt;Point out relevant bits of the code, where much of the logic happens&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ruOwR1_H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2020/sep/getting-good-code-reviews/idiomatic-screenshot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ruOwR1_H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2020/sep/getting-good-code-reviews/idiomatic-screenshot.png" alt="Is this idiomatic code?"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Drafts might help in big teams
&lt;/h1&gt;

&lt;p&gt;Sometimes, people get stuck in some part, and that is where asking your mates might be a good call. Push, open a pull request, label as “WIP” and send it to some people… right?&lt;/p&gt;

&lt;p&gt;The problem with this approach is that, in big teams, many code owners might be associated with this project. Usually, members are automatically notified on pull requests, and some people might not like the noise (e-mails, Github bots and so on).&lt;/p&gt;

&lt;p&gt;Most services have the concept of “draft pull request” (&lt;a href="https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request"&gt;Github&lt;/a&gt;, &lt;a href="https://docs.gitlab.com/ee/user/project/merge_requests/work_in_progress_merge_requests.html"&gt;Gitlab&lt;/a&gt;), which do not automatically request reviews from the code owners. For work in progress pull requests, this is quite helpful and highly recommended.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uAZDy6-h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2020/sep/getting-good-code-reviews/draft-screenshot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uAZDy6-h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2020/sep/getting-good-code-reviews/draft-screenshot.png" alt="Is this idiomatic code?"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once it is ready for review, you can convert from draft to pull request and profit 😉.&lt;/p&gt;

&lt;h1&gt;
  
  
  Descriptions always help
&lt;/h1&gt;

&lt;p&gt;The team might exactly know what to expect for this feature, and there might be even a ticket with more details. But humans tend to forget details, and a clear description of what is supposed to do might be helpful.&lt;/p&gt;

&lt;p&gt;If there is a ticket, replicating some bits in the description might be helpful as well. Someone might need to come back to it after months, or even other teams might want to peek into it. Most likely, just a few will remember details and this description could be of huge help in these moments.&lt;/p&gt;

&lt;h1&gt;
  
  
  Continuous integration: automation, automation, automation…
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lPUvsa-Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2020/sep/getting-good-code-reviews/circleci-screenshot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lPUvsa-Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2020/sep/getting-good-code-reviews/circleci-screenshot.png" alt="Release automation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Humans make mistakes. Who never pushed code with inconsistent formatting, logging calls, skipping some tests and so on? Reviewing these mistakes is a bit annoying (although doable), mostly because usually they could be 100% avoided.&lt;/p&gt;

&lt;p&gt;With tools such as &lt;a href="https://circleci.com/"&gt;CircleCI&lt;/a&gt; or &lt;a href="https://github.com/features/actions"&gt;Github Actions&lt;/a&gt;, a team can automate these tasks and mark the feature as “mergeable” only if all of those passed. It is what is called &lt;a href="https://martinfowler.com/articles/continuousIntegration.html"&gt;continuous integration&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Things that could be easily automated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tests: if the project has them (it should), the commands to run them should be easy to include in the automation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Lint_(software)"&gt;Linting&lt;/a&gt;: checks if the code follows code guidelines decided by the team, enabling to catch bugs and other programming errors. Most languages have linting tools, with many available configurations (examples: ESLint, golangci-lint)&lt;/li&gt;
&lt;li&gt;Building: from binaries to docker images, why not add this process to your automation pipeline?&lt;/li&gt;
&lt;li&gt;Deploying: depending on the team workflow, it might be even possible to deploy these straight to staging or production (continuous delivery)&lt;/li&gt;
&lt;li&gt;Publishing: if the project is some tool, it can publish in the specific platform (screenshot example)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are just examples. Your team might have different requirements and tasks, which could be configured into your continuous integration.&lt;/p&gt;

&lt;h1&gt;
  
  
  Don’t be “the rockstar” coder
&lt;/h1&gt;

&lt;p&gt;Besides all the above, be honest and genuine when asking questions, discussing topics or bringing new things (tooling, models, ways of code). Consider that people will spend some time to check your progress, and give feedback and recommendations. They are doing this genuinely, and so should you.&lt;/p&gt;

&lt;p&gt;Don’t be “that guy”, the one who knows everything and whos opinion is the only that matters.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I hope these steps are small enough to be easily integrated into your workflow. At some point, you might be able to convince other team members to use some of these as well. Integrate it in steps, to make it smoother to everyone 😉.&lt;/p&gt;

</description>
      <category>git</category>
      <category>workflow</category>
      <category>team</category>
      <category>coding</category>
    </item>
    <item>
      <title>A Tale Of How To Not Deploy Two Months Old Features</title>
      <dc:creator>Bruno Luiz Silva</dc:creator>
      <pubDate>Wed, 07 Mar 2018 00:00:00 +0000</pubDate>
      <link>https://dev.to/brunoluiz/a-tale-of-how-to-not-deploy-two-months-old-features-520d</link>
      <guid>https://dev.to/brunoluiz/a-tale-of-how-to-not-deploy-two-months-old-features-520d</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PSXwbhDd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2018/mar/a-tale-of-how-to-not-deploy-two-months-old-features/cover.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PSXwbhDd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2018/mar/a-tale-of-how-to-not-deploy-two-months-old-features/cover.jpg" alt="Photo by rawpixel.com on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is one big and very special date on the e-commerce and retail market and it’s called Black Friday. For many, it means “discount prices”, “sale!", “50% off”, but for developers and IT people it is a challenging adventure.&lt;/p&gt;

&lt;p&gt;To begin with, two weeks before, feature deployments are frozen and everything passes through load tests. On the week, machines are scaled up and, at the event’s day, all eyes are on metrics and logs.&lt;/p&gt;

&lt;p&gt;But there is a catch in this whole story: the feature development can’t stop. This means features will begin to stack up soon after the feature deployment freeze and usually it continues a bit after the event, especially when your software is multi-tenant and each client has its own Black Friday agenda.&lt;/p&gt;

&lt;p&gt;In the case which gave this article its title, the deploy was delayed until close Christmas and, as it was Christmas, the team preferred to not deploy until the next year.&lt;/p&gt;

&lt;p&gt;January came by and, at some point, the delayed deploys would have to start. As four sprints have been passed since Black Friday, the usual process would be to deploy each sprint package atomically, monitoring its results in the production environment. But this, this is not an ideal world.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fMTC1KNc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2018/mar/a-tale-of-how-to-not-deploy-two-months-old-features/surprises.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fMTC1KNc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2018/mar/a-tale-of-how-to-not-deploy-two-months-old-features/surprises.jpeg" alt="Photo by rawpixel.com on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Product Development Life Is Full Of Surprises
&lt;/h2&gt;

&lt;p&gt;When a product is just in its early days, the first clients are tech early adopters and the development team have to be close to them, as their inputs are valuable.&lt;/p&gt;

&lt;p&gt;At some day in January, one of the major platform’s clients informed they would launch more shops on the system. Besides the fact that, usually, some preparation is required, the biggest issue was that a specific feature was required. It had been developed at some point, but it was not well tested yet.&lt;/p&gt;

&lt;p&gt;Even worse, this feature depended on others, implemented in late November and early December, which means “Goodbye atomic deploys”: the team will have to prepare a deploy package with all four sprint features. Dangerous, isn’t it? Remember the &lt;em&gt;challenging adventure&lt;/em&gt; part?&lt;/p&gt;

&lt;p&gt;While finishing and polishing the required feature, the QA team had to work deliberately to test all features again to be sure that everything would be pretty smooth. Even those which were already tested as, since November, some hotfixes were made on the production environment and who knows if they could have affected one of the already tested features.&lt;/p&gt;

&lt;p&gt;With the feature finished, the QA and management teams got together to test it. After a period of tests, they confirmed it was working as expected, with no bugs or business rules flaws. Even though this surprise feature made us work insanely, the deploy looked like it would be a walk in the park.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VRZ0ZOOo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2018/mar/a-tale-of-how-to-not-deploy-two-months-old-features/deploy.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VRZ0ZOOo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2018/mar/a-tale-of-how-to-not-deploy-two-months-old-features/deploy.jpeg" alt="Photo by SpaceX on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  D(eploy)-Day
&lt;/h2&gt;

&lt;p&gt;It was 2 am when the whole deploy started. Low traffic and not that many orders flooding the system made it the perfect time to deploy the application. While deploying it, everything seemed fine, even though minor adjustments and migrations were needed. As soon as the clock hit 3h30 am, the team members were already wishing “Good Night” to each other.&lt;/p&gt;

&lt;p&gt;For a package with a lot of features and one quite critical, it was quite smooth… and this is when things started to fall apart. At 4 pm, one of the clients started to complain about some orders not being registered due to HTTP 400 errors and some inventory not being updated for no reason. _“WHAT THE F_CK IS GOING ON!” *everybody said, in despair.&lt;/p&gt;

&lt;p&gt;All developers stopped to investigate the problem and, of course, hidden in the middle of one of the sprint release packages, there were two bugs: one related to how the application dealt with the inventory queue producer and the other related to how addresses were validated. Ten lines of code worth of trouble.&lt;/p&gt;

&lt;p&gt;After roughly one hour of stress, everything was calm again, but the results of this deploy changed the entire team.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bUnZyOb7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2018/mar/a-tale-of-how-to-not-deploy-two-months-old-features/postmortem.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bUnZyOb7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2018/mar/a-tale-of-how-to-not-deploy-two-months-old-features/postmortem.jpeg" alt="Photo by Dustin Lee on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  THAT Post-Mortem And Its Results
&lt;/h2&gt;

&lt;p&gt;Soon after, a post-mortem had been written. Everybody collaborated: developers, managers, and QAs. The information contained in this single document would allow the team to learn, grow and know better how to deal with problems like this in the future.&lt;/p&gt;

&lt;p&gt;At the other day, a morning meeting was scheduled to discuss the points written in the post-mortem. Besides the issues from the deploy itself, many other problems arose in the heat of the discussion. All members agreed on the pointed issues and suggested some actions to tackle them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy age
&lt;/h3&gt;

&lt;p&gt;One could point to the code and say it was a bug, but it was not only that. Deploys that are too many weeks old are a problem, as it has features developed way too long ago, where devs and testers probably don’t remember all specifics for these. This can lead to database issues (if a migration was forgotten), schema validation problems, business rules flaws, and so on.&lt;/p&gt;

&lt;p&gt;The best way to tackle this is to deploy the feature package not too long after the sprint has been finished. Everything will be fresh for all team members and no git gimmicks will be required for this (rebase hell mostly).&lt;/p&gt;

&lt;h3&gt;
  
  
  Rushed deploys
&lt;/h3&gt;

&lt;p&gt;Never do rush deploys, especially big ones. The team will get stressed, communication probably will not be the best, documents (such as the release notes) can have errors or miss information. In this deploy, one of the features was not specified on the JIRA Release Board, but it was on the GitHub release. A developer with more time would have noticed that some stuff was missing.&lt;/p&gt;

&lt;p&gt;These release notes usually will not only be used by the clients, but by the QAs as well, as it will have which features will be deployed. As these have impacts on everybody, the best thing to do is to have a consensus on what can be fully delivered (developer side) and well tested (QA side). The idea is to avoid features which can have bugs or not well tested because they were made in a rush.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Processes
&lt;/h3&gt;

&lt;p&gt;Usually, people love to complain about “processes”. Some people even say they love startups because of the lack of them. But they exist for a reason and, in this case, it would have helped if everything followed a well-defined process.&lt;/p&gt;

&lt;p&gt;There was already a process, but it was not that specific. After the incident, the team got together and wrote a document describing each step of the product feature development, with a pipe of what should be done on each step of it: feature discussions and development, peer reviews metrics, deploy and release notes for tests environments, test processes and finally, the production deploy.&lt;/p&gt;

&lt;p&gt;Is it more bureaucratic? For sure! But until now, there were no complains by the team members and, especially, the client.&lt;/p&gt;

&lt;h3&gt;
  
  
  More Automated Tests
&lt;/h3&gt;

&lt;p&gt;Each sprint feature package is tested by QAs in a staging environment. The best scenario is to have a lot of different automated test scenarios, which would give 100% guarantee that nothing will break the APIs.&lt;/p&gt;

&lt;p&gt;But, this isn’t a perfect world. The usual is to have part of it automated and part of it is tested by humans. But, as this aging deploy was urgent and made in a rush, some features passed through without being well tested.&lt;/p&gt;

&lt;p&gt;How to solve this problem? Well, one side of the problem is organization: a board tool would help with this but, as aging deploys such as this one have too many tasks, the best thing to do is organize THAT release note. The QA team will be able then to plan how to do its tests.&lt;/p&gt;

&lt;p&gt;The other side, which is a bit more complicated, is to create more automated tests. Not only QAs but developers as well. Everybody knows someone who wants to skip the test development, but this can help to avoid countless problems (especially in the future). The other developers should not allow a feature to go on without automated tests for it. The same applies for QAs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error Metrics, Monitoring and Alerts
&lt;/h3&gt;

&lt;p&gt;Soon after the deploy, the team has checked some error metrics on &lt;a href="https://www.graylog.org"&gt;Graylog&lt;/a&gt; and &lt;a href="https://aws.amazon.com/cloudwatch/"&gt;CloudWatch&lt;/a&gt;, but these error metrics were just for a part of the system, not its whole. If more metrics had been monitored, probably the problem would have been discovered way before and the impact would have been smaller.&lt;/p&gt;

&lt;p&gt;The team should monitor at least some of these metrics manually, through dashboards or even the application log, but the best way to tackle this is through automated alerts. Nowadays, all major IaaS providers have a service for metrics and logs. With CloudWatch (AWS), the team can set alerts for when too many error HTTP responses are given by the applications on a certain determined period. It can send e-mails, SMS and even be integrated with mobile apps such as &lt;a href="https://www.opsgenie.com/"&gt;OpsGenie&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are other tools besides these, such as &lt;a href="https://newrelic.com/"&gt;NewRelic&lt;/a&gt; and &lt;a href="https://www.librato.com/"&gt;Librato&lt;/a&gt;, but they are a bit more specific and the team should analyze if they are really required.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rHXD4t1c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2018/mar/a-tale-of-how-to-not-deploy-two-months-old-features/noproblems.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rHXD4t1c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://brunoluiz.net/blog/2018/mar/a-tale-of-how-to-not-deploy-two-months-old-features/noproblems.jpeg" alt="Photo by Kupono Kuwamura on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  End Of Problems?
&lt;/h2&gt;

&lt;p&gt;This will not be the last problem the team will have to struggle with. Stressful moments like these will appear but this is when the team will learn and grow, being able to rise and aim towards high stakes through time.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
