From 5c086bc52fa3a226bcf706b1f420a5d98ea377dd Mon Sep 17 00:00:00 2001 From: Patrick Spek Date: Wed, 15 Dec 2021 10:45:58 +0100 Subject: Redo most of the blog in Hugo Missing posts will have to be added later --- content/posts/2017/2017-09-14-how-to-git.md | 182 +++++++++++++++++++++ ...17-09-28-perl6-creating-a-background-service.md | 157 ++++++++++++++++++ content/posts/2017/_index.md | 3 + 3 files changed, 342 insertions(+) create mode 100644 content/posts/2017/2017-09-14-how-to-git.md create mode 100644 content/posts/2017/2017-09-28-perl6-creating-a-background-service.md create mode 100644 content/posts/2017/_index.md (limited to 'content/posts/2017') diff --git a/content/posts/2017/2017-09-14-how-to-git.md b/content/posts/2017/2017-09-14-how-to-git.md new file mode 100644 index 0000000..39b884e --- /dev/null +++ b/content/posts/2017/2017-09-14-how-to-git.md @@ -0,0 +1,182 @@ +--- +date: 2017-09-14 +title: "How to: git" +tags: +- Tutorial +- Git +--- + +This guide will explain how to use `git` more efficiently, and why you should +use it as such. + +## Forking +When working in a team, there's generally a remote server which is used to sync +your repositories. There are gratis services, such as [GitHub][github], +[Gitlab][gitlab], [GOGS][gogs], and others. These services also allow you to +*fork* a repository. This basically makes a copy of the entire repository for +your own use. In it, you have full control over the branches, tags, merge +process and everything else you want to do with it. + +One the main reasons to do this is so you do not have to clutter up the main +repository with a ton of branches (these are explained later in the post). If +there are two people working in the same branch, it can help reduce conflicts, +as each developer is working on the branch in his own fork. + +As such, **always** use a fork. If the service does not have a fancy button for +you to click, you can still fork manually. Simply clone their repository as +usual, set a new remote and push it there: + +``` +git clone git@domain.tld:them/repo.git +cd repo +git remote rename origin upstream +git remote add origin git@domain.tld:you/repo.git +git push origin master +``` + +The default naming convention uses `upstream` for the base of your fork, and +`origin` for your remote version of the repository. If a merge request is +accepted on the original repo, you can apply it to your fork using + +``` +git pull upstream master +``` + +## Branching +Branching is the art of using separate branches to introduce new code into your +`master` branch. Every git repository starts with a `master` branch by default. +This is the *main* branch of your repository. + +Every time you want to add new code to your project, make a branch for the +feature or issue you are trying to solve. This way, you can commit freely +without having to worry about having untested or possibly broken code in the +`master` branch. If something were to come up with a higher priority, such as a +critical bug, you can simply create a new branch off of `master`, fix it and +merge that back into `master`, without having to worry about that other feature +you were working on, which is not in a releasable state yet. Once the fix is +applied, you go back to your feature branch on continue working on the cool new +stuff you wanted to implement. Now, the bug is fixed, and no code has been +released that should not have been released. If that's not convincing enough, +try some of the [Stack Overflow posts][so-git-branch] on this very topic. + +Branches can be made at your leisure, with next to no overhead on your project. +Do not be scared to play around with your code in a new branch to test +something out. You can also delete branches as quickly as you made them if you +are not satisfied with the result. + +Creating branches is done using `git checkout -b new-branch`. If you need to +switch to another existing branch to change something, use +`git checkout other-branch`. Deleting a branch can be done using +`git branch -D old-branch`. You can get a list of all branches in the +repository with `git branch`. The current branch is marked with an \*. + +If you start a new branch to implement a feature, be sure to always branch off +of `master`, unless you have a very compelling reason not to do so. If you are +not sure what reasons would validate branching off of another branch, you +should just branch off of `master`. If you branch off of another branch, you +will have the commit history of the other branch. This often includes commits +not accepted into master yet, which might result into commits getting into +master which should not be there (yet), or annoying merge conflicts later on. + +### Merging +Using multiple branches brings along the concept of *merging* branches +together. When working in a group, this is generally done by maintainers of the +upstream repository, via a *merge request*. For some reason, certain services +have named this as a *pull request* instead. The base idea of the process is as +follows: + +- Pull the latest `upstream/master` +- Create a new branch +- Apply the change you want +- Issue a merge request via the service you are using + - Generally, you want your change to be merged into their `master` branch +- Add a title and a description of your change: What does it do, and why should it be accepted +- Optionally, discuss the changes with the upstream maintainers +- Optionally, make a couple of changes to your branch, and push it again +- Upstream maintainer accepts your change + +When everything worked out, the upstream repository now contains your changes. +If you pull their branch again, it will contain your code. Using the merge +request process, your code can be easily reviewed by others, and discussed if +needed. + +## Committing +Whenever you have changed anything in the repository and you wish to share +these changes, you have to commit the changes. Committing in general is not +something people tend to have issues with. Simple add the changes you want to +commit using `git add` (add the `-p` switch if you want to commit only parts of +a changed file), then `git commit` and enter a descriptive message. And that is +where most annoyances come from: the commit *message*. There are no hard rules +on this forced by git itself. There are, however, some de-facto standards and +best practices which you should always follow. Even if you never intend to +share the repository with other people, having good commit messages can help +you identify a certain change when you look back into the history. + +A git commit message should be short, no more than 79 characters, on the first +line. It should be readable as "this commit message will ...", where your +commit message will replace the "...". It is a de-facto standard to start your +commit message with a capital letter, and leave off a finishing period. You do +not *have* to adhere to if you hate this, but be sure that all your commits are +consistent in how they are formatted. + +If you need to explain anything beyond that, such as a rationale for the +change, or things the reviewer should pay attention to in this particular +commit, you can leave an empty line and publish this message in the commit +body. + +When you are using a bug tracking system, you might also want to have a footer +with additional information. On services such as [Gitlab][gitlab] and +[GitHub][github], you can close issues by adding "Closes: #1" in the commit +message footer. A full commit message with all these things might look as +follows: + +``` +Fix overflow issue in table rendering mechanism + +An overflow issue was found in the table rendering mechanism, as explained in +CVE-0123-45678. Regression tests have been included as well. + +Closes: #35 +``` + +In order to achieve these kind of messages, you need to be sure that your +commits can fit in to this structure. This means you need to make small +commits. Having many smaller commits makes it easier to review the changes, +keep short, descriptive messages to describe each change, and revert a single +change in case it breaks something. + +### Signing your commits +You can set up git to cryptographically sign each commit you make. This will +ensure that the commit you made is proven to be from you, and not someone +impersonating you. People impersonating you might try to get harmful code into +a repo where you are a trusted contributor. Having all commits signed in a +repository can contribute in verifying the integrity of the project. + +Recently, [Github][github] has added the **Verified** tag to commits if the +commit contains a correct signature. + +To enable signing of all commits, add the following configuration to your +`~/.gitconfig`: + +```ini +[commit] + gpgsign = true + +[user] + signingkey = 9ACFE193FFBC1F50 +``` + +Ofcourse, you will have to update the value of the `signingkey` to match +the key you want to sign your commits with. + +## Closing words +I hope this post will help you in your adventures with git. It is a great tool +or working on projects together, but it gets much better when you stick to some +best practices. If you have any suggestions for this post, or any questions +after finishing it, contact me via any method listed on [my home page][home]. + +[github]: https://github.com +[gitlab]: https://gitlab.com +[gogs]: https://gogs.io +[home]: https://tyil.work +[so-git-branch]: https://softwareengineering.stackexchange.com/questions/335654/git-what-issues-arise-from-working-directly-on-master diff --git a/content/posts/2017/2017-09-28-perl6-creating-a-background-service.md b/content/posts/2017/2017-09-28-perl6-creating-a-background-service.md new file mode 100644 index 0000000..4f94bb6 --- /dev/null +++ b/content/posts/2017/2017-09-28-perl6-creating-a-background-service.md @@ -0,0 +1,157 @@ +--- +date: 2017-09-28 +title: Perl 6 - Creating a background service +tags: +- Tutorial +- Perl6 +- Programming +- Raku +--- + +I've recently made some progress on +[Shinrin](https://github.com/scriptkitties/perl6-Shinrin) a centralized logging +system in Perl 6. This has to run as service, which means that for most service +managers it has to be able to run in the background. + +{{< admonition title="Note" >}} +If you just want to get to the solution and don't care for the details, just +head straight to [the full script](#the-final-solution). +{{< / admonition >}} + +## It's not possible! + +After a lot of trying and talking with the folks at +[#perl6](irc://chat.freenode.net:6697/#perl6) I was told that it is not possible +to do this in pure Perl 6, explained by people with more knowledge than I have +on the internals: + +{{< quote attribution="jnthn" >}} +(jnthn suspects fork + multi-threaded VM = pain) Since fork only clones one +thread - the one that called it. So suddenly you've got an instance of the VM +missing most of its threads. +{{< / quote >}} + +{{< quote attribution="geekosaur" >}} +The most common failure mode is that some thread is holding e.g. a mutex (or a +userspace lock) during the fork. The thread goes away but the lock is process +level and remains, with nothing around to know to unlock it. So then things +work until something else needs that lock and suddenly you deadlock. +{{< / quote >}} + +Not much later, `jnthn` [pushed a +commit](https://github.com/perl6/doc/commit/8f9443c3ac) to update the docs to +clarify that a `fork` call through `NativeCall` will probably not give the +result you were hoping for. + +## Or is it? + +Luckily, the same people were able to think up of a work-around, which can be +made in POSIX sh, so it's usable on any decent OS. The workaround is to let a +little shell script fork into the background, and let that run the Perl +application. + +### A first example +This is fairly simple to create, as in this example to launch `shinrind` in the +background: + +```sh +#! /usr/bin/env sh + +main() +{ + perl6 -Ilib bin/shinrind "$@" +} + +main "$@" & +``` + +This works just fine if the working directory is correct. This means you need +to be in the parent directory to `lib` and `bin` of the program to make it +work. + +## Improving the forking script + +While that short script works fine to show a proof of concept, in order to make +it viable for real-world scenarios, it can use some improvements. After all, it +would be annoying if you'd have to `cd` to a specific directory any time you +want to start your application. + +### Ensure you are in the directory you should be in + +So for starters, let's make sure that you can run it from anywhere on your +system. For this, you should set the working directory for the script, so you +don't have to do it manually. Because the script runs in its own subshell, the +shell you're working from remains unaffected. + +A POSIX compliant way to get the directory the script is stored in is as +follows: + +```sh +DIR=$(CDPATH="" cd -- "$(dirname -- "$0")" && pwd) +``` + +This will set `$DIR` to the path of the directory the shell script is stored +in. You can simply `cd` to that and be assured you're in the right directory. + +In Perl 6, it is expected for executable files to live in the `bin` directory +of your project repository. So you should actually be in the parent of the +directory holding your script. Furthermore, you should check the `cd` command +executed correctly, just to be safe. + +```sh +cd -- "${DIR}/.." || exit +``` + +### Disable `STDOUT` and `STDERR` + +A started service should not be polluting your interactive shell, so you should +disable (or otherwise redirect) `STDOUT` and `STDERR`. This is done in the +shell using a small bit of code behind whatever you want to redirect: + +```sh +> /dev/null 2>&1 +``` + +This will set `STDOUT` to `/dev/null`, and set `STDERR` to the same stream as +`STDOUT`, which in effect will make all output go to `/dev/null`. If you want +to log everything to a single file, you can replace `/dev/null` with another +file of your choice. If you don't want logs to be overwritten on each start, +use a `>>` instead of a single `>` at the start. + +If you want to log errors and output in different files, you can use the +following: + +```sh +> /var/log/service.log 2> /var/log/service.err +``` + +This will put standard output in `/var/log/service.log` and errors in +`/var/log/service.err`. + +### Fork just the Perl 6 program + +In the initial example, I put the `&` behind the `main` call, at the bottom of +the script. While this works just fine for most simple usage, if you want to do +additional chores, like creating a pidfile after starting the Perl 6 program, +you're out of luck. If you were to only fork the Perl 6 application, you could +handle some other cases in the shell script. + +### The final solution + +For those eager to just get going with this, here is the complete example +script to just fork your Perl program into the background: + +```sh +#! /usr/bin/env sh + +readonly DIR=$(CDPATH="" cd -- "$(dirname -- "$0")" && pwd) + +main() +{ + cd -- "${DIR}/.." || exit + + perl6 -Ilib bin/shinrind "$@" > /dev/null >2&1 & +} + +main "$@" +``` diff --git a/content/posts/2017/_index.md b/content/posts/2017/_index.md new file mode 100644 index 0000000..141c28d --- /dev/null +++ b/content/posts/2017/_index.md @@ -0,0 +1,3 @@ +--- +title: 2017 +--- -- cgit v1.1