<?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: Michael Friedrich</title>
    <description>The latest articles on DEV Community by Michael Friedrich (@dnsmichi).</description>
    <link>https://dev.to/dnsmichi</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%2F95962%2F4889fa5d-d01d-4e79-af52-69df1c5bf4fe.png</url>
      <title>DEV Community: Michael Friedrich</title>
      <link>https://dev.to/dnsmichi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dnsmichi"/>
    <language>en</language>
    <item>
      <title>Efficient DevSecOps Pipelines in a Cloud Native World - free workshop</title>
      <dc:creator>Michael Friedrich</dc:creator>
      <pubDate>Fri, 10 Dec 2021 16:37:58 +0000</pubDate>
      <link>https://dev.to/dnsmichi/efficient-devsecops-pipelines-in-a-cloud-native-world-free-workshop-hmk</link>
      <guid>https://dev.to/dnsmichi/efficient-devsecops-pipelines-in-a-cloud-native-world-free-workshop-hmk</guid>
      <description>&lt;p&gt;Getting started with CI/CD has become more easy with the &lt;a href="https://about.gitlab.com/blog/2021/08/03/welcome-to-the-devops-platform-era/"&gt;DevOps platform era&lt;/a&gt;. GitLab provides a new pipeline editor to help with onboarding, and allow to prevent common configuration mistakes.&lt;/p&gt;

&lt;p&gt;Pipelines and their definitions are always changing, and a work in progress similar to source code development. It is easy to create a long lasting pipeline which blocks reviews from fast feedback, or waste ten thousands of dollars of cloud compute resources.&lt;/p&gt;

&lt;p&gt;The overall question is - how to create efficient DevSecOps pipelines, and make use of all available options: Configuration, resources, CI/CD infrastructure, Security and Observability. &lt;/p&gt;

&lt;p&gt;Based on the talk I had created after creating the CI/CD Pipeline Efficiency docs after a CI monitoring webinar ... &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.google.com/presentation/d/1nq7Q4WMv6rQc6WFJCRqjtgtgQfgtKTtwSFw4IXXuRsA/edit"&gt;Continuous LifeCycle 2021: Efficient DevSecOps Pipelines in a Cloud Native World&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.google.com/presentation/d/1NwKIJ-PG9xfV7CVGJC3N1Cn7KhPaFTwMhVBi98WAMDI/edit"&gt;AWS UG Nuremberg: Efficient DevSecOps Pipelines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=p2B0COC1u64"&gt;cdCon: Dev loves CI/CD: Efficient Sec and Ops Pipelines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.google.com/presentation/d/1jZYHIXjL6CDBQVblDvxUvBFl8Gbz4LTx5yCx-iwRsqg/edit"&gt;Tweakers Dev Summit: Devs love CI/CD: Efficient DevSecOps Pipelines&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.google.com/presentation/d/1EiBoaTOFx-bE2HkNT2v1ucXbAnwedc9v26ElLk9_fks/edit"&gt;2. German Connect Day: Efficient Sec and Ops Pipelines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.google.com/presentation/d/1emmdaQmqunV8fIlfLMB2gk6JHtVljKQ4slUaLBMrPIQ/edit"&gt;IT-Tage 365: Devs ❤️ CI/CD: Efficient Sec and Ops Pipelines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=QA2KeufcPdQ"&gt;Open Source Automation Days: Developers love CI/CD: The Sec and Ops Sequel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.google.com/presentation/d/1ONwIIzRB7GWX-WOSziIIv8fz1ngqv77HO1yVfRooOHM/edit"&gt;Webinar: Identify, analyze, action! Deep monitoring with CI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;... I have now built a 10+ hours workshop for Open Source Automation Days 2021 with old and new best practices for everyone to learn and benefit. I've added new topics focussing on auto-scaling and cloud native deployments, whilst enriching the configuration examples with many hidden gems. &lt;/p&gt;

&lt;p&gt;Yesterday, a discussion about a great blog post &lt;a href="https://blog.nimbleways.com/let-s-make-faster-gitlab-ci-cd-pipelines/"&gt;"Let's make faster GitLab CI/CD pipelines"&lt;/a&gt; on &lt;a href="https://news.ycombinator.com/item?id=29502999"&gt;Hacker News&lt;/a&gt; inspired me to share the workshop and now blog about it.  You can find all workshops in the &lt;a href="https://about.gitlab.com/handbook/marketing/community-relations/developer-evangelism/projects/#workshops"&gt;GitLab Developer Evangelism handbook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can learn async at your own pace, with the &lt;a href="https://docs.google.com/presentation/d/12ifd_w7G492FHRaS9CXAXOGky20pEQuV-Qox8V4Rq8s/edit"&gt;slides&lt;/a&gt; providing the exercises and the solutions in a &lt;a href="https://gitlab.com/gitlab-de/workshops/ci-cd-pipeline-efficiency-workshop"&gt;workshop project&lt;/a&gt;. Note that there is one exercise which needs preparations for auto-scaling which is described in the slides. &lt;/p&gt;

