-
Notifications
You must be signed in to change notification settings - Fork 0
/
feed.json
191 lines (191 loc) · 89.1 KB
/
feed.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
{
"version": "https://jsonfeed.org/version/1",
"title": "Finecloud",
"description": "",
"home_page_url": "https://www.finecloud.ch",
"feed_url": "https://www.finecloud.ch/feed.json",
"user_comment": "",
"author": {
"name": "Finecloud"
},
"items": [
{
"id": "https://www.finecloud.ch/automatically-update-hidden-dependencies-in-your-dockerfiles.html",
"url": "https://www.finecloud.ch/automatically-update-hidden-dependencies-in-your-dockerfiles.html",
"title": "Automatically update the hidden dependencies in your Dockerfiles",
"summary": "You have probably already heard about Renovate - the fantastic tool that helps you to keep your dependencies up to date. But today, we want to look at an edge case: how to keep your dependencies in your dependencies up to date (also called hidden…",
"content_html": "\n <p>\n You have probably already heard about Renovate - the fantastic tool that helps you to keep your dependencies up to date.\n </p>\n\n <p>\n But today, we want to look at an edge case: how to keep your dependencies in your dependencies up to date (also called hidden dependencies)?\n </p>\n\n <p>\n Atlassian provides a Confluence image. If you want to run this with an Oracle database, you have to inject the Oracle JDBC driver yourself. But how can you ensure that you automatically always will have the most recent OJDBC driver in your Confluence image? \n </p>\n<pre class=\" language-docker\"><code>FROM atlassian/confluence:8.5.15-ubuntu-jdk17\n\n# Download the ojdbc driver\nRUN curl -fSL \"https://repo1.maven.org/maven2/com/oracle/database/jdbc/ojdbc10/19.23.0.0/ojdbc10-19.23.0.0.jar\" \\\n -o \"${CONFLUENCE_INSTALL_DIR}/confluence/WEB-INF/lib/ojdbc10.jar\"\n\n</code></pre>\n\n <p>\n First of all, let's extract the semantic version tag from the URL into a separate ARG so that Renovate only needs to bump the version there:\n </p>\n<pre class=\" language-docker\"><code>FROM atlassian/confluence:8.5.15-ubuntu-jdk17\n\nARG OJDBC_VERSION=19.24.0.0\n\n# Download the ojdbc driver\nRUN curl -fSL \"https://repo1.maven.org/maven2/com/oracle/database/jdbc/ojdbc10/${OJDBC_VERSION}/ojdbc10-${OJDBC_VERSION}.jar\" \\\n -o \"${CONFLUENCE_INSTALL_DIR}/confluence/WEB-INF/lib/ojdbc10.jar\"\n</code></pre>\n\n <p>\n Next, we will add a comment directly above the ARG OJDBC version, which we will later use to tell Renovate what dependency type and package this version tag is about. It's a maven package with the package name \"com.oracle.database.jdbc:ojdbc10\":\n </p>\n<pre class=\" language-docker\"><code>FROM atlassian/confluence:8.5.15-ubuntu-jdk17\n\n# renovate: datasource=maven depName=com.oracle.database.jdbc:ojdbc10 packageName=com.oracle.database.jdbc:ojdbc10\nARG OJDBC_VERSION=19.24.0.0\n\n# Download the ojdbc driver\nRUN curl -fSL \"https://repo1.maven.org/maven2/com/oracle/database/jdbc/ojdbc10/${OJDBC_VERSION}/ojdbc10-${OJDBC_VERSION}.jar\" \\\n -o \"${CONFLUENCE_INSTALL_DIR}/confluence/WEB-INF/lib/ojdbc10.jar\"</code></pre>\n\n <p>\n You could write a custom regex manager in the Renovate config that updates this version tag. But what if you have multiple ARG or ENV version tags in multiple Dockerfiles within the same repo? You Probably don't want to write a regex config for each case.\n </p>\n\n <p>\n Let's imagine you have something like this in your Dockerfile:\n </p>\n<pre class=\" language-docker\"><code># renovate: datasource=github-tags depName=node packageName=nodejs/node versioning=node\nENV NODE_VERSION=20.10.0\n# renovate: datasource=github-releases depName=composer packageName=composer/composer\nENV COMPOSER_VERSION=1.9.3\n# renovate: datasource=docker packageName=docker versioning=docker\nENV DOCKER_VERSION=19.03.1\n# renovate: datasource=npm packageName=yarn\nENV YARN_VERSION=1.19.1</code></pre>\n\n <p>\n All you now need is the following regex configuration in your <em>renovate.json</em> config to detect and bump all of these version tags:\n </p>\n<pre class=\" language-json\"><code>{\n \"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n \"extends\": [\n \"config:recommended\"\n ],\n \"separateMinorPatch\": true,\n \"customManagers\": [\n {\n \"customType\": \"regex\",\n \"description\": \"Update _VERSION variables in Dockerfiles\",\n \"fileMatch\": [\"(^|/|\\\\.)Dockerfile$\", \"(^|/)Dockerfile\\\\.[^/]*$\"],\n \"matchStrings\": [\n \"# renovate: datasource=(?<datasource>[a-z-]+?)(?: depName=(?<depName>.+?))? packageName=(?<packageName>.+?)(?: versioning=(?<versioning>[a-z-]+?))?\\\\s(?:ENV|ARG) .+?_VERSION=(?<currentValue>.+?)\\\\s\"\n ]\n }\n ]\n}</code></pre>\n\n <p>\n Now, you could even set up auto merge for these Renovate updates. Make sure you have some merge checks before you enable this. At least you should ensure that the Docker image can still be built before a new Renovate pull request gets auto-merged.\n </p>\n\n <p>\n ✨ Happy renovating! ✨\n </p>",
"author": {
"name": "Finecloud"
},
"tags": [
"software development",
"renovate",
"regex",
"maven",
"linux",
"docker",
"devops",
"container",
"bash"
],
"date_published": "2024-09-13T17:23:46+02:00",
"date_modified": "2024-09-13T22:50:31+02:00"
},
{
"id": "https://www.finecloud.ch/github-classic-vs-fine-grained-personal-access-tokens.html",
"url": "https://www.finecloud.ch/github-classic-vs-fine-grained-personal-access-tokens.html",
"title": "GitHub classic vs. fine-grained Personal Access Tokens",
"summary": "What are PATs? Personal access tokens are an alternative to using passwords for authentication to GitHub when using the GitHub API or the command line. Personal access tokens are intended to access GitHub resources on your behalf. To access resources on behalf of an organization,…",
"content_html": "\n <div class=\"post__toc\">\n <h3>Contents</h3>\n <ul>\n <li><a href=\"#what-are-pats\">What are PATs?</a></li><li><a href=\"#what-are-classic-pats\">What are classic PATs?</a></li><li><a href=\"#what-are-fine-grained-pats\">What are fine-grained PATs?</a></li><li><a href=\"#what-happens-when-the-user-who-generated-them-becomes-inactive-and-loses-access-to-the-resource\">What happens when the user who generated them becomes inactive and loses access to the resource?</a></li><li><a href=\"#what-are-the-risks-to-consider-with-pats\">What are the risks to consider with PATs?</a></li><li><a href=\"#can-a-classic-pat-owned-by-a-regular-gh-user-be-used-to-access-and-manipulate-a-gh-internal-repo-from-externally-without-any-other-auth-requirement\">Can a classic PAT (owned by a regular GH user) be used to access and manipulate a GH internal Repo from externally without any other auth requirement?</a></li><li><a href=\"#can-a-fine-grained-pat-owned-by-a-regular-gh-user-be-used-to-access-and-manipulate-a-gh-internal-repo-from-externally-without-any-other-auth-requirement\">Can a fine-grained PAT (owned by a regular GH User) be used to access and manipulate a GH internal Repo from externally without any other auth requirement?</a></li><li><a href=\"#can-a-fine-grained-pat-owned-by-the-org-be-used-to-access-and-manipulate-a-gh-internal-repo-externally-without-any-other-auth-requirement\">Can a fine-grained PAT (owned by the Org) be used to access and manipulate a GH internal Repo externally without any other auth requirement?</a></li><li><a href=\"#how-can-org-admins-restrict-classic-pats-access-to-the-org\">How can Org. Admins restrict classic PATs access to the Org?</a></li><li><a href=\"#how-can-you-manage-classic-pats-of-the-users-as-an-org-adminlessbrgreater\">How can you manage classic PATs of the Users as an Org Admin?<br></a></li><li><a href=\"#how-can-i-restrict-org-access-of-fine-grained-pats-as-an-org-admin\">How can I restrict Org access of fine-grained PATs as an Org Admin?</a></li><li><a href=\"#how-can-i-manage-fine-grained-pats-of-the-users-as-an-org-admin\">How can I manage fine-grained PATs of the Users as an Org Admin?</a></li><li><a href=\"#overview-of-classic-vs-fine-grained-pats\">Overview of Classic vs. Fine-grained PATs</a></li>\n </ul>\n </div>\n \n\n <h2 id=\"what-are-pats\">\n What are PATs?\n </h2>\n\n <p>\n Personal access tokens are an alternative to using passwords for authentication to GitHub when using the <a href=\"https://docs.github.com/en/rest/overview/authenticating-to-the-rest-api\" target=\"_blank\">GitHub API</a> or the <a href=\"https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#using-a-personal-access-token-on-the-command-line\" target=\"_blank\">command line</a>.<br><br>Personal access tokens are intended to access GitHub resources on your behalf. <strong>To access resources on behalf of an organization, or for long-lived integrations, you should use a GitHub App. For more information, see \"<a href=\"https://docs.github.com/en/apps/creating-github-apps/setting-up-a-github-app/about-creating-github-apps\" target=\"_blank\">About creating GitHub Apps</a>\"</strong><br><br><strong>GitHub recommends that you use fine-grained personal access tokens instead of personal access tokens (classic) whenever possible. (<a href=\"https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#types-of-personal-access-tokens\" target=\"_blank\">source</a>)</strong>\n </p>\n\n <h2 id=\"what-are-classic-pats\">\n What are classic PATs?\n </h2>\n\n <p>\n Personal access tokens (classic) are less secure. <strong>However, some features currently will only work with personal access tokens (classic):</strong>\n </p>\n\n <ul>\n <li><span style=\"color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: 1em; font-weight: var(--font-weight-normal);\">Only personal access tokens (classic) have write access for public repositories that are not owned by you or an organization that you are not a member of.</span><br></li><li>Outside collaborators can only use personal access tokens (classic) to access organization repositories that they are a collaborator on.</li><li>A few REST API endpoints are only available with a personal access tokens (classic). To check whether an endpoint also supports fine-grained personal access tokens, see the documentation for that endpoint, or see \"<a href=\"https://docs.github.com/en/rest/overview/endpoints-available-for-fine-grained-personal-access-tokens\" target=\"_blank\">Endpoints available for fine-grained personal access tokens</a>\".</li>\n </ul>\n\n <p>\n If you choose to use a personal access token (classic), keep in mind that it will grant access to all repositories within the organizations that you have access to, as well as all personal repositories in your personal account.<br><br>As a security precaution, GitHub automatically removes personal access tokens that haven't been used in a year. To provide additional security, we highly recommend adding an expiration to your personal access tokens.\n </p>\n\n <h2 id=\"what-are-fine-grained-pats\">\n What are fine-grained PATs?\n </h2>\n\n <p>\n Fine-grained personal access tokens have several security advantages over personal access tokens (classic):\n </p>\n\n <ul>\n <li>Each token can only access resources owned by a single user or organization.</li><li>Each token can only access specific repositories.</li><li>Each token is granted specific permissions, which offer more control than the scopes granted to personal access tokens (classic).</li><li>Each token must have an expiration date.</li><li>Organization owners can require approval for any fine-grained personal access tokens that can access resources in the organization.</li>\n </ul>\n\n <h2 id=\"what-happens-when-the-user-who-generated-them-becomes-inactive-and-loses-access-to-the-resource\">\n What happens when the user who generated them becomes inactive and loses access to the resource?\n </h2>\n\n <p>\n Both fine-grained personal access tokens and personal access tokens (classic) are tied to the user who generated them and will become inactive if the user loses access to the resource.\n </p>\n\n <h2 id=\"what-are-the-risks-to-consider-with-pats\">\n What are the risks to consider with PATs?\n </h2>\n\n <ul>\n <li>PATs could be leaked if they get into the wrong hands and are used externally</li><li> Org. Admins don't see users classic PATs with Org. access</li>\n </ul>\n\n <h2 id=\"can-a-classic-pat-owned-by-a-regular-gh-user-be-used-to-access-and-manipulate-a-gh-internal-repo-from-externally-without-any-other-auth-requirement\">\n Can a classic PAT (owned by a regular GH user) be used to access and manipulate a GH internal Repo from externally without any other auth requirement?\n </h2>\n\n <p>\n Yes. You need to create a classic PAT, select all permissions and then try to access an internal GitHub Test Repo from an external Computer without any VPN/internal access or SSO auth session. You will be able to pull all the Repo content and write everywhere where the owner of the PAT has access, e.g., create Issues, close PRs, etc.\n </p>\n\n <h2 id=\"can-a-fine-grained-pat-owned-by-a-regular-gh-user-be-used-to-access-and-manipulate-a-gh-internal-repo-from-externally-without-any-other-auth-requirement\">\n Can a fine-grained PAT (owned by a regular GH User) be used to access and manipulate a GH internal Repo from externally without any other auth requirement?\n </h2>\n\n <p>\n Per default, user-owned fine-grained PATs have only read access to public github.com repos. To select access to an internal GH Repo, the Organization must own the PAT, which is only possible if the token request gets approved by an Org. Admin.\n </p>\n\n <h2 id=\"can-a-fine-grained-pat-owned-by-the-org-be-used-to-access-and-manipulate-a-gh-internal-repo-externally-without-any-other-auth-requirement\">\n Can a fine-grained PAT (owned by the Org) be used to access and manipulate a GH internal Repo externally without any other auth requirement?\n </h2>\n\n <p>\n Once the requested PAT got approved by an Org Admin, yes, this is possible. But the token has a maximum lifetime of 1 year. If the user of the PAT changes something on the permissions, the review workflow is again triggered, and an Org Admin must approve the permission change before it is applied.\n </p>\n\n <h2 id=\"how-can-org-admins-restrict-classic-pats-access-to-the-org\">\n How can Org. Admins restrict classic PATs access to the Org?\n </h2>\n\n <p>\n Organization owners/admins can prevent personal access tokens (classic) from accessing resources owned by the organization. Personal access tokens (classic) can still read public resources within the organization.\n </p>\n\n <figure class=\"post__image post__image--center\">\n <img loading=\"lazy\" src=\"https://www.finecloud.ch/media/posts/104/gh-token.png\" height=\"258\" width=\"934\" alt=\"\" sizes=\"100vw\" srcset=\"https://www.finecloud.ch/media/posts/104/responsive/gh-token-xs.png 300w ,https://www.finecloud.ch/media/posts/104/responsive/gh-token-sm.png 480w ,https://www.finecloud.ch/media/posts/104/responsive/gh-token-md.png 768w ,https://www.finecloud.ch/media/posts/104/responsive/gh-token-lg.png 1024w ,https://www.finecloud.ch/media/posts/104/responsive/gh-token-xl.png 1360w ,https://www.finecloud.ch/media/posts/104/responsive/gh-token-2xl.png 1600w\">\n \n </figure>\n\n <p>\n https://github.com/organizations/<your-gh-org-name>/settings/personal-access-tokens\n </p>\n\n <h2 id=\"how-can-you-manage-classic-pats-of-the-users-as-an-org-adminlessbrgreater\">\n How can you manage classic PATs of the Users as an Org Admin?<br>\n </h2>\n\n <p>\n You can't, because you don't see them. Only the User who created the classic PAT can see and manage it.\n </p>\n\n <h2 id=\"how-can-i-restrict-org-access-of-fine-grained-pats-as-an-org-admin\">\n How can I restrict Org access of fine-grained PATs as an Org Admin?\n </h2>\n\n <figure class=\"post__image post__image--center\">\n <img loading=\"lazy\" src=\"https://www.finecloud.ch/media/posts/104/gh-token-2.png\" height=\"264\" width=\"928\" alt=\"\" sizes=\"100vw\" srcset=\"https://www.finecloud.ch/media/posts/104/responsive/gh-token-2-xs.png 300w ,https://www.finecloud.ch/media/posts/104/responsive/gh-token-2-sm.png 480w ,https://www.finecloud.ch/media/posts/104/responsive/gh-token-2-md.png 768w ,https://www.finecloud.ch/media/posts/104/responsive/gh-token-2-lg.png 1024w ,https://www.finecloud.ch/media/posts/104/responsive/gh-token-2-xl.png 1360w ,https://www.finecloud.ch/media/posts/104/responsive/gh-token-2-2xl.png 1600w\">\n \n </figure>\n\n <p>\n https://github.com/organizations/<your-gh-org-name><your-gh-org-name>/settings/personal-access-tokens</your-gh-org-name><br>\n </p>\n\n <h2 id=\"how-can-i-manage-fine-grained-pats-of-the-users-as-an-org-admin\">\n How can I manage fine-grained PATs of the Users as an Org Admin?\n </h2>\n\n <p>\n You can't manage/see the fine-grained PATs the User Account owns. Once the Org owns the PAT, you can see and manage them.<br><br>If the owner is set to the User, the PAT is invisible/unable to manage, but this also means that token only has access to public repos:\n </p>\n\n <figure class=\"post__image post__image--center\">\n <img loading=\"lazy\" src=\"https://www.finecloud.ch/media/posts/104/SCR-20240805-qyyf.png\" height=\"429\" width=\"996\" alt=\"\" sizes=\"100vw\" srcset=\"https://www.finecloud.ch/media/posts/104/responsive/SCR-20240805-qyyf-xs.png 300w ,https://www.finecloud.ch/media/posts/104/responsive/SCR-20240805-qyyf-sm.png 480w ,https://www.finecloud.ch/media/posts/104/responsive/SCR-20240805-qyyf-md.png 768w ,https://www.finecloud.ch/media/posts/104/responsive/SCR-20240805-qyyf-lg.png 1024w ,https://www.finecloud.ch/media/posts/104/responsive/SCR-20240805-qyyf-xl.png 1360w ,https://www.finecloud.ch/media/posts/104/responsive/SCR-20240805-qyyf-2xl.png 1600w\">\n \n </figure>\n\n <p>\n If you select the Organization as the Resource owner of the PAT instead, a fine-grained personal access token request will be made, which needs to be approved by an Org. Admin before it can be used.\n </p>\n\n <p>\n An overview of all Org. owned PATs can be found under this URL; if you are an Org. Admin: https://github.com/organizations/<your-gh-org-name>/settings/personal-access-tokens/active\n </p>\n\n <h2 id=\"overview-of-classic-vs-fine-grained-pats\">\n Overview of Classic vs. Fine-grained PATs\n </h2>\n<div><style type=\"text/css\">\n.tg {border-collapse:collapse;border-spacing:0;}\n.tg td{border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;\n overflow:hidden;padding:10px 5px;word-break:normal;}\n.tg th{border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;\n font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}\n.tg .tg-wp8o{text-align:center;vertical-align:top}\n.tg .tg-73oq{text-align:left;vertical-align:top}\n</style>\n<table class=\"tg\"><thead>\n <tr>\n <th class=\"tg-73oq\"></th>\n <th class=\"tg-wp8o\">Classic PAT</th>\n <th class=\"tg-wp8o\">Fine-grained PAT</th>\n </tr></thead>\n<tbody>\n <tr>\n <td class=\"tg-73oq\">write access for public repositories that are not owned by you or an organization that you are not a member of</td>\n <td class=\"tg-wp8o\">✅</td>\n <td class=\"tg-wp8o\">❌</td>\n </tr>\n <tr>\n <td class=\"tg-73oq\">Outside collaborators can access organization repositories that they are a collaborator on.</td>\n <td class=\"tg-wp8o\">✅</td>\n <td class=\"tg-wp8o\">❌</td>\n </tr>\n <tr>\n <td class=\"tg-73oq\">Can be used with all REST API endpoints</td>\n <td class=\"tg-wp8o\">✅</td>\n <td class=\"tg-wp8o\">❌</td>\n </tr>\n <tr>\n <td class=\"tg-73oq\">Feature release status</td>\n <td class=\"tg-wp8o\">stable</td>\n <td class=\"tg-wp8o\">beta<br></td>\n </tr>\n <tr>\n <td class=\"tg-73oq\">Tokens must have an expiration date</td>\n <td class=\"tg-wp8o\">❌</td>\n <td class=\"tg-wp8o\">✅</td>\n </tr>\n <tr>\n <td class=\"tg-73oq\">Token can inherit all permissions of the User, incl. all repositories <br>within the organizations that the user has access to without any <br>approval/reivew</td>\n <td class=\"tg-wp8o\">✅</td>\n <td class=\"tg-wp8o\">❌</td>\n </tr>\n <tr>\n <td class=\"tg-73oq\">Token permissions can be defined set on repository level (fine-grained)</td>\n <td class=\"tg-wp8o\">❌</td>\n <td class=\"tg-wp8o\">✅</td>\n </tr>\n <tr>\n <td class=\"tg-73oq\">Organization owners can prevent token from accessing resources owned by the organization</td>\n <td class=\"tg-wp8o\">✅</td>\n <td class=\"tg-wp8o\">✅</td>\n </tr>\n <tr>\n <td class=\"tg-73oq\">Organization owners can require approval for each token that can access <br>the organization (e.g. internal Repo) from externally without any other <br>auth requirement</td>\n <td class=\"tg-wp8o\">❌</td>\n <td class=\"tg-wp8o\">✅</td>\n </tr>\n</tbody></table>\n</div>",
"author": {
"name": "Finecloud"
},
"tags": [
"security",
"github",
"devops"
],
"date_published": "2024-07-31T17:32:59+02:00",
"date_modified": "2024-08-05T20:11:49+02:00"
},
{
"id": "https://www.finecloud.ch/third-party-github-actions.html",
"url": "https://www.finecloud.ch/third-party-github-actions.html",
"title": "Third-party GitHub Actions",
"summary": "Today I came across these steps to guide our decision-making process, before using a 3rd Part GitHub Action:",
"content_html": "\n <p>\n Today I came across these steps to guide our decision-making process, before using a 3rd Part GitHub Action:\n </p>\n\n <ol>\n <li><span style=\"color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: 1em; font-weight: var(--font-weight-normal);\">For simple tasks, avoid external GitHub Actions because the risk might outweigh the value. Maybe a simple curl could to it as well? 😉</span><br></li><li><span style=\"color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: 1em; font-weight: var(--font-weight-normal);\">Use GitHub Actions from Verified Creators because they follow a strict security review process.</span><br></li><li><span style=\"color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: 1em; font-weight: var(--font-weight-normal);\">Use the latest version of a GitHub Action because it might contain security fixes.</span><br></li><li><span style=\"color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: 1em; font-weight: var(--font-weight-normal);\">Think about GitHub Actions like dependencies: they need to be maintained and updated. Dependabot or Renovate can help here.</span><br></li><li><span style=\"color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: 1em; font-weight: var(--font-weight-normal);\">Think about disabling or limiting GitHub Actions for your organization(s) in Settings.</span><br></li><li><span style=\"color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: 1em; font-weight: var(--font-weight-normal);\">Have a PR process with multiple reviewers to avoid adding a malicious GitHub Action.</span><br></li>\n </ol>\n\n <p>\n \n </p>",
"author": {
"name": "Finecloud"
},
"tags": [
"security",
"github"
],
"date_published": "2024-04-08T20:50:51+02:00",
"date_modified": "2024-04-08T20:50:51+02:00"
},
{
"id": "https://www.finecloud.ch/github-codespace.html",
"url": "https://www.finecloud.ch/github-codespace.html",
"title": "GitHub Codespace",
"summary": "What is a Codespace? A codespace is a development environment that's hosted in the cloud. You can customize your project for GitHub Codespaces by committing configuration files to your repository (also known as configuration-as-code), which creates a repeatable codespace configuration for all users of your…",
"content_html": "\n <h2 id=\"what-is-a-codespace\">\n What is a Codespace?\n </h2>\n\n <p>\n A codespace is a development environment that's hosted in the cloud. You can customize your project for GitHub Codespaces by committing configuration files to your repository (also known as configuration-as-code), which creates a repeatable codespace configuration for all users of your project. Each codespace you create is hosted by GitHub in a Docker container that runs on a virtual machine. You can choose the type of machine you want to use depending on the resources you need.\n </p>\n\n <h2 id=\"how-can-i-create-a-codespace\">\n How can I create a Codespace?\n </h2>\n\n <p>\n There are four ways to create a Codespace: \n </p>\n\n <ul>\n <li>From a GitHub template or any template repository on GitHub.com to start a new project.</li><li> From a branch in your repository for new feature work.</li><li> From an open pull request to explore work-in-progress.</li><li> From a commit in a repository's history to investigate a bug at a specific point in time.</li>\n </ul>\n\n <p>\n The easiest way to start a Codespace is by clicking the green Code button and then choosing open in a Codespace:\n </p>\n\n <figure class=\"post__image post__image--center\">\n <img loading=\"lazy\" src=\"https://www.finecloud.ch/media/posts/102/SCR-20240405-stqz.png\" height=\"892\" width=\"942\" alt=\"\" sizes=\"100vw\" srcset=\"https://www.finecloud.ch/media/posts/102/responsive/SCR-20240405-stqz-xs.png 300w ,https://www.finecloud.ch/media/posts/102/responsive/SCR-20240405-stqz-sm.png 480w ,https://www.finecloud.ch/media/posts/102/responsive/SCR-20240405-stqz-md.png 768w ,https://www.finecloud.ch/media/posts/102/responsive/SCR-20240405-stqz-lg.png 1024w ,https://www.finecloud.ch/media/posts/102/responsive/SCR-20240405-stqz-xl.png 1360w ,https://www.finecloud.ch/media/posts/102/responsive/SCR-20240405-stqz-2xl.png 1600w\">\n \n </figure>\n\n <h4 id=\"what-happens-when-i-create-a-codespace\">\n What happens when I create a Codespace?\n </h4>\n\n <p>\n When you create a GitHub Codespace, four processes occur:\n </p>\n\n <ol>\n <li>VM and storage are assigned to your Codespace.</li><li> A container is created.</li><li> A connection to the Codespace is made.</li><li> A post-creation setup is made.</li>\n </ol>\n\n <h2 id=\"what-you-can-customize\">\n What you can customize\n </h2>\n\n <p>\n There are many ways you can customize your Codespace. Let's review each one.\n </p>\n\n <ul>\n <li>Settings Sync: You can synchronize your Visual Studio Code (VS Code) settings between the desktop application and the VS Code web client.</li><li>Dotfiles: You can use a dotfiles repository to specify scripts, shell preferences, and other configurations.<br></li><li> Rename a Codespace: When you create a Codespace, it's assigned an autogenerated display name. If you have multiple Codespaces, the display name helps you to differentiate between Codespaces. You can change the display name for your Codespace.<br></li><li> Change your shell: You can change your shell in a Codespace to keep the setup you're used to. When you're working in a Codespace, you can open a new terminal window with a shell of your choice, change your default shell for new terminal windows, or install a new shell. You can also use dotfiles to configure your shell.<br></li><li> Change the machine type: You can change the type of machine that's running your Codespace, so that you're using resources appropriate for the work you're doing.<br></li><li> Set the default editor: You can set your default editor for Codespaces in your personal settings page. Set your editor preference so that when you create a Codespace or open an existing Codespace, it opens to your default editor.<br>- Visual Studio Code (desktop application)<br>- Visual Studio Code (web client application)<br>- JetBrains Gateway - for opening Codespaces in a JetBrains IDE<br>- JupyterLab - the web interface for Project Jupyter<br></li><li> Set the default region: You can set your default region in the GitHub Codespaces profile settings page to personalize where your data is held.<br></li><li> Set the timeout: A Codespace will stop running after a period of inactivity. By default this period is 30 minutes, but you can specify a longer or shorter default timeout period in your personal settings on GitHub. The updated setting applies to any new Codespaces you create, or to existing Codespaces the next time you start them.</li><li>Configure automatic deletion: Inactive Codespaces are automatically deleted. You can choose how long your stopped Codespaces are retained, up to a maximum of 30 days.<br></li>\n </ul>\n\n <h2 id=\"difference-betweenandnbspcodespaces-and-githubdev-editor\">\n Difference between Codespaces and GitHub.dev editor\n </h2>\n\n <h4 id=\"when-should-i-use-github-codespaces-and-when-should-i-use-githubdev\">\n when should I use GitHub Codespaces and when should I use GitHub.dev?\n </h4>\n\n <p>\n GitHub.dev is a good fit if you only want to navigate some files and sources code repositories from GitHub, and maybe make and commit small code changes.\n </p>\n\n <p>\n On the other hand, if you want to run a bunch of tests with your code, or build a heavy application you better use GitHub Codespaces. It has compute associated with it so you can build your code, run your code, and have terminal access. GitHub.dev doesn't have compute in it. With GitHub Codespaces, you get the power of a personal Virtual Machine (VM) with terminal access, the same way you could use your local environment, just in the cloud.\n </p>\n<div><table>\n <tr>\n <th></th>\n <th>GitHub.dev</th>\n <th>GitHub Codespaces</th>\n </tr>\n <tr>\n <td>Cost</td>\n <td>Free</td>\n <td>Free monthly quota of usage for personal accounts</td>\n </tr>\n <tr>\n <td>Availability</td>\n <td>Available to everyone on GitHub.com</td>\n <td>Available to everyone on GitHub.com</td>\n </tr>\n <tr>\n <td>Startup</td>\n <td>GitHub.dev opens instantly with a key-press and you can start using it right away without having to wait for configuration or installation</td>\n <td>When you create or resume a Codespace, the Codespace is assigned a VM, and the container is configured based on the contents of a devcontainer.json file. This setup takes a few minutes to create the development environment.</td>\n </tr>\n <tr>\n <td>Compute</td>\n <td>There's no associated compute, so you can't build and run your code or use the integrated terminal.</td>\n <td>With GitHub Codespaces, you get the power of a dedicated VM to run and debug your application.</td>\n </tr>\n <tr>\n <td>Terminal access</td>\n <td>None</td>\n <td>GitHub Codespaces provides a common set of tools by default, meaning that you can use the Terminal exactly as you would in your local environment.</td>\n </tr>\n <tr>\n <td>Extensions</td>\n <td>Only a subset of extensions that can run on the web appear in the extensions view and can be installed</td>\n <td>With GitHub Codespaces, you can use most extensions from the Visual Studio Code Marketplace.</td>\n </tr>\n</table>\n</div>\n\n <h2 id=\"using-codespace-images\">\n Using Codespace images\n </h2>\n\n <p>\n One of the biggest benefits of codespaces is that Github ships images with the most recent and common tools you need to develop. Have a look at this Repository: <a href=\"https://github.com/devcontainers/images/tree/main/src/universal\" target=\"_blank\" rel=\"nofollow noopener\">https://github.com/devcontainers/images/tree/main/src/universal</a>\n </p>",
"author": {
"name": "Finecloud"
},
"tags": [
"software development",
"github",
"git",
"codespace"
],
"date_published": "2024-04-05T21:02:42+02:00",
"date_modified": "2024-04-06T14:23:11+02:00"
},
{
"id": "https://www.finecloud.ch/awk-and-sed.html",
"url": "https://www.finecloud.ch/awk-and-sed.html",
"title": "Awk and Sed",
"summary": "awk and sed are text manipulation programs. You can use them for example to replace strings: echo image.jpg | sed 's/\\.jpg/.png/' image.png or change order of strings: echo \"hello world\" | awk '{print $2, $1}' world hello awk and sed are harder to learn than…",
"content_html": "\n <p>\n awk and sed are text manipulation programs. You can use them for example to replace strings:\n </p>\n<pre class=\" language-bash\"><code>echo image.jpg | sed 's/\\.jpg/.png/'\nimage.png\n</code></pre>\n\n <p>\n or change order of strings:<br>\n </p>\n<pre class=\" language-bash\"><code>echo \"hello world\" | awk '{print $2, $1}'\nworld hello\n</code></pre>\n\n <p>\n awk and sed are harder to learn than some other basic linux cli tools because they contain their own small programming language.<br>\n </p>\n\n <h2 id=\"awk-basics\">\n awk basics\n </h2>\n\n <p>\n awk transforms lines of text (stdin) into any other text, using a set of instructions (called the awk program):\n </p>\n<pre class=\" language-bash\"><code>awk program input-files\n</code></pre>\n\n <p>\n a awk program can also contain one or more `actions`, for example calculating values or printing text. These `actions` run only when an input matches a `pattern`:<br>`pattern {action}`\n </p>\n\n <p>\n typical patterns include:\n </p>\n\n <ul>\n <li>`BEGIN` runs once before the awk processes any input</li><li>`END` run once after awk has processed all the input</li><li>A Regex surrounded by forward slashes, example: `/^[A-Z]/`</li><li>other awk specific expressions, example: `FNR>5` tells awk to skip the first five lines of input</li>\n </ul>\n\n <p>\n <br>A `pattern` with no `action` runs the default action `{print}` .<br>awk can also perform calculations such as these:\n </p>\n<pre class=\" language-bash\"><code>seq 1 100 | awk '{s+=$1} END {print s}'\n5050</code></pre>\n\n <p>\n (sum numbers 1 to 100)\n </p>\n\n <h2 id=\"sed-basics\">\n sed basics\n </h2>\n\n <p>\n sed like awk can be used to transform text from stdin to any other text using instructions called `sed scripts`:\n </p>\n<pre class=\" language-bash\"><code>sed script input-files</code></pre>\n\n <p>\n the most common use case for sed is text replacement, like in this example:<br>\n </p>\n<pre class=\" language-bash\"><code>echo \"Windows eats Linux for breakfast\" | sed s/Windows/Linux/g | sed s/Linux/Windows/2\n</code></pre>\n\n <p>\n \n </p>",
"author": {
"name": "Finecloud"
},
"tags": [
"shell",
"sed",
"linux",
"bash",
"awk"
],
"date_published": "2024-04-05T20:57:46+02:00",
"date_modified": "2024-04-05T20:58:56+02:00"
},
{
"id": "https://www.finecloud.ch/how-to-do-a-code-review.html",
"url": "https://www.finecloud.ch/how-to-do-a-code-review.html",
"title": "How to do a code review",
"summary": "This Blog post is my personal summary of Googles code review process Make sure to review every line of code you’ve been asked to review, look at the context, make sure you’re improving code health, and compliment developers on good things that they do. Look at…",
"content_html": "\n <p>\n This Blog post is my personal summary of <a href=\"https://google.github.io/eng-practices/review/\" target=\"_blank\" rel=\"nofollow noopener\">Googles code review process</a>\n </p>\n\n <p>\n \n </p>\n\n <div class=\"post__toc\">\n <h3>Table of contents</h3>\n <ul>\n <li><a href=\"#summary-of-what-you-should-look-at\">Summary of what you should look at</a></li><li><a href=\"#the-standard-of-code-review\">The Standard of Code Review</a></li><li><a href=\"#navigate-a-pull-request-pr-in-review\">Navigate a Pull-Request (PR) in review</a><ul><li><a href=\"#1-take-a-broad-view-of-the-change\">1. Take a broad view of the change</a></li><li><a href=\"#2-examine-the-main-parts-of-the-pr\">2. Examine the main parts of the PR</a></li><li><a href=\"#3andnbsplook-through-the-rest-of-the-pr-in-an-appropriate-sequence\">3. Look through the rest of the PR in an appropriate sequence</a></li></ul></li><li><a href=\"#speed-of-code-reviews\">Speed of Code Reviews</a><ul><li><a href=\"#approve-with-comments\">Approve with Comments</a></li></ul></li><li><a href=\"#how-to-write-comments\">How to write comments</a></li>\n </ul>\n </div>\n \n\n <h2 id=\"summary-of-what-you-should-look-at\">\n Summary of what you should look at\n </h2>\n\n <ul>\n <li><strong>Design</strong>: Is the code well-designed and appropriate for your system?<br></li><li> <strong>Functionality</strong>: Does the code behave as the author likely intended? Is the way the code behaves good for its users?</li><li><strong>Complexity</strong>: Could the code be made simpler? Would another developer be able to easily understand and use this code when they come across it in the future?</li><li><strong>Tests</strong>: Does the code have correct and well-designed automated tests?<br></li><li> <strong>Naming</strong>: Did the developer choose clear names for variables, classes, methods, etc.?</li><li><strong>Comments</strong>: Are the comments clear and useful?</li><li><strong>Style</strong>: Does the code follow our style guides?</li><li><strong>Documentation</strong>: Did the developer also update relevant documentation?<br></li>\n </ul>\n\n <p>\n Make sure to review <strong>every line</strong> of code you’ve been asked to review, look at the <strong>context</strong>, make sure you’re <strong>improving code health</strong>, and compliment developers on <strong>g</strong><strong>ood things</strong> that they do.\n </p>\n\n <h2 id=\"the-standard-of-code-review\">\n The Standard of Code Review\n </h2>\n\n <ul>\n <li>You need to balance the tradeoff between making progress, by letting a change go into your code base and not decreasing overall code health and quality. </li><li><span style=\"color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: 1em; font-weight: var(--font-weight-normal);\">does the Pull-Request improve the maintainability, readability, and understandability?</span><br></li><li><strong>In general you should try to approve a Pull-Request (PR) once it is in a state where it definitely improves the overall code health, even if the PR isn’t perfect.</strong></li><li>Reviewers should not require the author to polish every tiny piece of a CL before granting approval. Rather, the reviewer should balance out the need to make forward progress compared to the importance of the changes they are suggesting. </li><li>Instead of seeking perfection, what a reviewer should seek is continuous improvement.</li><li>If you add a comment on a PR to mention something could be better, but it’s optional and not very important, prefix it with something like “Nit: “ to let the author know that it’s just a point of polish that they could choose to ignore.</li>\n </ul>\n\n <h2 id=\"navigate-a-pull-request-pr-in-review\">\n Navigate a Pull-Request (PR) in review\n </h2>\n\n <h3 id=\"1-take-a-broad-view-of-the-change\">\n 1. Take a broad view of the change\n </h3>\n\n <p>\n Look at the PR description and what the PR does in general. Does this change even make sense? If this change shouldn’t have happened in the first place, please respond immediately with an explanation of why the change should not be happening. When you reject a change like this, it’s also a good idea to suggest to the developer what they should have done instead.\n </p>\n\n <h3 id=\"2-examine-the-main-parts-of-the-pr\">\n 2. Examine the main parts of the PR\n </h3>\n\n <p>\n Find the file or files that are the “main” part of this PR. Often, there is one file that has the largest number of logical changes, and it’s the major piece of the PR. Look at these major parts first. This helps give context to all of the smaller parts of the PR, and generally accelerates doing the code review. \n </p>\n\n <h3 id=\"3andnbsplook-through-the-rest-of-the-pr-in-an-appropriate-sequence\">\n 3. Look through the rest of the PR in an appropriate sequence\n </h3>\n\n <p>\n Once you’ve confirmed there are no major design problems with the CL as a whole, try to figure out a logical sequence to look through the files while also making sure you don’t miss reviewing any file.\n </p>\n\n <h2 id=\"speed-of-code-reviews\">\n Speed of Code Reviews\n </h2>\n\n <p>\n Why is it so important that you send comments out immediately, especially if you see major design problems within a PR?\n </p>\n\n <ul>\n <li>Developers often open a PR and then immediately start new work based on that PR (e.g. feature branch) while they wait for review. If there are major design problems in the PR you’re reviewing, they’re also going to have to re-work their later PR. You want to catch them before they’ve done too much extra work on top of the problematic design.</li><li>Major design changes take longer to do than small changes. Developers nearly all have deadlines; in order to make those deadlines and still have quality code in the codebase, the developer needs to start on any major re-work of the PR as soon as possible.<br></li>\n </ul>\n\n <p>\n When code reviews are slow, several things happen:\n </p>\n\n <ul>\n <li>The velocity of the team as a whole is decreased.</li><li>Developers start to protest the code review process. Most complaints about the code review process are actually resolved by making the process faster.</li><li>Code health can be impacted.<br></li>\n </ul>\n\n <p>\n How fast should a code review be? \n </p>\n\n <ul>\n <li>If you are not in the middle of a focused task, <strong>you should do a code review shortly after it comes in</strong>.</li><li><strong>One business day is the maximum time it should take to respond</strong> to a code review request (i.e., first thing the next morning).</li>\n </ul>\n\n <p>\n <strong>If you are in the middle of a focused task, such as writing code, don’t interrupt yourself to do a code review</strong>. Research has shown that it can take a long time for a developer to get back into a smooth flow of development after being interrupted. So interrupting yourself while coding is actually more expensive to the team than making another developer wait a bit for a code review.\n </p>\n\n <h3 id=\"approve-with-comments\">\n Approve with Comments\n </h3>\n\n <p>\n In order to speed up code reviews, there are certain situations in which a reviewer should give the Approval even though they are also leaving unresolved comments on the PR. This is done when either:\n </p>\n\n <ul>\n <li>The reviewer is confident that the developer will appropriately address all the reviewer’s remaining comments.</li><li> The remaining changes are minor and don’t have to be done by the developer.</li>\n </ul>\n\n <h2 id=\"how-to-write-comments\">\n How to write comments\n </h2>\n\n <ul>\n <li>Be kind.</li><li>Explain your reasoning (why?).</li><li>Balance giving explicit directions with just pointing out problems and letting the developer decide -> In general it is the developer’s responsibility to fix a PR, not the reviewer’s.</li><li>Encourage developers to simplify code or add code comments instead of just explaining the complexity to you.<br></li>\n </ul>",
"author": {
"name": "Finecloud"
},
"tags": [
"software development",
"devops"
],
"date_published": "2024-03-18T08:44:04+01:00",
"date_modified": "2024-03-18T17:33:39+01:00"
},
{
"id": "https://www.finecloud.ch/building-a-graphql-service.html",
"url": "https://www.finecloud.ch/building-a-graphql-service.html",
"title": "Building a GraphQL service",
"summary": "Let's build a GraphQL Spring Application that will accept GraphQL requests at http://localhost:8080/graphql. First let's navigate to https://start.spring.io. This service pulls in all the dependencies you need for an application and does most of the setup for you. GraphQL is a query language to retrieve…",
"content_html": "\n <div class=\"post__toc\">\n <h3>Table of contents</h3>\n <ul>\n <li><a href=\"#preparation\">Preparation</a></li><li><a href=\"#a-very-short-introduction-to-graphql\">A very short introduction to GraphQL</a></li><li><a href=\"#our-example-api-getting-book-details\">Our example API: getting book details</a></li><li><a href=\"#schema\">Schema</a></li><li><a href=\"#source-of-the-data\">Source of the data</a></li><li><a href=\"#create-the-book-and-author-data-sources\">Create the Book and Author data sources</a></li><li><a href=\"#adding-code-to-fetch-data\">Adding code to fetch data</a></li><li><a href=\"#running-our-first-query\">Running our first query</a><ul><li><a href=\"#enable-the-graphiql-playground\">Enable the GraphiQL Playground</a></li><li><a href=\"#boot-the-application\">Boot the application</a></li><li><a href=\"#run-the-query\">Run the query</a></li></ul></li><li><a href=\"#testing\">Testing</a></li>\n </ul>\n </div>\n \n\n <p>\n Let's build a GraphQL Spring Application that will accept GraphQL requests at http://localhost:8080/graphql.\n </p>\n\n <h2 id=\"preparation\">\n Preparation\n </h2>\n\n <p>\n First let's navigate to https://start.spring.io. This service pulls in all the dependencies you need for an application and does most of the setup for you.<br>\n </p>\n\n <ul>\n <li>Choose Maven and chose Java.Click </li><li>Dependencies and select Spring for GraphQL and Spring Web.</li><li><span style=\"color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: 1em; font-weight: var(--font-weight-normal);\">Click Generate.</span><br></li><li><span style=\"color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: 1em; font-weight: var(--font-weight-normal);\">Download the resulting ZIP file, which is an archive of a GraphQL application that is configured with your choices.</span><br></li><li>Unzip and open the Folder with your favorite IDE (IntelliJ recommended)</li>\n </ul>\n\n <h2 id=\"a-very-short-introduction-to-graphql\">\n A very short introduction to GraphQL\n </h2>\n\n <p>\n GraphQL is a query language to retrieve data from a server. It is an alternative to REST, SOAP, or gRPC. In the next Part we will query the details for a specific book from an online store backend.<br><br>This is an example request you can send to a GraphQL server to retrieve book details:\n </p>\n<pre class=\" language-graphql\"><code>query bookDetails {\n bookById(id: \"book-1\") {\n id\n name\n pageCount\n author {\n firstName\n lastName\n }\n }\n}</code></pre>\n\n <p>\n This GraphQL request says:\n </p>\n\n <ul>\n <li>perform a query for a book with id \"book-1\"</li><li><span style=\"color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: 1em; font-weight: var(--font-weight-normal);\">for the book, return id, name, pageCount and author</span><br></li><li><span style=\"color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: 1em; font-weight: var(--font-weight-normal);\">for the author, return firstName and lastName</span><br></li>\n </ul>\n\n <p>\n The response is in JSON. For example:<br>\n </p>\n<pre class=\" language-json\"><code>{\n \"bookById\": {\n \"id\":\"book-1\",\n \"name\":\"Effective Java\",\n \"pageCount\":416,\n \"author\": {\n \"firstName\":\"Joshua\",\n \"lastName\":\"Bloch\"\n }\n }\n}</code></pre>\n\n <p>\n An important feature of GraphQL is that it defines a schema language, and that it is statically typed. The server knows exactly what types of objects requests can query and what fields those objects contain. Furthermore, clients can introspect the server to ask for schema details.\n </p>\n\n <p class=\"msg msg--info\">\n The word schema in this Post refers to a \"GraphQL Schema\", which is not related to other schemas like \"JSON Schema\" or \"Database Schema\".\n </p>\n\n <p>\n The schema for the above query is:\n </p>\n<pre class=\" language-graphql\"><code>type Query {\n bookById(id: ID): Book\n}\n\ntype Book {\n id: ID\n name: String\n pageCount: Int\n author: Author\n}\n\ntype Author {\n id: ID\n firstName: String\n lastName: String\n}</code></pre>\n\n <p>\n This Post will focus on how to implement a GraphQL server with this schema in Java.<br><br>We’ve barely scratched the surface of what’s possible with GraphQL. Further information can be found on the official GraphQL page.\n </p>\n\n <h2 id=\"our-example-api-getting-book-details\">\n Our example API: getting book details\n </h2>\n\n <p>\n These are the main steps to create a server with Spring for GraphQL:\n </p>\n\n <ol>\n <li>Define a GraphQL schema</li><li>Implement the logic to fetch the actual data for a query<br></li>\n </ol>\n\n <p>\n Our example app will be a simple API to get details for a specific book. It is not intended to be a comprehensive API.\n </p>\n\n <h2 id=\"schema\">\n Schema\n </h2>\n\n <p>\n In your Spring for GraphQL application prepared earlier, add a new file <em>schema.graphqls</em> to the <em>src/main/resources/graphql</em> folder with the following content:\n </p>\n<pre class=\" language-graphql\"><code>type Query {\n bookById(id: ID): Book\n}\n\ntype Book {\n id: ID\n name: String\n pageCount: Int\n author: Author\n}\n\ntype Author {\n id: ID\n firstName: String\n lastName: String\n}</code></pre>\n\n <p>\n Every GraphQL schema has a top-level <em>Query</em> type, and the fields under it are the query operations exposed by the application. Here the schema defines one query called <em>bookById</em> that returns the details of a specific book.<br><br>It also defines the types <em>Book</em> with fields<em> id, name, pageCount</em> and <em>author</em>, and the type <em>Author</em> with fields <em>firstName</em> and <em>lastName</em>.<br>\n </p>\n\n <p class=\"msg msg--info\">\n The Domain Specific Language used above to describe a schema is called the Schema Definition Language or SDL. For more details, see the GraphQL documentation.\n </p>\n\n <h2 id=\"source-of-the-data\">\n Source of the data\n </h2>\n\n <p>\n A key strength of GraphQL is that data can be sourced from anywhere. Data can come from a database, an external service, or a static in-memory list.<br><br>To simplify the demo here, book and author data will come from static lists inside their respective classes.\n </p>\n\n <h2 id=\"create-the-book-and-author-data-sources\">\n Create the Book and Author data sources\n </h2>\n\n <p>\n Let’s now create the <em>Book</em> and <em>Author</em> classes in the main application package, right next to <em>GraphQlServerApplication</em>. Use the following as their content:\n </p>\n<pre class=\" language-java\"><code>package com.example.graphqlserver;\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic record Book (String id, String name, int pageCount, String authorId) {\n\n private static List<Book> books = Arrays.asList(\n new Book(\"book-1\", \"Effective Java\", 416, \"author-1\"),\n new Book(\"book-2\", \"Hitchhiker's Guide to the Galaxy\", 208, \"author-2\"),\n new Book(\"book-3\", \"Down Under\", 436, \"author-3\")\n );\n\n public static Book getById(String id) {\n return books.stream()\n\t\t\t\t.filter(book -> book.id().equals(id))\n\t\t\t\t.findFirst()\n\t\t\t\t.orElse(null);\n }\n}</code></pre>\n<pre class=\" language-java\"><code>package com.example.graphqlserver;\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic record Author (String id, String firstName, String lastName) {\n\n private static List<Author> authors = Arrays.asList(\n new Author(\"author-1\", \"Joshua\", \"Bloch\"),\n new Author(\"author-2\", \"Douglas\", \"Adams\"),\n new Author(\"author-3\", \"Bill\", \"Bryson\")\n );\n\n public static Author getById(String id) {\n return authors.stream()\n\t\t\t\t.filter(author -> author.id().equals(id))\n\t\t\t\t.findFirst()\n\t\t\t\t.orElse(null);\n }\n}</code></pre>\n\n <h2 id=\"adding-code-to-fetch-data\">\n Adding code to fetch data\n </h2>\n\n <p>\n Spring for GraphQL provides an annotation-based programming model. With controller annotated methods, we can declare how to fetch the data for specific GraphQL fields.<br><br>Add the following to <em>BookController.java</em> in the main application package, next to Book and Author:\n </p>\n<pre class=\" language-java\"><code>package com.example.graphqlserver;\n\nimport org.springframework.graphql.data.method.annotation.Argument;\nimport org.springframework.graphql.data.method.annotation.QueryMapping;\nimport org.springframework.graphql.data.method.annotation.SchemaMapping;\nimport org.springframework.stereotype.Controller;\n\n@Controller\npublic class BookController {\n @QueryMapping\n public Book bookById(@Argument String id) {\n return Book.getById(id);\n }\n\n @SchemaMapping\n public Author author(Book book) {\n return Author.getById(book.authorId());\n }\n}</code></pre>\n\n <p>\n By defining a method named <em>bookById</em> annotated with <em>@QuerMapping</em>, this controller declares how to fetch a <em>Book</em> as defined under the Query type. The query field is determined from the method name, but can also be declared on the annotation itself.\n </p>\n\n <p class=\"msg msg--info\">\n Spring for GraphQL uses RuntimeWiring.Builder that registers each such controller method as a GraphQL Java graphql.schema.DataFetcher. A DataFetcher provides the logic to fetch the data for a query or for any schema field. The Spring Boot starter for GraphQL has auto-configurations that automates this registration.\n </p>\n\n <p>\n In the GraphQL Java engine, <em>DataFetchingEnvironment</em> provides access to a map of field-specific argument values. Use the <em>@Argument</em> annotation to have an argument bound to a target object and injected into the controller method. By default, the method parameter name is used to look up the argument, but can also be specified on the annotation itself.<br><br>This <em>bookById</em> method defines how to get a specific <em>Book</em>, but does not take care of fetching the related <em>Author</em>. If the request asks for the author information, GraphQL Java will need to fetch this field.<br><br>The <em>@SchemaMapping</em> annotation maps a handler method to a field in the GraphQL schema and declares it to be the <em>DataFetcher</em> for that field. The field name defaults to the method name, and the type name defaults to the simple class name of the source/parent object injected into the method. In this example, the field defaults to <em>author</em> and the type defaults to <em>Book</em>.<br><br>For more, see the <a href=\"https://docs.spring.io/spring-graphql/reference/controllers.html\" target=\"_blank\" rel=\"nofollow noopener\">documentation for the Spring for GraphQL annotated controller feature</a>.<br><br>Now let’s run our first query.\n </p>\n\n <h2 id=\"running-our-first-query\">\n Running our first query\n </h2>\n\n <h3 id=\"enable-the-graphiql-playground\">\n Enable the GraphiQL Playground\n </h3>\n\n <p>\n GraphiQL is a useful visual interface for writing and executing queries, and much more. Enable GraphiQL by adding this config to the <em>application.properties</em> file.\n </p>\n<pre class=\" language-java\"><code>spring.graphql.graphiql.enabled=true</code></pre>\n\n <h3 id=\"boot-the-application\">\n Boot the application\n </h3>\n\n <p>\n Start your Spring application. Navigate to http://localhost:8080/graphiql.\n </p>\n\n <h3 id=\"run-the-query\">\n Run the query\n </h3>\n\n <p>\n Type in the query and click the play button at the top of the window.<br>\n </p>\n<pre class=\" language-graphql\"><code>query bookDetails {\n bookById(id: \"book-1\") {\n id\n name\n pageCount\n author {\n id\n firstName\n lastName\n }\n }\n}</code></pre>\n\n <p>\n You should see a response like this:\n </p>\n<pre class=\" language-json\"><code>{\n \"data\": {\n \"bookById\": {\n \"id\": \"book-1\",\n \"name\": \"Effective Java\",\n \"pageCount\": 416,\n \"author\": {\n \"id\": \"author-1\",\n \"firstName\": \"Joshua\",\n \"lastName\": \"Bloch\"\n }\n }\n }\n}</code></pre>\n\n <p>\n Congratulations, you have built a GraphQL service and executed your first query! With the help of Spring for GraphQL, you were able to achieve this with only a few lines of code.\n </p>\n\n <h2 id=\"testing\">\n Testing\n </h2>\n\n <p>\n Spring for GraphQL provides helpers for GraphQL testing in the <em>spring-graphql-test</em> artifact. We have already included this artifact as part of the project generated by Spring Initializr.<br><br>Thoroughly testing a GraphQL service requires tests with different scopes. In this tutorial, we will write a <em>@GraphQlTest</em> slice test, which focuses on a single controller. There are other helpers to assist with full end-to-end integration tests and focused server side tests. For the full details, see the Spring for GraphQL Testing documentation and Auto-configured Spring for GraphQL tests in the Spring Boot documentation.<br><br>Let’s write a controller slice test that verifies the same <em>bookDetails</em> query requested in the GraphiQL playground a few moments ago.<br><br>Add the following to a test file <em>BookControllerTests.java</em>. Save this file in a location within the <em>src/test/java/com/example/graphqlserver/</em> folder.\n </p>\n<pre class=\" language-java\"><code>package com.example.graphqlserver;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.autoconfigure.graphql.GraphQlTest;\nimport org.springframework.graphql.test.tester.GraphQlTester;\n\n@GraphQlTest(BookController.class)\npublic class BookControllerTests {\n\n @Autowired\n private GraphQlTester graphQlTester;\n\n @Test\n void shouldGetFirstBook() {\n this.graphQlTester\n\t\t\t\t.documentName(\"bookDetails\")\n\t\t\t\t.variable(\"id\", \"book-1\")\n .execute()\n .path(\"bookById\")\n .matchesJson(\"\"\"\n {\n \"id\": \"book-1\",\n \"name\": \"Effective Java\",\n \"pageCount\": 416,\n \"author\": {\n \"firstName\": \"Joshua\",\n \"lastName\": \"Bloch\"\n }\n }\n \"\"\");\n }\n}\n</code></pre>\n\n <p>\n This test refers to a GraphQL query similar to what we used in the GraphiQL Playground. It’s parameterized with an <em>$id</em> to make it reusable. Add this query in a <em>bookDetails</em>.<em>graphql</em> file located in <em>src/test/resources/graphql-test.</em>\n </p>\n<pre class=\" language-graphql\"><code>query bookDetails($id: ID) {\n bookById(id: $id) {\n id\n name\n pageCount\n author {\n id\n firstName\n lastName\n }\n }\n}</code></pre>\n\n <p>\n Run the test and verify that the result is identical to the GraphQL query manually requested in the GraphiQL Playground.<br><br>The <em>@GraphQlTest</em> annotation is useful for writing controller slice tests, which are focused on a single controller. <em>@GraphQlTest </em>auto-configures the Spring for GraphQL infrastructure, without any transport nor server being involved. Automatic configuration enables us to write tests faster by skipping boilerplate code. As this is a focused slice test, only a limited number of beans are scanned including <em>@Controller</em> and <em>RuntimeWiringConfigurer.</em><br><br><em>GraphQlTester</em> is a contract that declares a common workflow for testing GraphQL requests, independent of transport. In our test, we provide a document with <em>documentName</em> with the required variables, then <em>execute</em> the request. We then select a part of the response with its JSON path and assert that the JSON at this location matches the expected result.<br><br>Congratulations! In this tutorial you built a GraphQL service, ran your first query, and wrote your first GraphQL test!<br>\n </p>\n\n <p>\n \n </p>",
"author": {
"name": "Finecloud"
},
"tags": [
"spring-framework",
"spring",
"software development",
"java",
"graphql",
"api"
],
"date_published": "2024-01-22T21:19:17+01:00",
"date_modified": "2024-01-24T20:15:11+01:00"
},
{
"id": "https://www.finecloud.ch/working-efficient-within-different-directories-in-a-linux-shell.html",
"url": "https://www.finecloud.ch/working-efficient-within-different-directories-in-a-linux-shell.html",
"title": "Working efficient within different directories in a Linux Shell",
"summary": "Lets Suppose you need to perform a certain kind of work in all of these directories: You might know about the \"cd\" command. But isn't it annoying if you need to use and retype a lot of Commands, like for example: $ cd ~/Work/Projects/Web/src $…",
"content_html": "\n <p>\n \n </p>\n\n <div class=\"post__toc\">\n <h3>TOC</h3>\n <ul>\n <ul><li><a href=\"#directory-stack\">Directory stack</a></li><li><a href=\"#push-a-directory-onto-the-stack\">Push a directory onto the stack</a></li><li><a href=\"#view-a-directory-stack\">View a directory stack</a></li><li><a href=\"#pop-a-directory-from-the-stack\">Pop a directory from the stack</a></li><li><a href=\"#swap-directories-on-the-stack\">Swap directories on the stack</a></li><li><a href=\"#turn-a-mistaken-cd-into-a-pushd\">Turn a mistaken cd into a pushd</a></li><li><a href=\"#go-deeper-into-the-stack\">Go deeper into the stack</a></li></ul>\n </ul>\n </div>\n \n\n <p>\n Lets Suppose you need to perform a certain kind of work in all of these directories: \n </p>\n\n <ul>\n <li>/var/www/html</li><li>/etc/apache2</li><li>/etc/ssl/certs</li><li>~/Work/Projects/Web/src</li>\n </ul>\n\n <p>\n You might know about the \"cd\" command. But isn't it annoying if you need to use and retype a lot of Commands, like for example:\n </p>\n<pre class=\" language-bash\"><code>$ cd ~/Work/Projects/Web/src\n$ cd /var/www/html\n$ cd /etc/apache2\n$ cd ~/Work/Projects/Web/src\n$ cd /etc/ssl/certs</code></pre>\n\n <p>\n But there is a much better and more efficient way. Take advantage of a shell feature called a directory stack.\n </p>\n\n <h3 id=\"directory-stack\">\n Directory stack\n </h3>\n\n <p>\n You can manipulate the stack by performing two operations called <em>pushing</em> and <em>popping</em>.\n </p>\n\n <ul>\n <li>Pushing a directory adds it to the beginning of the list, which is traditionally called the top of the stack.</li><li>Popping removes the topmost directory from the stack.</li><li>Initially, the stack contains only your current directory, but you can add (push) and remove (pop) directories and rapidly cd among them.</li>\n </ul>\n\n <h3 id=\"push-a-directory-onto-the-stack\">\n Push a directory onto the stack\n </h3>\n\n <p>\n The command pushd (short for “push directory”) does all of the following:\n </p>\n\n <ol>\n <li>Adds a given directory to the top of the stack</li><li>Performs a cd to that directory</li><li>Prints the stack from top to bottom for your reference</li>\n </ol>\n\n <p>\n Let's build a directory stack of four directories, pushing them onto the stack one at a time:\n </p>\n<pre class=\" language-bash\"><code>$ pwd\n/home/john/Work/Projects/Web/src\n$ pushd /var/www/html\n/var/www/html ~/Work/Projects/Web/src\n$ pushd /etc/apache2\n/etc/apache2 /var/www/html ~/Work/Projects/Web/src\n$ pushd /etc/ssl/certs\n/etc/ssl/certs /etc/apache2 /var/www/html\n~/Work/Projects/Web/src\n$ pwd\n/etc/ssl/certs</code></pre>\n\n <p>\n The shell prints the stack after each pushd operation. The current directory is the leftmost (top) directory.\n </p>\n\n <h3 id=\"view-a-directory-stack\">\n View a directory stack\n </h3>\n\n <p>\n Print a shell’s directory stack with the dirs command. It does not modify the stack:\n </p>\n<pre class=\" language-bash\"><code>$ dirs -p\n/etc/ssl/certs\n/etc/apache2\n/var/www/html\n~/Work/Projects/Web/src</code></pre>\n\n <p>\n you can leave out the -p if you don't want to have each of them at it's own line. Or you can pass a -v to see them numbered:\n </p>\n<pre class=\" language-bash\"><code>$ dirs -v\n0 /etc/ssl/certs\n1 /etc/apache2\n2 /var/www/html\n3 ~/Work/Projects/Web/src\n</code></pre>\n\n <h3 id=\"pop-a-directory-from-the-stack\">\n Pop a directory from the stack\n </h3>\n\n <p>\n The popd command (“pop directory”) is the reverse of pushd. It does all of the following:\n </p>\n\n <ol>\n <li>Removes one directory from the top of the stack</li><li>Performs a cd to the new top directory</li><li>Prints the stack from top to bottom for your reference<br></li>\n </ol>\n\n <p>\n For example, if your stack has four directories:\n </p>\n<pre class=\" language-bash\"><code>$ dirs\n/etc/ssl/certs /etc/apache2 /var/www/html\n~/Work/Projects/Web/src\n</code></pre>\n\n <p>\n then repeatedly running popd will traverse these directories from top to bottom:\n </p>\n<pre class=\" language-bash\"><code>$ popd\n/etc/apache2 /var/www/html ~/Work/Projects/Web/src\n$ popd\n/var/www/html ~/Work/Projects/Web/src\n$ popd\n~/Work/Projects/Web/src\n$ popd\nbash: popd: directory stack empty\n$ pwd\n~/Work/Projects/Web/src</code></pre>\n\n <h3 id=\"swap-directories-on-the-stack\">\n Swap directories on the stack\n </h3>\n\n <p>\n Now that you can build and empty the directory stack, let’s focus on practical use cases. <em>pushd</em> with no arguments swaps the top two directories in the stack and navigates to the new top directory. Let’s jump between /etc/apache2 and your work directory several times by simply running <em>pushd</em>. See how the third directory /var/www/html remains in the stack as the first two directories swap positions:\n </p>\n<pre class=\" language-bash\"><code>$ dirs\n/etc/apache2 ~/Work/Projects/Web/src /var/www/html\n$ pushd\n~/Work/Projects/Web/src /etc/apache2 /var/www/html\n$ pushd\n/etc/apache2 ~/Work/Projects/Web/src /var/www/html\n$ pushd\n~/Work/Projects/Web/src /etc/apache2 /var/www/html</code></pre>\n\n <p>\n <em>pushd</em> behaves similarly to the <em>cd -</em> command, toggling between two directories, but it does not have the limitation of remembering just one directory.\n </p>\n\n <h3 id=\"turn-a-mistaken-cd-into-a-pushd\">\n Turn a mistaken cd into a pushd\n </h3>\n\n <p>\n Suppose you are jumping among several directories with pushd and you accidentally run cd instead and lose a directory:\n </p>\n<pre class=\" language-bash\"><code>$ dirs\n~/Work/Projects/Web/src /var/www/html /etc/apache2\n$ cd /etc/ssl/certs\n$ dirs\n/etc/ssl/certs /var/www/html /etc/apache2</code></pre>\n\n <p>\n Oops, the accidental cd command replaced ~/Work/Projects/Web/src in the stack with /etc/ssl/certs. But don’t worry. You can add the missing directory back to the stack without typing its long path. Just run <em>pushd</em> twice, once with a dash argument and once without:\n </p>\n<pre class=\" language-bash\"><code>$ pushd -\n~/Work/Projects/Web/src /etc/ssl/certs /var/www/html\n/etc/apache2\n$ pushd\n/etc/ssl/certs ~/Work/Projects/Web/src /var/www/html\n/etc/apache2</code></pre>\n\n <p>\n Why this works:\n </p>\n\n <ul>\n <li>The first pushd returns to your shell’s previous directory, ~/Work/Projects/Web/src, and pushes it onto the stack. pushd, like cd, accepts a dash as an argument to mean “go back to my previous directory.”</li><li>The second pushd command swaps the top two directories, bringing you back to /etc/ssl/certs. The end result is that you’ve restored ~/Work/Projects/Web/src to the second position in the stack, exactly where it would have been if you hadn’t made your mistake.</li>\n </ul>\n\n <h3 id=\"go-deeper-into-the-stack\">\n Go deeper into the stack\n </h3>\n\n <p>\n What if you want to cd between directories in the stack other than the top two? <em>pushd</em> and <em>popd</em> accept a positive or negative integer argument to operate further into the stack. The command:\n </p>\n<pre class=\" language-bash\"><code>$ pushd +N</code></pre>\n\n <p>\n shifts N directories from the top of the stack to the bottom and then performs a cd to the new top directory. A negative argument (-N) shifts directories in the opposite direction, from the bottom to the top, before performing the cd.\n </p>\n<pre class=\" language-bash\"><code>$ dirs\n/etc/ssl/certs ~/Work/Projects/Web/src /var/www/html\n/etc/apache2\n$ pushd +1\n~/Work/Projects/Web/src /var/www/html /etc/apache2\n/etc/ssl/certs\n$ pushd +2\n/etc/apache2 /etc/ssl/certs ~/Work/Projects/Web/src\n/var/www/html</code></pre>\n\n <p>\n In this manner, you can jump to any other directory in the stack with a simple command. If your stack is long, however, it may be difficult to judge a directory’s numeric position by eye. So, print the numeric position of each directory with dirs -v, as you did in “View a<br>directory stack”:\n </p>\n<pre class=\" language-bash\"><code>$ dirs -v\n0 /etc/apache2\n1 /etc/ssl/certs\n2 ~/Work/Projects/Web/src\n3 /var/www/html</code></pre>\n\n <p>\n To shift /var/www/html to the top of the stack (and make it your current directory), run pushd +3. To jump to the directory at the bottom of the stack, run pushd -0 (dash zero):\n </p>\n<pre class=\" language-bash\"><code>$ dirs\n/etc/apache2 /etc/ssl/certs ~/Work/Projects/Web/src\n/var/www/html\n$ pushd -0\n/var/www/html /etc/apache2 /etc/ssl/certs\n~/Work/Projects/Web/src</code></pre>\n\n <p>\n You also can remove directories from the stack beyond the top directory, using popd with a numeric argument. The command:\n </p>\n<pre class=\" language-bash\"><code>$ popd +N</code></pre>\n\n <p>\n removes the directory in position N from the stack, counting down from the top. A negative argument (-N) counts up from the bottom of the stack instead. Counting begins at zero, so popd +1 removes the second directory from the top:\n </p>\n<pre class=\" language-bash\"><code>$ dirs\n/var/www/html /etc/apache2 /etc/ssl/certs\n~/Work/Projects/Web/src\n$ popd +1\n/var/www/html /etc/ssl/certs ~/Work/Projects/Web/src\n$ popd +2\n/var/www/html /etc/ssl/certs</code></pre>",
"author": {
"name": "Finecloud"
},
"tags": [
"shell",
"linux",
"bash"
],
"date_published": "2023-12-10T13:52:14+01:00",
"date_modified": "2023-12-11T07:36:08+01:00"
},
{
"id": "https://www.finecloud.ch/microservices.html",
"url": "https://www.finecloud.ch/microservices.html",
"title": "Microservices",
"summary": "This Post is a summary of the famous Article about Microservices: https://martinfowler.com/articles/microservices.html The text discusses the concept of \"Microservice Architecture,\" which is an approach to designing software applications as a suite of independently deployable services. It highlights that there is no precise definition but outlines…",
"content_html": "\n <p>\n This Post is a summary of the famous Article about Microservices: https://martinfowler.com/articles/microservices.html<br>\n </p>\n\n <h2 id=\"a-definition-of-this-new-architectural-termlessbrgreater\">\n a definition of this new architectural term<br>\n </h2>\n\n <p>\n The text discusses the concept of \"Microservice Architecture,\" which is an approach to designing software applications as a suite of independently deployable services. It highlights that there is no precise definition but outlines common characteristics such as organization around business capabilities, automated deployment, decentralized control of languages and data, and the use of lightweight communication mechanisms like HTTP. Microservices are contrasted with monolithic architecture, where applications are built as a single unit. The text emphasizes that microservices provide advantages like independent deployment, scalability, and modular structure, making it increasingly appealing for building enterprise applications. The microservice style is not claimed to be innovative but is considered beneficial for software development.<br>\n </p>\n\n <h2 id=\"componentization-via-services\">\n Componentization via Services\n </h2>\n\n <p>\n The text discusses the evolution of component-based software development in the software industry. It highlights the distinction between libraries and services as components, with a focus on microservice architectures. The main point is that components, in this context, are units of software that are independently replaceable and upgradeable. The text also explains that services, as out-of-process components, offer advantages in terms of independent deployability and explicit component interfaces. However, it acknowledges that using services can have downsides, such as increased overhead for remote calls and challenges in changing the allocation of responsibilities between components. The text concludes by noting that services can consist of multiple processes that are developed and deployed together.\n </p>\n\n <h2 id=\"organized-around-business-capabilities\">\n Organized around Business Capabilities\n </h2>\n\n <p>\n The text mentions how companies like comparethemarket.com organize themselves using cross-functional teams responsible for building and operating individual services. The text also touches upon Conway's Law, emphasizing that an organization's system design mirrors its communication structure.\n </p>\n\n <p>\n The key point is the contrast between the traditional approach of splitting teams based on technology layers (UI, server-side, database) and the microservices approach, which focuses on dividing services around business capabilities. Microservices encourage cross-functional teams with expertise in user experience, database, and project management. The text suggests that large monolithic applications can also benefit from modularization based on business capabilities but cautions against excessive complexity and recommends maintaining clear team boundaries, which is facilitated by the more explicit separation in service components.\n </p>\n\n <h2 id=\"products-not-projects\">\n Products not Projects\n </h2>\n\n <p>\n The text discusses the difference in development approaches between traditional project-based models and the microservices approach. In the traditional model, software development is seen as a project with a defined end, after which it's handed over to a maintenance organization. Microservice proponents advocate for teams to own a product throughout its entire lifecycle, emphasizing the \"you build, you run it\" philosophy popularized by Amazon.<br><br>This approach encourages developers to be responsible for their software in production, fostering closer interaction with how it behaves and its users. The text highlights that this product-oriented mentality aligns with the focus on business capabilities, emphasizing an ongoing relationship where software continuously enhances business capabilities.<br><br>It also notes that while this approach can be applied to monolithic applications, the smaller granularity of services in microservices makes it easier to establish personal relationships between service developers and their users.\n </p>\n\n <h2 id=\"smart-endpoints-and-dumb-pipes\">\n Smart endpoints and dumb pipes\n </h2>\n\n <p>\n The text starts by mentioning the traditional approach, exemplified by Enterprise Service Bus (ESB), where significant intelligence is embedded in the communication mechanism itself, allowing for sophisticated message routing, choreography, and transformation.<br><br>In contrast, the microservices community prefers a different approach: \"smart endpoints and dumb pipes.\" Microservices are designed to be highly decoupled and cohesive, with each service owning its domain logic. These services act as filters, receiving requests, applying logic, and producing responses. They utilize simple RESTish protocols and emphasize two common protocols: HTTP request-response with resource APIs and lightweight messaging. The principles of the World Wide Web and Unix underlie these protocols.<br><br>The text also highlights that, in microservices, the infrastructure used for messaging is typically simple and serves as a message router only, with the intelligence residing in the end points. The key challenge in transitioning from a monolithic architecture to microservices is changing the communication pattern. The text advises against a naive conversion to remote procedure calls (RPC) as it can lead to inefficient and \"chatty\" communications, advocating for a coarser-grained approach instead.\n </p>\n\n <h2 id=\"decentralized-governance\">\n Decentralized Governance\n </h2>\n\n <p>\n The text highlights the limitations of centralized governance, such as the tendency to standardize on single technology platforms. In contrast, microservices allow for a more flexible approach, enabling teams to choose the right tools and technologies for specific components.<br><br>Microservice teams focus on producing practical tools and sharing them with other developers, often following open-source practices. This approach encourages flexibility in solving similar problems while still valuing service contracts. The text mentions patterns like Tolerant Reader and Consumer-Driven Contracts that help service contracts evolve independently, with tools enabling automated contract verification during the build process.<br><br>Furthermore, the text discusses the \"build it / run it\" ethos popularized by Amazon, where development teams are responsible for operating the software they build, emphasizing the decentralization of responsibility. This approach, exemplified by companies like Netflix, fosters a focus on code quality and contrasts sharply with traditional centralized governance models.\n </p>\n\n <h2 id=\"decentralized-data-management\">\n Decentralized Data Management\n </h2>\n\n <p>\n The text points out that decentralized data management leads to differences in the conceptual models of systems, particularly when integrating across a large enterprise. This divergence in views can even occur within applications, especially when they are divided into separate components, which can be understood using the concept of Bounded Context from Domain-Driven Design.\n </p>\n\n <p>\n Microservices further decentralize data storage decisions by allowing each service to manage its own database, known as Polyglot Persistence. This contrasts with the monolithic approach of a single logical database for persistent data.<br><br>In terms of data updates, traditional monolithic applications often use transactions to guarantee consistency when updating multiple resources. However, microservices prioritize transactionless coordination between services due to the challenges of implementing distributed transactions. This approach acknowledges that consistency may be eventual and addresses problems with compensating operations.<br><br>The text also highlights that managing inconsistencies aligns with business practices where businesses often tolerate a degree of inconsistency to respond quickly to demand, with the ability to reverse processes to address mistakes. This trade-off is considered worthwhile as long as the cost of fixing errors is lower than the cost of lost business under greater consistency.\n </p>\n\n <h2 id=\"infrastructure-automation\">\n Infrastructure Automation\n </h2>\n\n <p>\n The text points out that teams building microservices often have experience with Continuous Delivery and Continuous Integration, both of which heavily rely on infrastructure automation.<br><br>The text highlights that infrastructure automation plays a crucial role in building confidence in software by running automated tests and automating deployment to different environments. It mentions that once the path to production for a monolithic application is automated, deploying more applications becomes less daunting. The goal of Continuous Delivery is to make deployment a routine and uneventful process.\n </p>\n\n <p>\n The text also acknowledges that while the deployment process may not differ significantly between monolithic applications and microservices, the operational landscape for each can be notably distinct, suggesting that infrastructure automation is key to managing microservices effectively in production.\n </p>\n\n <h2 id=\"design-for-failure\">\n Design for failure\n </h2>\n\n <p>\n The text points out that using services as components means applications need to be resilient and capable of handling service failures. Unlike monolithic designs, microservices introduce complexity in managing failures gracefully. To address this, microservice teams place a strong emphasis on monitoring and detecting failures in real-time.<br><br>The text mentions Netflix's \"Simian Army,\" which intentionally induces service and datacenter failures during the working day to test the application's resilience and monitoring capabilities. While monolithic architectures can also have sophisticated monitoring, it's less common.<br><br>Microservices require the ability to quickly detect and, if possible, automatically restore service. They rely on real-time monitoring, checking both architectural and business-relevant metrics. Semantic monitoring helps spot issues, especially in a microservices architecture where choreography and event collaboration can lead to emergent behavior, which may not always be desirable.<br><br>The text concludes that microservice teams expect to have sophisticated monitoring and logging setups for each individual service, including dashboards for status, operational and business metrics, and details on circuit breaker status, throughput, and latency. Transparency and quick detection of failures are critical in a microservices environment.\n </p>\n\n <h2 id=\"evolutionary-design\">\n Evolutionary Design\n </h2>\n\n <p>\n Microservice practitioners often come from an evolutionary design background and view service decomposition as a tool to enable application developers to control changes without slowing down the development process.<br><br>The key principle behind microservices is the notion of independent replacement and upgradeability. This means looking for points in the application where components can be rewritten without affecting their collaborators. Some microservice groups take this a step further by expecting that many services will be replaced rather than evolved in the long term.<br><br>The text provides examples of applications that started as monoliths but evolved in a microservice direction. These microservices are particularly useful for adding temporary features or services that are discarded after a short period, such as specialized pages for sporting events.<br><br>It emphasizes the importance of modular design based on the pattern of change, where components that change together should be in the same module. Microservices allow for more granular release planning, as changes only require redeploying the specific service(s) that were modified. However, this introduces the challenge of ensuring that changes to one service do not break its consumers, and the text suggests that versioning should be a last resort, with services designed to be tolerant of changes in their suppliers.\n </p>\n\n <h2 id=\"are-microservices-the-future\">\n Are Microservices the Future?\n </h2>\n\n <p>\n The concept of microservices is a promising architectural style for enterprise applications but the text emphasizes that it's still too early to make definitive judgments about its long-term impact. Several well-known companies, including Amazon, Netflix, The Guardian, and others, have adopted microservices. However, the text acknowledges that the full consequences of architectural decisions may take several years to become evident.<br><br>It highlights some challenges and potential concerns associated with microservices, such as the difficulty of defining service boundaries, the increased complexity in coordinating interface changes, and the risk of moving complexity from within a component to the connections between components. Additionally, the success of microservices can be influenced by team skill, and it remains to be seen how less skillful teams would fare with this approach.<br><br>The text suggests a reasonable argument of starting with a monolith and splitting it into microservices when necessary, while maintaining modularity from the beginning. It concludes with cautious optimism, acknowledging that the microservices style holds promise, but the ultimate outcomes will depend on how well it addresses these challenges in practice.\n </p>",
"author": {
"name": "Finecloud"
},
"tags": [
"software development",
"microservices"
],
"date_published": "2023-10-28T14:08:02+02:00",
"date_modified": "2023-10-28T14:08:12+02:00"
},
{
"id": "https://www.finecloud.ch/the-concept-of-api-contracts.html",
"url": "https://www.finecloud.ch/the-concept-of-api-contracts.html",
"title": "The Concept of API Contracts",
"summary": "What is it about? We define an API contract as a formal agreement between a software provider and a consumer that abstractly communicates how to interact with each other. This contract defines how API providers and consumers interact, what data exchanges looks like, and how…",
"content_html": "\n <h2 id=\"what-is-it-about\">\n What is it about?\n </h2>\n\n <p>\n We define an API contract as a formal agreement between a software provider and a consumer that abstractly communicates how to interact with each other. This contract defines how API providers and consumers interact, what data exchanges looks like, and how to communicate success and failure cases.<br><br>The provider and consumers do not have to share the same programming language, only the same API contracts. Lets imagine that we need to design a API for a Family Cash Card Web Application. Let’s assume that currently there's one contract between the Cash Card service and all services using it. Below is an example of that first API contract.\n </p>\n<pre class=\" language-json\"><code>Request\n URI: /cashcards/{id}\n HTTP Verb: GET\n Body: None\n\nResponse:\n HTTP Status:\n 200 OK if the user is authorized and the Cash Card was successfully retrieved\n 403 UNAUTHORIZED if the user is unauthenticated or unauthorized\n 404 NOT FOUND if the user is authenticated and authorized but the Cash Card cannot be found\n Response Body Type: JSON\n Example Response Body:\n {\n \"id\": 99,\n \"amount\": 123.45\n }</code></pre>\n\n <h2 id=\"why-are-api-contracts-important\">\n Why Are API Contracts Important?\n </h2>\n\n <p>\n API contracts are important because they communicate the behavior of a REST API. They provide specific details about the data being serialized (or deserialized) for each command and parameter being exchanged. The API contracts are written in such a way that can be easily translated into API provider and consumer functionality, and corresponding automated tests.\n </p>",
"author": {
"name": "Finecloud"
},
"tags": [
"software development",
"api"
],
"date_published": "2023-09-23T13:52:33+02:00",
"date_modified": "2023-09-23T13:54:08+02:00"
}
]
}