[{"content":"Today I decided to update my resume. And by update, I mean make easy to update at any point in the future in a controlled, over-engineered, repeatable way. I\u0026rsquo;ve decided that I\u0026rsquo;d like to be able to modify the LaTex source, commit and push to GitLab, kick off a build on a GitLab runner, use a Docker image to manage dependencies, then store the binary (PDF) output alongside the repo.\nLuckily, I already had a LaTeX version of my resume from a couple of months ago in GitHub. Step one is moving to GitLab. Easy as pulling, updating my SSH key, updating the remote, then pushing.\nNext step is adding a Dockerfile. I forked this LaTeX base for my resume repository a couple months ago, so I can steal and adapt the Dockerfile from that same repository.\nFROMubuntu:xenialENV DEBIAN_FRONTEND noninteractiveRUN apt-get update -q \u0026amp;\u0026amp; apt-get install -qy \\  --no-install-recommends \\  curl jq \\  texlive-full \\  python-pygments gnuplot \\  make git \\  \u0026amp;\u0026amp; rm -rf /var/lib/apt/lists/*WORKDIR/dataVOLUME [\u0026#34;/data\u0026#34;]Just a few changes to this so that I\u0026rsquo;m sure that the Ubuntu image doesn\u0026rsquo;t change from build to build,\nFROMubuntu:20.04ENV DEBIAN_FRONTEND noninteractive...In an attempt to update the dependencies based on this StackOverflow post by someone who is much better versed in the LaTeX-Ubuntu landscape than I am,\n# from https://tex.stackexchange.com/a/132305RUN apt-get --no-install-recommends install \\  texlive-{base,bibtex-extra,extra-utils,generic-recommended,fonts-recommended,font-utils,latex-base,latex-recommended,latex-extra,math-extra,pictures,pstricks,science} \\  perl-tk purifyeps chktex latexmk dvipng xindy dvidvi fragmaster lacheck latexdiff libfile-which-perl dot2tex tipa latex-xcolor latex-beamer prosper pgfI found that simpler is generally better,\nRUN apt-get update -qyRUN apt-get --no-install-recommends install -qy \\  texlive \\  texlive-latex-extraAnd finally, adding multi-stage builds made this much quicker to test changes to the LaTeX document,\nFROMubuntu:20.04 AS texlive_baseENV DEBIAN_FRONTEND noninteractiveRUN apt-get update -qyRUN apt-get --no-install-recommends install -qy \\  texlive \\  texlive-latex-extraFROMtexlive_baseWORKDIR/dataVOLUME [ \u0026#34;/data\u0026#34; ]After testing the build on this Ubuntu image, it\u0026rsquo;s time to set up CI/CD on a GitLab Runner.\n# use `dind` or docker-in-docker for building the image default: image: docker:19.03.12 services: - docker:19.03.12-dind # use a single stage since I don\u0026#39;t want to bounce the image off a registry stages: - build # set up some variables for dating the pdf and exposing the working dir as a volume before_script: - export CI_JOB_TIMESTAMP=$(date -I) - export CI_BUILD_WORKDIR=$(pwd) build-job: stage: build # copy in some commands from the makefile since I couldn\u0026#39;t figure out how # to get a docker image with make installed :) maybe next time. script: - echo \u0026#34;Building Docker container for rendering\u0026#34; - docker build -t latex . - echo \u0026#34;Successfully built container\u0026#34; - echo \u0026#34;Rendering PDF in container\u0026#34; - docker run --rm -i -v $CI_BUILD_WORKDIR:/data latex pdflatex --jobname=resume-$CI_JOB_TIMESTAMP resume.tex - echo \u0026#34;Successfully rendered PDF\u0026#34; # attach the pdf to the job and pipeline artifacts: paths: - ./*.pdf And boom, now I can just change my *.tex files, commit and push, then let GitLab make and host the PDF. All while having a history of what my resume looks like!\n","permalink":"https://mcnowak.io/post/overengineered-pdf-ci-cd-with-docker-and-gitlab/","summary":"Today I decided to update my resume. And by update, I mean make easy to update at any point in the future in a controlled, over-engineered, repeatable way. I\u0026rsquo;ve decided that I\u0026rsquo;d like to be able to modify the LaTex source, commit and push to GitLab, kick off a build on a GitLab runner, use a Docker image to manage dependencies, then store the binary (PDF) output alongside the repo.","title":"Overengineered PDF CI/CD with Docker and GitLab"},{"content":"Today I recreated my personal site using Hugo and Netlify. It took a total of half an hour to get everything set up using a template from GitLab. It took longer to drool over all of the themes than to set this up.\nAnd now, here we are!\n","permalink":"https://mcnowak.io/post/moving-to-hugo/","summary":"Today I recreated my personal site using Hugo and Netlify. It took a total of half an hour to get everything set up using a template from GitLab. It took longer to drool over all of the themes than to set this up.\nAnd now, here we are!","title":"Moving to Hugo"},{"content":"Kaggle is an online community of data scientists and machine learning practitioners. And it\u0026rsquo;s also a great place to get your feet wet in data science. I recently ran through two free courses: Intro to SQL, and Advanced SQL. Both of these courses are free, and will give you a good introduction to both SQL in general and Google BigQuery.\nKaggle Intro to SQL You might think that you can skip this if you know SQL. You already know what SELECT does. You already know tables and schemas and keys and JOINs work. Well if you don\u0026rsquo;t know Google BigQuery or haven\u0026rsquo;t used Kaggle or pandas before, you need this.\nfrom google.cloud import bigquery # Create a \u0026#34;Client\u0026#34; object client = bigquery.Client() # Construct a reference to the \u0026#34;hacker_news\u0026#34; dataset dataset_ref = client.dataset(\u0026#34;hacker_news\u0026#34;, project=\u0026#34;bigquery-public-data\u0026#34;) # API request - fetch the dataset dataset = client.get_dataset(dataset_ref) # Construct a reference to the \u0026#34;comments\u0026#34; table table_ref = dataset_ref.table(\u0026#34;comments\u0026#34;) # API request - fetch the table table = client.get_table(table_ref) # Preview the first five lines of the table client.list_rows(table, max_results=5).to_dataframe() That\u0026rsquo;s the code to inspect a few rows from a dataset. The boilerplate takes a bit of time to get used to. I kept the page for the first two courses open while working through Intro to SQL and Advanced SQL just because I kept getting the reference to a table and the actual table backwards.\nThe Intro to SQL course runs through an intro to BigQuery, basic keywords, grouping, ordering, and ends with JOINing tables. Overall, it\u0026rsquo;s a great way to kill a few birds with one stone if you\u0026rsquo;re totally fresh to Kaggle, BigQuery, or SQL.\nKaggle Advanced SQL Google BigQuery allows you to nest records. A record in a record. And it\u0026rsquo;s more efficient. No need to JOIN. Really interesting if you\u0026rsquo;re coming from a Microsoft SQL Server background. How does it work. Total magic. I\u0026rsquo;ve used OPENJSON before. And it was a pain in the ass. And no schema. BigQuery has nested records which each have a defined schema. It\u0026rsquo;s amazing. Go try it out.\nThe rest of the course is just normal advanced SQL: aggregates, analytics functions, windowing and partitioning, and a light into to optimization. You know, so you don\u0026rsquo;t blow through your 3 TB allocation on Google Cloud by SELECT * ...ing from a twenty table JOIN.\nOverall, really nice courses Kaggle\u0026rsquo;s notebooks for these courses are super slick. I only ran into a single issue when exploring the GitHub sample data where the recommended safe scan size (so you don\u0026rsquo;t blow through your 3TB scan limit on Google Cloud) was over the default safe limit. The query scanned somewhere close to 26GB of data when running through a query. I just bumped the limit to 30GB using the job_config parameter to the BigQuery client.query() call and continued along.\nThe hint system is great. Each question has a hint and a solution if you get stuck. Just uncomment the call to the hint method or the solution method for that question, and boom the solution or hint is shown in the notebook.\n","permalink":"https://mcnowak.io/post/a-short-review-of-the-kaggle-sql-courses/","summary":"Kaggle is an online community of data scientists and machine learning practitioners. And it\u0026rsquo;s also a great place to get your feet wet in data science. I recently ran through two free courses: Intro to SQL, and Advanced SQL. Both of these courses are free, and will give you a good introduction to both SQL in general and Google BigQuery.\nKaggle Intro to SQL You might think that you can skip this if you know SQL.","title":"A short review of the Kaggle SQL Courses"},{"content":"I deployed this site in about four hours. I cheated, I cut corners, I used a bunch of free tools and templates. And this is exactly what I needed.\nStarting at 90% complete by using a Next.js template Next.js is a React front-end framework for building either static or server-side rendered sites. It\u0026rsquo;s awesome. And Next.js has a WordPress CMS example (which looks pretty nice) And Next.js has more examples for almost anything you can think of. Creating a new GitHub repo, copying a template, tweaking it just a bit, and hooking up a CMS or writing markdown files gets us about 90% to a complete, simple blog or personal site.\nPut it out there on that big, beautiful world wide web (99% complete) Hooking my repository up to Netlify for free deployment and hosting (yes completely free) took about 5 minutes. There\u0026rsquo;s a button in their beautiful menu that basically does it for you.\nOnce you\u0026rsquo;ve authorized Netlify to rifle through your repository, it\u0026rsquo;s almost like it deploys itself. One small gotcha that I missed because reading docs is for nerds (jk please read the docs please) was that setting up your build is about 100x easier if you have a netlify.toml file in your project root.\nThen you\u0026rsquo;ll need to describe that as an npm export command in package.son,\nSpooky complicated, I know.\nThat last 1% Go drop some $$$\u0026rsquo;s on a domain (I used Google Domains) and plug it into Netlify,\nThen you\u0026rsquo;ll have to do some magic and make sure that Netlify is being used for your domain\u0026rsquo;s name servers. This will depend on where you got your domain (it was a copy-paste and wait scenario for Google Domains.) And at this point, Netlify will automagically generate a certificate for you using Let\u0026rsquo;s Encrypt! I don\u0026rsquo;t know how that works and I don\u0026rsquo;t care but I think it\u0026rsquo;s awesome.\nAnd that\u0026rsquo;s it! So for the price of just a few dollars or some ridiculous aftermarket price for a domain, you now have a personal site. A site with free hosting. Free builds. Free deployment management. Available anywhere. With your beautiful face and name plastered all over it. Congratulations Netlify- I mean you did it. I\u0026rsquo;m so proud 🎉\n","permalink":"https://mcnowak.io/post/how-i-deployed-this-site-in-a-couple-hours-for-almost-free/","summary":"I deployed this site in about four hours. I cheated, I cut corners, I used a bunch of free tools and templates. And this is exactly what I needed.\nStarting at 90% complete by using a Next.js template Next.js is a React front-end framework for building either static or server-side rendered sites. It\u0026rsquo;s awesome. And Next.js has a WordPress CMS example (which looks pretty nice) And Next.js has more examples for almost anything you can think of.","title":"How I deployed this site in a couple hours for (almost) free"},{"content":"My name is Michael Nowak and I\u0026rsquo;m a software engineer who decided to finally make a blog.\n","permalink":"https://mcnowak.io/page/about/","summary":"My name is Michael Nowak and I\u0026rsquo;m a software engineer who decided to finally make a blog.","title":"About"}]