&lt;p&gt;The following topics will be practiced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduction: CI/CD meets Dev, Sec and Ops&lt;/li&gt;
&lt;li&gt;CI/CD: Terminology and first steps

&lt;ul&gt;
&lt;li&gt;Pipeline Editor &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Analyse &amp;amp; Identify

&lt;ul&gt;
&lt;li&gt;Learn using the &lt;a href="https://github.com/mvisonneau/gitlab-ci-pipelines-exporter/tree/main/examples/quickstart"&gt;GitLab CI Pipeline Exporter&lt;/a&gt; to monitor the exercise project throughout the workshop.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Efficiency actions

&lt;ul&gt;
&lt;li&gt;Config Efficiency: CI/CD Variables in variables, job templates (YAML anchors, extends), includes (local, remote), rules and conditions (if, dynamic variables, conditional includes), &lt;code&gt;!reference&lt;/code&gt; tags (script, rules), maintain own CI/CD templates (include templates, override config values), parent-child pipelines, multi project pipelines, better error messages to fix failures fast &lt;/li&gt;
&lt;li&gt;Resource Use Efficiency: Identification, max pipeline duration analysis, fail fast with stages grouping, fail fast with async needs, analyse blocking stages pipeline (solution with needs), matrix builds for parallel execution (pratice: combine matrix and &lt;code&gt;extends&lt;/code&gt;, combine matrix and &lt;code&gt;!reference&lt;/code&gt;), &lt;code&gt;extends&lt;/code&gt; merge strategies (with and without &lt;code&gt;!reference&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;CI/CD Infrastructure Efficiency: Optimization ideas, custom build images, optimize builds with C++ as example, GitLab runner resource analysis (sharing, tags, external dependencies, Kubernetes), local runner exercise, resource groups, storage usage analysis, caching (Python dependency exercise, including &lt;code&gt;when:always&lt;/code&gt; on failed jobs) &lt;/li&gt;
&lt;li&gt;Auto-scaling: Overview, AWS auto-scaling with GitLab Runner with Terraform, insights into &lt;a href="https://about.gitlab.com/blog/2021/08/17/100-runners-in-less-than-10mins-and-less-than-10-clicks/"&gt;Spot Runners on AWS Graviton&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Group discussion

&lt;ul&gt;
&lt;li&gt;Deployment Strategies: IaC, GitOps, Terraform, Kubernetes, registries&lt;/li&gt;
&lt;li&gt;Security: Secrets in CI/CD variables, Hashicorp Vault, secrets scanning, vulnerability scanning&lt;/li&gt;
&lt;li&gt;Observability: CI/CD Runner monitoring, SLOs, quality gates, CI/CD Tracing&lt;/li&gt;
&lt;li&gt;More efficiency ideas: Auto DevOps, Fast vs Resources, Conclusion and tips&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Take your time with learning, the workshop has a lot of topics inside. Let me know how it goes, and join &lt;a href="https://forum.gitlab.com/"&gt;https://forum.gitlab.com/&lt;/a&gt; for questions and feedback (please tag &lt;a class="mentioned-user" href="https://dev.to/dnsmichi"&gt;@dnsmichi&lt;/a&gt;
). 🤗 &lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.google.com/presentation/d/12ifd_w7G492FHRaS9CXAXOGky20pEQuV-Qox8V4Rq8s/edit"&gt;Start exploring now&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everyone Can Contribute - learned a new gem from this workshop? Blog about it and share on social tagging &lt;a href="https://twitter.com/dnsmichi"&gt;@dnsmichi&lt;/a&gt; &lt;a href="https://twitter.com/gitlab"&gt;@gitlab&lt;/a&gt;! 💡 &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Blog originally published on &lt;a href="https://dnsmichi.at/2021/12/10/efficient-devsecops-pipelines-in-a-cloud-native-world-free-workshop/"&gt;https://dnsmichi.at/2021/12/10/efficient-devsecops-pipelines-in-a-cloud-native-world-free-workshop/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>gitlab</category>
      <category>devsecops</category>
      <category>workshop</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Use Homebrew Bundle to manage software installation on macOS </title>
      <dc:creator>Michael Friedrich</dc:creator>
      <pubDate>Mon, 30 Nov 2020 15:37:55 +0000</pubDate>
      <link>https://dev.to/dnsmichi/use-homebrew-bundle-to-manage-software-installation-on-macos-1223</link>
      <guid>https://dev.to/dnsmichi/use-homebrew-bundle-to-manage-software-installation-on-macos-1223</guid>
      <description>&lt;p&gt;Automation is iteration. First you'll find a way to make it work, and share your learnings - feedback and best practices help make it even better. When I first published my &lt;a href="https://about.gitlab.com/blog/2020/04/17/dotfiles-document-and-automate-your-macbook-setup/"&gt;dotfiles - Document and automate your Macbook setup&lt;/a&gt; blog post, Nate &lt;a href="https://gitlab.com/dnsmichi/dotfiles/-/issues/2"&gt;suggested to use&lt;/a&gt; Homebrew bundle for a more clean management approach. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Homebrew/homebrew-bundle"&gt;Homebrew bundle&lt;/a&gt; follows the same idea as known from Ruby bundle, has a &lt;code&gt;Brewfile&lt;/code&gt; and specific keywords for packages to install.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Steps with Homebrew Bundle
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;tap: Add more brew third-party repos &lt;/li&gt;
&lt;li&gt;cask: Install application casks (Gimp, etc.)&lt;/li&gt;
&lt;li&gt;brew: Install packages&lt;/li&gt;
&lt;li&gt;mas: Install App store items (requires &lt;code&gt;brew install mas&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also override the default cask installation path:&lt;br&gt;
&lt;/p&gt;

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

cask_args appdir: "/Applications"

tap "homebrew/cask"

cask "gimp"

brew "git"

mas "Slack", id: 803453959
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it to see how it works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ brew bundle
Using homebrew/cask
Using gimp
Using git
Using Slack
Homebrew Bundle complete! 4 Brewfile dependencies now installed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;git&lt;/code&gt; from Homebrew is newer than the macOS Git binary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git --version
git version 2.29.2

$ /usr/bin/git --version
git version 2.24.3 (Apple Git-128)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Homebrew's Git is installed into &lt;code&gt;/usr/local/bin&lt;/code&gt; which has a priority in the &lt;code&gt;PATH&lt;/code&gt; environment variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ which git
/usr/local/bin/git

$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Existing Homebrew Setup? No Problem
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;bundle&lt;/code&gt; provides the &lt;code&gt;dump&lt;/code&gt; sub command which writes a new &lt;code&gt;Brewfile&lt;/code&gt; with your current setup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew bundle dump
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Homebrew automatically installs the &lt;code&gt;bundle&lt;/code&gt; tap the first time the command is invoked, no extra preparations needed. &lt;/p&gt;

&lt;p&gt;You can either use this file to continue working, or start fresh in your own &lt;code&gt;Brewfile&lt;/code&gt;. You can also manually install software first and then analyse how a dump looks like. &lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats with GNU tools (sed, tar, ...)
&lt;/h2&gt;

&lt;p&gt;You can install GNU tools to avoid different parameters and behaviour with the native UNIX representation of sed, tar, etc. Homebrew provides binaries prefixed with the &lt;code&gt;g&lt;/code&gt; character, so even an updated PATH variable won't help, requiring you to call &lt;code&gt;gsed&lt;/code&gt; instead of &lt;code&gt;sed&lt;/code&gt;. To keep compatibility with existing Linux scripts, I used symlinks created inside a &lt;a href="https://gitlab.com/dnsmichi/dotfiles/-/blob/v1.0.0/brew.sh"&gt;brew setup script&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BREW_PREFIX=$(brew --prefix)
ln -s "${BREW_PREFIX}/bin/gsed" "${BREW_PREFIX}/bin/sed"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't possible inside a Brewfile. Luckily this can be automated in your PATH, as the Homebrew formulas provide these symlink overrides on their own:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ brew info gnu-sed

GNU "sed" has been installed as "gsed".
If you need to use it as "sed", you can add a "gnubin" directory
to your PATH from your bashrc like:

    PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"

$ ls -la /usr/local/opt/gnu-sed/libexec/gnubin
total 0
drwxr-xr-x  3 mfriedrich  staff   96 Jan 15  2020 .
drwxr-xr-x  5 mfriedrich  staff  160 Jan 15  2020 ..
lrwxr-xr-x  1 mfriedrich  staff   14 Jan 15  2020 sed -&amp;gt; ../../bin/gsed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Collect the inventory from all GNU tools and render an update for your environment file. You can automate this task with &lt;a href="https://gist.github.com/skyzyx/3438280b18e4f7c490db8a2a2ca0b9da#gistcomment-3049694"&gt;this inventory snippet&lt;/a&gt; added to &lt;a href="https://gitlab.com/dnsmichi/dotfiles/-/blob/v2.0.0/.oh-my-zsh/custom/path.zsh"&gt;.oh-my-zsh/custom/path.zsh&lt;/a&gt; or &lt;code&gt;.zshrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# GNU utils path overrides as default CLI tools
if type brew &amp;amp;&amp;gt;/dev/null; then
  HOMEBREW_PREFIX=$(brew --prefix)
  for d in ${HOMEBREW_PREFIX}/opt/*/libexec/gnubin; do export PATH=$d:$PATH; done
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you prefer to use symlinks, you can do so too instead of the export. Keep in mind that the PATH environment is generated on each new terminal, while symlinks can run stale. &lt;/p&gt;

&lt;h2&gt;
  
  
  A complete example
&lt;/h2&gt;

&lt;p&gt;Follow the iteration in &lt;a href="https://gitlab.com/dnsmichi/dotfiles/-/merge_requests/2/diffs"&gt;this merge request&lt;/a&gt; and open the &lt;a href="https://gitlab.com/dnsmichi/dotfiles"&gt;dotfiles repository&lt;/a&gt; to learn more.&lt;/p&gt;

&lt;p&gt;My Brewfile focusses on my work as &lt;a href="https://about.gitlab.com/handbook/marketing/community-relations/developer-evangelism/"&gt;Developer Evangelist at GitLab&lt;/a&gt; with a local Linux-ified CLI environment and Docker. Heavier workloads are shifted into cloud environments. Image manipulation tools help with automating tasks for blog posts and workshops. &lt;/p&gt;

&lt;p&gt;I'm also not pinning specific versions for packages, this is not supported by Homebrew bundle either.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cask_args appdir: "/Applications"

# Tap Homebrew
tap "homebrew/bundle"
tap "homebrew/cask"
tap "homebrew/cask-fonts"
tap "homebrew/cask-versions"
tap "homebrew/core"
tap "homebrew/services"

cask "java"
cask "visual-studio-code"
cask "firefox"
cask "vlc"
cask "wireshark"
cask "gimp"
cask "inkscape"
cask "jitsi-meet"
cask "handbrake"
cask "vagrant"
cask "spotify"

# System
brew "mas"
brew "curl"
brew "wget"
brew "git"
brew "vim"
brew "openssl"
brew "coreutils"
brew "moreutils"
brew "findutils"
brew "binutils"
brew "rename"
brew "gnu-sed"
brew "gnu-tar"
brew "gawk"
brew "gnutls"
brew "gnu-indent"
brew "gnu-getopt"
brew "tree"
brew "htop"
brew "pidof"
brew "pstree"
brew "grep"
brew "openssh"
brew "rsync"
brew "ssh-copy-id"
brew "screen"
brew "gmp"
brew "nmap"
brew "socat"
brew "rlwrap"
brew "dnstracer"

# Images, Audio, Video
brew "imagemagick"
brew "gifsicle"
brew "gifify"
brew "ffmpeg"

# Archive &amp;amp; Git
brew "xz"
brew "p7zip"
brew "git"
brew "git-lfs"
brew "tig"
brew "hub"

# Extract rpm file content with rpm2cpio *.rpm | cpio -ivd
brew "rpm2cpio"

# JSON
brew "jq"
brew "jo"

# Dev
brew "ruby"
brew "yarn"
brew "rbenv"
brew "python"
brew "go"
brew "cmake"
brew "openjdk"
brew "kind"

# GitLab Pages
brew "hugo"

# App Store
mas "1Password 7", id: 1333542190
mas "Slack", id: 803453959
mas "Telegram", id: 747648890
mas "uBlock", id: 1385985095
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>macos</category>
      <category>homebrew</category>
      <category>bundle</category>
      <category>packages</category>
    </item>
    <item>
      <title>GitLab CI/CD pipelines and container registry for ARM Cortex firmware builds </title>
      <dc:creator>Michael Friedrich</dc:creator>
      <pubDate>Thu, 21 May 2020 19:36:16 +0000</pubDate>
      <link>https://dev.to/dnsmichi/gitlab-ci-cd-pipelines-and-container-registry-for-arm-cortex-firmware-builds-4n4n</link>
      <guid>https://dev.to/dnsmichi/gitlab-ci-cd-pipelines-and-container-registry-for-arm-cortex-firmware-builds-4n4n</guid>
      <description>&lt;p&gt;You'll learn best about a specific tool or program by helping users with their problems and questions. I have experienced this when starting with Nagios/Icinga more than 10 years ago. Today I am trying to help the GitLab community and learn myself a lot. Often I just have an idea but never tackled the code or environment myself.&lt;/p&gt;

&lt;p&gt;Today I have found a question on the GitLab forums on the &lt;a href="https://forum.gitlab.com/t/gitlab-ci-first-try-2-issues/37787"&gt;first steps with CI/CD&lt;/a&gt;. It actually involved building &lt;a href="https://gitlab.com/spectrum70/zion-firmware"&gt;source code&lt;/a&gt; for an ARM Cortex hardware architecture:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;to build a small cortex-m4 firmware&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The question was about a specific build step and &lt;code&gt;make&lt;/code&gt; not being found. Also, whether the Docker-in-Docker image build really is the correct way of doing it.&lt;/p&gt;

&lt;p&gt;Never did that before for ARM Cortex builds. The question also included a link to the project repository and its &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; with all the details there. It also showed the build error right in front of me.&lt;/p&gt;

&lt;p&gt;Guess what I did next? Right, the power of open source and collaboration - I forked the repository into my &lt;a href="https://gitlab.com/dnsmichi"&gt;account&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Analyse the first make error
&lt;/h2&gt;

&lt;p&gt;The Docker-in-Docker approach is used to build a new image providing the cortex-m4 hardware specific build tools. Among the container build steps there was one which executed a &lt;code&gt;test.sh&lt;/code&gt; script which ran &lt;code&gt;make&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ok, then let's just see how to install &lt;code&gt;make&lt;/code&gt; into the &lt;code&gt;docker:git&lt;/code&gt; image. Wait, which OS is that?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker run -ti docker:git sh

/ # cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.11.6
PRETTY_NAME="Alpine Linux v3.11"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"

/ # apk add make

OK: 26 MiB in 26 packages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CI build runs fine now, the script does something. But does it really compile the binaries ... it is executed in the outer Alpine Docker container, not inside the newly created build image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build the image, then compile inside the image
&lt;/h2&gt;

&lt;p&gt;Then I remembered the two stages for GitLab CI/CD and the container registry: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, create a new build image with your tool chain. Push that into the container registry. &lt;/li&gt;
&lt;li&gt;Second, define a new job which uses this image to spawn a container and compile the source code from the repository &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To better visualize this, let's create two stages as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stages:
  - prepare
  - build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VsoyHwAi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/16ez21ydqgwjpbki4nqf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VsoyHwAi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/16ez21ydqgwjpbki4nqf.png" alt="CI/CD stages" width="880" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use the Web IDE for syntax highlighting and direct CI/CD feedback in the upper right corner.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To prepare this environment, define these variables: &lt;code&gt;DOCKER_DRIVER&lt;/code&gt; is read by the CI/CD Runner environment in the background, while the &lt;code&gt;IMAGE_TAG&lt;/code&gt; allows a shorter variable reference for the GitLab registry URL to the container image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variables:
  DOCKER_DRIVER: overlay2
  IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build and push the Docker image
&lt;/h3&gt;

&lt;p&gt;The next step is to define the build image. Ensure that the &lt;a href="https://gitlab.com/spectrum70/zion-firmware/-/blob/master/dockerfile"&gt;Dockerfile&lt;/a&gt; is located in the main repository.&lt;/p&gt;

&lt;p&gt;Wait, there was Docker-in-Docker? Yes, the CI/CD runners use the Docker executor, so every job on its own is run inside a container.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A container does not run any services by default.&lt;/li&gt;
&lt;li&gt;You want to build a new Docker image inside this job container.&lt;/li&gt;
&lt;li&gt;There is no Docker daemon answering &lt;code&gt;docker login&lt;/code&gt; at first.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trick here is to virtually share the runner's Docker daemon socket with the job container building the image. This happens in the background, only visible with the settings for &lt;code&gt;image: docker&lt;/code&gt; and &lt;code&gt;service: docker:dind&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Things to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The job name &lt;code&gt;prepare/image&lt;/code&gt; can be freely defined and is just an example.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;image&lt;/code&gt; is defined in the job scope and uses the DinD &lt;code&gt;docker:git&lt;/code&gt; image&lt;/li&gt;
&lt;li&gt;The job belongs to the &lt;code&gt;prepare&lt;/code&gt; stage&lt;/li&gt;
&lt;li&gt;Before any script is run, the login into the container registry is persisted once&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;docker:dind&lt;/code&gt; service must be running to communicate with the outside Docker daemon&lt;/li&gt;
&lt;li&gt;The script invokes building the Docker image and tagging it accordingly. If this steps success, it pushes the newly tagged image to authenticated container registry.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Build the docker image first
prepare/image:
  image: docker:git
  stage: prepare

  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_JOB_TOKEN" $CI_REGISTRY

  services:
  - docker:dind

  script:
    - docker build --pull -t "$IMAGE_TAG" .
    - docker push "$IMAGE_TAG"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Compile the source code
&lt;/h3&gt;

&lt;p&gt;The reason for creating the Docker image is a different architecture and specific cross compilation requirements for the ARM Cortex architecture. A similar approach is needed when building binaries for Raspberry Pis with using QEMU for example. &lt;/p&gt;

&lt;p&gt;Things to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the previously tagged &lt;code&gt;image&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Assign the job to the &lt;code&gt;build&lt;/code&gt; stage&lt;/li&gt;
&lt;li&gt;Run the compilation steps in a script provided in the same Git repository. It is located in &lt;code&gt;scripts/build.sh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The binaries need to be stored somewhere. The easiest way is to define them as artifacts and store them on the GitLab server in the job.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Build the source code based on the newly created Docker image
build/source:
  image: $IMAGE_TAG
  stage: build
  script:
    - ./scripts/build.sh 
  artifacts:
    paths:
      - "thermo/*.bin"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---4fGae-L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vrk3fldipmmpkyummser.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---4fGae-L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vrk3fldipmmpkyummser.png" alt="GitLab CI/CD job result" width="880" height="679"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I didn't achieve this in one shot, so don't fear a build to fail and another Git commit to attempt to fix it. The hardest challenge is to understand the code and scripts from someone else, and iteratively learn.&lt;/p&gt;

&lt;p&gt;Open source definitely helps as we can collaborate and work on the different challenges. You can see my attempt in &lt;a href="https://gitlab.com/spectrum70/zion-firmware/-/merge_requests/1"&gt;this merge request&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;More questions on GitLab CI/CD first steps? Hop onto the &lt;a href="https://forum.gitlab.com"&gt;forum&lt;/a&gt; and maybe we'll write another dev.to post from our findings!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>cicd</category>
      <category>gitlab</category>
      <category>development</category>
    </item>
    <item>
      <title>Emojis everywhere - supercharged with Alfred workflows</title>
      <dc:creator>Michael Friedrich</dc:creator>
      <pubDate>Fri, 24 Apr 2020 13:52:20 +0000</pubDate>
      <link>https://dev.to/dnsmichi/emojis-everywhere-supercharged-with-alfred-workflows-1o3n</link>
      <guid>https://dev.to/dnsmichi/emojis-everywhere-supercharged-with-alfred-workflows-1o3n</guid>
      <description>&lt;p&gt;I fell in love with macOS because of the gestures and workflows. &lt;a href="https://www.alfredapp.com/"&gt;Alfred&lt;/a&gt; improves this behaviour with custom workflows and many more convenient &lt;a href="https://dev.to/dnsmichi/dotfiles-document-and-automate-your-macbook-setup-3684"&gt;shortcuts for locking the screen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are various reasons to use a workflow with shortcuts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Speed &amp;amp; productivity, avoiding context switches.&lt;/li&gt;
&lt;li&gt;The editor window doesn't support emojis (outside of GitLab, GitHub, etc., typing &lt;code&gt;:heart&lt;/code&gt; has no effect).&lt;/li&gt;
&lt;li&gt;You don't want to type, search and copy on &lt;a href="https://emojipedia.org"&gt;Emojipedia&lt;/a&gt; all the time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://www.alfredapp.com/powerpack/"&gt;Alfred Powerpack&lt;/a&gt; allows you to add custom workflows. You'll need to pay for the Alfred license but the time savings are well invested imho. Keep in mind that there are &lt;a href="https://gitlab.com/dnsmichi/dotfiles#tools"&gt;more workflows&lt;/a&gt; and the possibility to create your own. &lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/jsumners/alfred-emoji/releases"&gt;emoji workflow for Alfred&lt;/a&gt; needs to be downloaded and imported into Alfred. Considering that you replaced Spotlight with Alfred, use the following shortcut and type &lt;code&gt;emoji&lt;/code&gt; to trigger the workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cmd + Space
emoji
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AFtnSnya--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/podiw9yacmqhk3iehf7i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AFtnSnya--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/podiw9yacmqhk3iehf7i.png" alt="Alfred Emoji Workflow" width="623" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then type as you go and search for the emoji. Cursor up/down for selection, and Enter to copy it to the clipboard.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CCXe00Nu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yy9zul954qg0i14zyn91.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CCXe00Nu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yy9zul954qg0i14zyn91.png" alt="Alfred Emoji Workflow Search" width="623" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you can easily insert it your text flow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Alt + Tab
Cmd + v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The more often you use the emoji workflow, the less you need to type. Mine looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cmd + space
e
&amp;lt;shows emoji, enter to autocomplete&amp;gt;
Enter
&amp;lt;heart is the first one&amp;gt;
Enter

Alt + tab
Cmd + v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's spread the emoji love everywhere! ❤️❤️❤️&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>workflows</category>
      <category>macos</category>
      <category>emoji</category>
    </item>
    <item>
      <title>dotfiles - Document and automate your Macbook setup</title>
      <dc:creator>Michael Friedrich</dc:creator>
      <pubDate>Fri, 17 Apr 2020 14:45:32 +0000</pubDate>
      <link>https://dev.to/dnsmichi/dotfiles-document-and-automate-your-macbook-setup-3684</link>
      <guid>https://dev.to/dnsmichi/dotfiles-document-and-automate-your-macbook-setup-3684</guid>
      <description>&lt;h2&gt;
  
  
  Why dotfiles
&lt;/h2&gt;

&lt;p&gt;When I first started working on Windows, Linux and macOS many years ago, there was this steep learning curve. Not everything on the system had a good default for improved productivity, often tools were missing to create your own work environment.&lt;/p&gt;

&lt;p&gt;At first glance, I started writing blog posts and shared my findings with everyone. This had the benefit that I exactly knew where these snippets can be found. Many years ago, systems were not so reliable and often a full operating system reinstall worked better than troubleshooting existing problems.&lt;/p&gt;

&lt;p&gt;After some years, many best practices had been documented in blog posts and were hard to apply in one go. Especially with working in many areas for development, professional services, ops and support, different settings and tools have been applied. At that point I had created a wiki page with text and screenshots.&lt;/p&gt;

&lt;p&gt;The wiki page allowed for many revisions, and was kept in the internal Confluence since it contained company sensitive information. I often was asked how my Linux and macOS setup looks like and if I could share best practices.&lt;/p&gt;

&lt;p&gt;Then I learned that users share their configuration and setup commands in a Git repository which is called “dotfiles”. At first glance, a dotfile is a hidden file on a Linux/Unix system, containing tool specific settings. Common tools are Git, vim, bash storing their configuration in a dotfile in the user’s home directory.&lt;br&gt;
These dotfiles were enriched with scripts to install additional software via package managers, and to apply certain runtime configuration after the work environment was setup the first time.&lt;/p&gt;
&lt;h2&gt;
  
  
  dotfiles on my Macbook
&lt;/h2&gt;

&lt;p&gt;My first steps with dotfiles started at the point where updating the Confluence wiki became troublesome. It also was the only left bastion where I could not write documentation in Markdown. Within the dotfiles Git repository, best practice always has been a &lt;code&gt;README.md&lt;/code&gt; file which describes more details and tips. Copying snippets and scripts for everyone also has become easier. Users can even fork the repository and use this as a basis for their own work environments.&lt;/p&gt;

&lt;p&gt;Navigate into my &lt;a href="https://gitlab.com/dnsmichi/dotfiles" rel="noopener noreferrer"&gt;dotfiles repository&lt;/a&gt; to learn more. The following sections highlight some of my daily best practices as a Developer Evangelist at GitLab.&lt;/p&gt;
&lt;h3&gt;
  
  
  ZSH with OhMyZSH
&lt;/h3&gt;

&lt;p&gt;macOS Catalina uses ZSH by default. Therefore I was looking into best practices and soon learned about OhMyZSH as shell framework. It comes with nice plugins which provide a native Git shell integration as well as exporting credentials as environment variables.&lt;/p&gt;

&lt;p&gt;In addition to the built-in functionality, it is easy to add custom aliases and settings. Avoid clutter inside the main &lt;code&gt;.zshrc&lt;/code&gt; file, instead extend &lt;code&gt;.oh-my-zsh/custom/aliases.zsh&lt;/code&gt; for example. The following alias allows to clean up the local git branches very easily:&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;# Delete all remote tracking Git branches where the upstream branch has been deleted&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;git_prune&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"git fetch --prune &amp;amp;&amp;amp; git branch -vv | grep 'origin/.*: gone]' | awk '{print &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;1}' | xargs git branch -d"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Git Configuration
&lt;/h3&gt;

&lt;p&gt;My Git configuration is rather simple. The reason I keep it inside the dotfiles repository is that I always forget about the Git CLI commands to set them properly. Over the years, all my preferred customizations have been applied in Git itself. The only minimalistic addons are a custom &lt;code&gt;git log&lt;/code&gt; command and the credential helper setting. I need that for storing the GitLab personal token and not being asked by &lt;code&gt;git push/pull&lt;/code&gt; all the time.&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.gitconfig

&lt;span class="o"&gt;[&lt;/span&gt;user]
    name &lt;span class="o"&gt;=&lt;/span&gt; Michael Friedrich
    email &lt;span class="o"&gt;=&lt;/span&gt; mfriedrich@gitlab.com
        signingkey &lt;span class="o"&gt;=&lt;/span&gt; D14A1F16
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
        l  &lt;span class="o"&gt;=&lt;/span&gt; log &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s1"&gt;'%Cred%h%Creset %C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&amp;lt;%an&amp;gt;%Creset'&lt;/span&gt; &lt;span class="nt"&gt;--abbrev-commit&lt;/span&gt; &lt;span class="nt"&gt;--date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;relative &lt;span class="nt"&gt;--&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;credential]
    helper &lt;span class="o"&gt;=&lt;/span&gt; osxkeychain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Git shell prompt integration is done with OhMyZSH as plugin. Previously I had done this with a customized Bash profile. I decided to go for ZSH with macOS Catalina and my new job at GitLab. &lt;/p&gt;

&lt;h3&gt;
  
  
  vim Configuration
&lt;/h3&gt;

&lt;p&gt;Even with habits changed to using VS Code/Atom or the Web IDE, I am still very fast with vim, especially with spell checking included. I've been carrying this &lt;code&gt;.vimrc&lt;/code&gt; file around for more than 10 years now and it always helped :) Here is the best of - there is more inside with syntax highlighting and restoring the cursor on re-open.&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="nb"&gt;set &lt;/span&gt;&lt;span class="nv"&gt;viminfo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'20,&amp;lt;1000,s1000,:20,%,n~/.viminfo “ Increase buffer size for search
set history=50            " keep 50 lines of command line history
set ruler                      " show the cursor position all the time
set nofixeol                 " don'&lt;/span&gt;t fix end-of-line errors
&lt;span class="s2"&gt;"set background=dark
set background=light
set showcmd              "&lt;/span&gt; Show &lt;span class="o"&gt;(&lt;/span&gt;partial&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;command &lt;/span&gt;&lt;span class="k"&gt;in &lt;/span&gt;status line.
&lt;span class="nb"&gt;set &lt;/span&gt;showmatch           &lt;span class="s2"&gt;" Show matching brackets.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install favorite software and tools
&lt;/h3&gt;

&lt;p&gt;Homebrew is my favorite package manager on macOS. It ranges from adding simple tools like “htop” to applications not available in the app store like “Gimp”.&lt;/p&gt;

&lt;p&gt;In order to keep things simple, the &lt;code&gt;brew_once.sh&lt;/code&gt; script takes care of installing Homebrew, enabling the cask system for applications and installs wget/curl to setup OhMyZsh.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./brew_once.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additional software is installed with the “&lt;code&gt;brew.sh&lt;/code&gt; script. This can be re-run any time to ensure the same state is applied. This will be useful if an application was accidentally removed. Please fork the repository and adjust everything for your likings!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./brew.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script takes care of installing the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GNU utils (sed, awk, tar, sha256sum). The macOS utils differ a bit and may break scripts made for Linux.&lt;/li&gt;
&lt;li&gt;System tools (htop, pidof, pstree, grep, screen, nmap, ssh-copy-id, tree)&lt;/li&gt;
&lt;li&gt;Images (imagemagick) for easy conversions&lt;/li&gt;
&lt;li&gt;Archive and Git (git, git-lfs, p7zip, xz, tig, hub)&lt;/li&gt;
&lt;li&gt;JSON (jq, jo)&lt;/li&gt;
&lt;li&gt;Development (Ruby, Python, Go, Redis)&lt;/li&gt;
&lt;li&gt;Applications as cask (Java, Atom, VS Code, Firefox, VLC, Gimp, Vagrant)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Enhanced Workflows with Alfred
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.alfredapp.com/" rel="noopener noreferrer"&gt;Alfred&lt;/a&gt; is not only a Spotlight replacement for opening applications or searching files. The major selling points are custom workflows accessible by quick typing. Picking HTML color codes, querying DNS records or copying emojis all over the place have become easier with quick shortcuts.&lt;/p&gt;

&lt;p&gt;Tired of locking your screen on macOS? &lt;code&gt;Cmd+Space, l, Enter&lt;/code&gt; after Alfred has learned that &lt;code&gt;l&lt;/code&gt; means &lt;code&gt;lock&lt;/code&gt;. Yep, it remembers the most often typed commands.&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%2Fzdi9x3brpf6jv6s3v8kh.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%2Fzdi9x3brpf6jv6s3v8kh.png" alt="Alfred Workflow Dig GitLab.com IPv6"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Trackpad and Keyboard
&lt;/h2&gt;

&lt;p&gt;I always used to have a mouse with me for my previous notebooks, and the change to the trackpad always worried me. Move the mouse, click here and on it goes. When I got my first iPad, I got introduced to just tapping and approving. &lt;/p&gt;

&lt;p&gt;I’ve learned that this setting can be enabled on macOS too for the trackpad which is my preferred input method since then. In order to automate this setting, run the following CLI commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking &lt;span class="nt"&gt;-bool&lt;/span&gt; &lt;span class="nb"&gt;true
&lt;/span&gt;defaults &lt;span class="nt"&gt;-currentHost&lt;/span&gt; write NSGlobalDomain com.apple.mouse.tapBehavior &lt;span class="nt"&gt;-int&lt;/span&gt; 1
defaults write NSGlobalDomain com.apple.mouse.tapBehavior &lt;span class="nt"&gt;-int&lt;/span&gt; 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another thing I prefer using - the right click for accessing the actions toolbar. By default, the secondary click is available with two fingers. My improved workflow prefers the right bottom corner of the trackpad. You can either change this inside the trackpad preferences or run these CLI commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadCornerSecondaryClick &lt;span class="nt"&gt;-int&lt;/span&gt; 2
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadRightClick &lt;span class="nt"&gt;-bool&lt;/span&gt; &lt;span class="nb"&gt;true
&lt;/span&gt;defaults &lt;span class="nt"&gt;-currentHost&lt;/span&gt; write NSGlobalDomain com.apple.trackpad.trackpadCornerClickBehavior &lt;span class="nt"&gt;-int&lt;/span&gt; 1
defaults &lt;span class="nt"&gt;-currentHost&lt;/span&gt; write NSGlobalDomain com.apple.trackpad.enableSecondaryClick &lt;span class="nt"&gt;-bool&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Last but not least using &lt;code&gt;tab&lt;/code&gt; for changing the focus area in windows is a must have. This is hidden in the keyboard shortcut settings as &lt;code&gt;use keyboard navigation to move focus between controls&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;defaults write NSGlobalDomain AppleKeyboardUIMode &lt;span class="nt"&gt;-int&lt;/span&gt; 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additional ideas and commands can be found in &lt;a href="https://github.com/herrbischoff/awesome-macos-command-line" rel="noopener noreferrer"&gt;this repository&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Everything else is stored in the GitLab repository, including the documentation in Markdown format. Additional screenshots can be put there too into the &lt;code&gt;doc/images&lt;/code&gt; directory for example.&lt;br&gt;
There is no need to carry an extra wiki page around and everyone can access the repository via URL. You can also download the whole archive and work offline.&lt;/p&gt;

&lt;p&gt;The best thing about my dotfiles repository - it is open source and we can learn, share, suggest together :-)&lt;br&gt;
Do you have a cool idea for making this even more convenient? Fork the &lt;a href="https://gitlab.com/dnsmichi/dotfiles" rel="noopener noreferrer"&gt;repository&lt;/a&gt; and send a merge request please!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This blog post was originally posted on &lt;a href="https://about.gitlab.com/blog/2020/04/17/dotfiles-document-and-automate-your-macbook-setup/" rel="noopener noreferrer"&gt;about.gitlab.com/blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>dotfiles</category>
      <category>development</category>
      <category>workflows</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
