Opensource.com https://opensource.com/ en How to rename a branch, delete a branch, and find the author of a branch in Git https://opensource.com/article/22/5/git-branch-rename-delete-find-author <span class="field field--name-title field--type-string field--label-hidden">How to rename a branch, delete a branch, and find the author of a branch in Git</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/users/agantony" class="username">Agil Antony</a></span> <span class="field field--name-created field--type-created field--label-hidden">Fri, 05/20/2022 - 03:00</span> <div data-drupal-selector="rate-node-70026" class="rate-widget-thumbs-up" title="Register or Login to like."> <div class="rate-thumbs-up-btn-up vote-pending">3 readers like this</div> <div class="rate-score">3 readers like this</div> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>One of Git's primary strengths is its ability to "fork" work into different branches.</p> <p>If you're the only person using a repository, the benefits are modest, but once you start working with many other contributors, branching is essential. Git's branching mechanism allows multiple people to work on a project, and even on the same file, at the same time. Users can introduce different features, independent of one another, and then merge the changes back to a main branch later. A branch created specifically for one purpose, such as adding a new feature or fixing a known bug, is sometimes called <i>a topic branch</i>.</p> <p>Once you start working with branches, it's helpful to know how to manage them. Here are the most common tasks developers do with Git branches in the real world.</p> <p></p><div class="embedded-resource-list callout-float-right"> <div class="field field--name-title field--type-string field--label-hidden field__item">More on Git</div> <div class="field field--name-links field--type-link field--label-hidden field__items"> <div class="field__item"><a href="https://opensource.com/resources/what-is-git?intcmp=7013a000002CxqLAAS">What is Git?</a></div> <div class="field__item"><a href="https://opensource.com/downloads/cheat-sheet-git?intcmp=7013a000002CxqLAAS">Git cheat sheet</a></div> <div class="field__item"><a href="https://opensource.com/downloads/cheat-sheet-markdown?intcmp=7013a000002CxqLAAS">Markdown cheat sheet</a></div> <div class="field__item"><a href="https://opensource.com/tags/git?intcmp=7013a000002CxqLAAS">New Git articles</a></div> </div> </div> <h2>Rename a branch using Git</h2> <p>Renaming a topic branch is useful if you have named a branch incorrectly or you want to use the same branch to switch between different bugs or tasks after merging the content into the main branch.</p> <h3>Rename a local branch</h3> <p>1. Rename the local branch:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git branch</span> <span class="re5">-m</span> <span class="sy0">&lt;</span>old_branch_name<span class="sy0">&gt;</span> <span class="sy0">&lt;</span>new_branch_name<span class="sy0">&gt;</span></code></span></pre><p>Of course, this only renames <i>your</i> copy of the branch. If the branch exists on the remote Git server, continue to the next steps.</p> <p>2. Push the new branch to create a new remote branch:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git push</span> origin <span class="sy0">&lt;</span>new_branch_name<span class="sy0">&gt;</span></code></span></pre><p>3. Delete the old remote branch:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git push</span> origin <span class="re5">-d</span> <span class="re5">-f</span> <span class="sy0">&lt;</span>old_branch_name<span class="sy0">&gt;</span></code></span></pre><h3>Rename the current branch</h3> <p>When the branch you want to rename is your current branch, you don't need to specify the existing branch name.</p> <p>1. Rename the current branch:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git branch</span> <span class="re5">-m</span> <span class="sy0">&lt;</span>new_branch_name<span class="sy0">&gt;</span></code></span></pre><p>2. Push the new branch to create a new remote branch:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git push</span> origin <span class="sy0">&lt;</span>new_branch_name<span class="sy0">&gt;</span></code></span></pre><p>3. Delete the old remote branch:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git push</span> origin <span class="re5">-d</span> <span class="re5">-f</span> <span class="sy0">&lt;</span>old_branch_name<span class="sy0">&gt;</span></code></span></pre><h2>Delete local and remote branches using Git</h2> <p>As part of good repository hygiene, it's often recommended that you delete a branch after ensuring you have merged the content into the main branch.</p> <h3>Delete a local branch</h3> <p>Deleting a local branch only deletes the copy of that branch that exists on your system. If the branch has already been pushed to the remote repository, it remains available to everyone working with the repo.</p> <p>1. Checkout the central branch of your repository (such as <i>main</i> or <i>master</i>):</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git checkout</span> <span class="sy0">&lt;</span>central_branch_name<span class="sy0">&gt;</span></code></span></pre><p>2. List all the branches (local as well as remote):</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git branch</span> <span class="re5">-a</span></code></span></pre><p>3. Delete the local branch:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git branch</span> <span class="re5">-d</span> <span class="sy0">&lt;</span>name_of_the_branch<span class="sy0">&gt;</span></code></span></pre><p>To remove all your local topic branches and retain only the <em>main</em> branch:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git branch</span> <span class="sy0">|</span> <span class="kw2">grep</span> <span class="re5">-v</span> main <span class="sy0">|</span> <span class="kw2">xargs</span> <span class="kw2">git branch</span> <span class="re5">-d</span></code></span></pre><h3>Delete a remote branch</h3> <p>Deleting a remote branch only deletes the copy of that branch that exists on the remote server. Should you decide that you didn't want to delete the branch after all, you can re-push it to the remote, such as GitHub, as long as you still have your local copy.</p> <p>1. Checkout the central branch of your repository (usually <i>main </i>or <i>master</i>):</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git checkout</span> <span class="sy0">&lt;</span>central_branch_name<span class="sy0">&gt;</span></code></span></pre><p>2. List all branches (local as well as remote):</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git branch</span> <span class="re5">-a</span></code></span></pre><p>3. Delete the remote branch:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git push</span> origin <span class="re5">-d</span> <span class="sy0">&lt;</span>name_of_the_branch<span class="sy0">&gt;</span></code></span></pre><h2>Find the author of a remote topic branch using Git</h2> <p>If you are the repository manager, you might need to do this so you can inform the author of an unused branch that it should be deleted.</p> <p>1. Checkout the central branch of your repository (such as <i>main</i> or <i>master</i>):</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git checkout</span> <span class="sy0">&lt;</span>central_branch_name<span class="sy0">&gt;</span></code></span></pre><p>2. Delete branch references to remote branches that do not exist:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git remote</span> <span class="kw2">prune</span> origin</code></span></pre><p>3. List the author of all the remote topic branches in the repository, using the <code>--format</code> option along with special selectors (in this example, <code>%(authorname)</code> and <code>%(refname)</code> for author and branch name) to print just the information you want:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">git for-each-ref</span> <span class="re5">--sort</span>=authordate <span class="re5">--format</span>=<span class="st_h">'%(authorname) %(refname)'</span> refs<span class="sy0">/</span>remotes</code></span></pre><p>Example output:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">tux  refs<span class="sy0">/</span>remotes<span class="sy0">/</span>origin<span class="sy0">/</span>dev<br /> agil refs<span class="sy0">/</span>remotes<span class="sy0">/</span>origin<span class="sy0">/</span>main</div></div></pre><p>You can add further formatting, including color coding and string manipulation, for easier readability:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ <span class="kw2">git for-each-ref</span> <span class="re5">--sort</span>=authordate \<br /> <span class="re5">--format</span>=<span class="st_h">'%(color:cyan)%(authordate:format:%m/%d/%Y %I:%M %p)%(align:25,left)%(color:yellow) %(authorname)%(end)%(color:reset)%(refname:strip=3)'</span> \<br /> refs<span class="sy0">/</span>remotes</div></div></pre><p>Example output:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">01<span class="sy0">/</span><span class="nu0">16</span><span class="sy0">/</span><span class="nu0">2019</span> 03:<span class="nu0">18</span> PM tux      dev<br /> 05<span class="sy0">/</span><span class="nu0">15</span><span class="sy0">/</span><span class="nu0">2022</span> <span class="nu0">10</span>:<span class="nu0">35</span> PM agil     main</div></div></pre><p>You can use grep to get the author of a specific remote topic branch:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ <span class="kw2">git for-each-ref</span> <span class="re5">--sort</span>=authordate \<br /> <span class="re5">--format</span>=<span class="st_h">'%(authorname) %(refname)'</span> \<br /> refs<span class="sy0">/</span>remotes <span class="sy0">|</span> <span class="kw2">grep</span> <span class="sy0">&lt;</span>topic_branch_name<span class="sy0">&gt;</span></div></div></pre><h2>Get good at branching</h2> <p>There are nuances to how Git branching works depending on the point at which you want to fork the code base, how the repository maintainer manages branches, squashing, rebasing, and so on. Here are three articles for further reading on this topic:</p> <ul> <li><a href="https://opensource.com/article/22/4/git-branches">Explaining Git branches with a LEGO analogy</a>, by Seth Kenlon</li> <li><a href="https://opensource.com/article/22/4/git-push">My guide to using the Git push command safely</a>, by Noaa Barki</li> <li><a href="https://opensource.com/article/18/5/git-branching">A guide to Git branching</a>, by Kedar Vijay Kulkarni</li> </ul> </div> <div class="clearfix text-formatted field field--name-field-article-subhead field--type-text-long field--label-hidden field__item"><p>Become an expert at the most common Git tasks for managing local and remote branches.</p> </div> <div class="field field--name-field-lead-image field--type-entity-reference field--label-hidden field__item"><article class="media media--type-image media--view-mode-caption"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="/sites/default/files/tree-branches.jpg" width="640" height="425" alt="tree branches" title="tree branches" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>Image by <a href="https://www.flickr.com/photos/22244945@N00/3353319002" target="_blank">Erik Fitzpatrick</a>. <a href="https://creativecommons.org/licenses/by-sa/4.0/" target="_blank">CC BY-SA 4.0</a></p> </div> </article> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/tags/git" hreflang="en">Git</a></div> </div> <div class="hidden field field--name-field-listicle-title field--type-string field--label-hidden field__item">What to read next</div> <div class="field field--name-field-default-license field--type-list-string field--label-hidden field__item"><a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"> <img alt="Creative Commons License" src="/themes/osdc/assets/img/cc-by-sa-4.png" title="This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License." /></a>This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.</div> <section id='comments' class="field field--name-field-comments field--type-comment field--label-hidden comment-wrapper"> <div class="comments__count"> <div class="login"><a href="/user/register?absolute=1">Register</a> or <a href="/user/login?current=/rss.xml&amp;absolute=1">Login</a> to post a comment.</div> </div> </section> Fri, 20 May 2022 07:00:00 +0000 Agil Antony 70026 at https://opensource.com A programmer's guide to GNU C Compiler https://opensource.com/article/22/5/gnu-c-compiler <span class="field field--name-title field--type-string field--label-hidden">A programmer&#039;s guide to GNU C Compiler</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/users/jayashree-huttanagoudar" class="username">Jayashree Hutt…</a></span> <span class="field field--name-created field--type-created field--label-hidden">Fri, 05/20/2022 - 03:00</span> <div data-drupal-selector="rate-node-70018" class="rate-widget-thumbs-up" title="Register or Login to like."> <div class="rate-thumbs-up-btn-up vote-pending">2 readers like this</div> <div class="rate-score">2 readers like this</div> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p><meta charset="utf-8" /></p> <p>C is a well-known programming language, popular with experienced and new programmers alike. Source code written in C uses standard English terms, so it's considered human-readable. However, computers only understand binary code. To convert code into machine language, you use a tool called a <em>compiler</em>.</p> <p>A very common compiler is GCC (GNU C Compiler). The compilation process involves several intermediate steps and adjacent tools.</p> <h2>Install GCC</h2> <p>To confirm whether GCC is already installed on your system, use the <code>gcc</code> command:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">gcc</span> <span class="re5">--version</span></code></span></pre><p>If necessary, install GCC using your packaging manager. On Fedora-based systems, use <code>dnf</code>:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">sudo</span> dnf <span class="kw2">install</span> <span class="kw2">gcc</span> libgcc</code></span></pre><p>On Debian-based systems, use <code>apt</code>:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">sudo</span> apt <span class="kw2">install</span> build-essential</code></span></pre><p>After installation, if you want to check where GCC is installed, then use:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">whereis</span> <span class="kw2">gcc</span></code></span></pre><h2>Simple C program using GCC</h2> <p>Here's a simple C program to demonstrate how to compile code using GCC. Open your favorite text editor and paste in this code:</p> <pre> <div class="geshifilter"><div class="c geshifilter-c"><span class="co1">// hellogcc.c</span><br /> <span class="co2">#include &lt;stdio.h&gt;</span><br />  <br /> <span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span><br />         <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">(</span><span class="st0">"Hello, GCC!<span class="es1">\n</span>"</span><span class="br0">)</span><span class="sy0">;</span><br /> <span class="kw1">return</span> <span class="nu0">0</span><span class="sy0">;</span><br /> <span class="br0">}</span></div></div></pre><p>Save the file as <code>hellogcc.c</code> and then compile it:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ <span class="kw2">ls</span><br /> hellogcc.c<br /> <br /> $ <span class="kw2">gcc</span> hellogcc.c<br /> <br /> $ <span class="kw2">ls</span> <span class="re5">-1</span><br /> a.out<br /> hellogcc.c</div></div></pre><p>As you can see, <code>a.out</code> is the default executable generated as a result of compilation. To see the output of your newly-compiled application, just run it as you would any local binary:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ .<span class="sy0">/</span>a.out<br /> Hello, GCC<span class="sy0">!</span></div></div></pre><h2>Name the output file</h2> <p>The filename <code>a.out</code> isn't very descriptive, so if you want to give a specific name to your executable file, you can use the <code>-o</code> option:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ <span class="kw2">gcc</span> <span class="re5">-o</span> hellogcc hellogcc.c<br /> <br /> $ <span class="kw2">ls</span><br /> a.out  hellogcc  hellogcc.c<br /> <br /> $ .<span class="sy0">/</span>hellogcc<br /> Hello, GCC<span class="sy0">!</span></div></div></pre><p>This option is useful when developing a large application that needs to compile multiple C source files.</p> <p></p><div class="embedded-resource-list callout-float-right"> <div class="field field--name-title field--type-string field--label-hidden field__item">Programming and development</div> <div class="field field--name-links field--type-link field--label-hidden field__items"> <div class="field__item"><a href="https://developers.redhat.com/?intcmp=7016000000127cYAAQ">Red Hat Developers Blog</a></div> <div class="field__item"><a href="https://opensource.com/downloads/cheat-sheets?intcmp=7016000000127cYAAQ">Programming cheat sheets</a></div> <div class="field__item"><a href="https://www.redhat.com/en/services/training/learning-subscription?intcmp=7016000000127cYAAQ">Try for free: Red Hat Learning Subscription</a></div> <div class="field__item"><a href="https://opensource.com/downloads/bash-programming-guide?intcmp=7016000000127cYAAQ">eBook: An introduction to programming with Bash</a></div> <div class="field__item"><a href="https://developers.redhat.com/cheat-sheets/bash-shell-cheat-sheet?intcmp=7016000000127cYAAQ">Bash shell scripting cheat sheet</a></div> <div class="field__item"><a href="https://developers.redhat.com/e-books/modernizing-enterprise-java?intcmp=7016000000127cYAAQ">eBook: Modernizing Enterprise Java</a></div> </div> </div> <h2>Intermediate steps in GCC compilation</h2> <p>There are actually four steps to compiling, even though GCC performs them automatically in simple use-cases.</p> <ol> <li>Pre-Processing: The GNU C Preprocessor (<code>cpp</code>) parses the headers (<strong>#include</strong> statements), expands macros (<strong>#define</strong> statements), and generates an intermediate file such as <code>hellogcc.i</code> with expanded source code.</li> <li>Compilation: During this stage, the compiler converts pre-processed source code into assembly code for a specific CPU architecture. The resulting assembly file is named with a <code>.s</code> extension, such as <code>hellogcc.s</code> in this example.</li> <li>Assembly: The assembler (<code>as</code>) converts the assembly code into machine code in an object file, such as <code>hellogcc.o</code>.</li> <li>Linking: The linker (<code>ld</code>) links the object code with the library code to produce an executable file, such as <code>hellogcc</code>.</li> </ol> <p>When running GCC, use the <code>-v</code> option to see each step in detail.</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span><span class="kw2">gcc</span> <span class="re5">-v</span> <span class="re5">-o</span> hellogcc hellogcc.c</code></span></pre><article class="align-center media media--type-image media--view-mode-default"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="https://opensource.com/sites/default/files/2022-05/compiler-flowchart.png" width="651" height="275" alt="Compiler flowchart" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>(Jayashree Huttanagoudar, CC BY-SA 4.0)</p> </div> </article> <h2>Manually compile code</h2> <p>It can be useful to experience each step of compilation because, under some circumstances, you don't need GCC to go through all the steps.</p> <p>First, delete the files generated by GCC in the current folder, except the source file.</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ <span class="kw2">rm</span> a.out hellogcc.o<br /> <br /> $ <span class="kw2">ls</span><br /> hellogcc.c</div></div></pre><h3>Pre-processor</h3> <p>First, start the pre-processor, redirecting its output to <code>hellogcc.i</code>:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ <span class="kw2">cpp</span> hellogcc.c <span class="sy0">&gt;</span> hellogcc.i<br /> <br /> $ <span class="kw2">ls</span><br /> hellogcc.c  hellogcc.i</div></div></pre><p>Take a look at the output file and notice how the pre-processor has included the headers and expanded the macros.</p> <h3>Compiler</h3> <p>Now you can compile the code into assembly. Use the <code>-S</code> option to set GCC just to produce assembly code.</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ <span class="kw2">gcc</span> <span class="re5">-S</span> hellogcc.i<br /> <br /> $ <span class="kw2">ls</span><br /> hellogcc.c  hellogcc.i  hellogcc.s<br /> <br /> $ <span class="kw2">cat</span> hellogcc.s</div></div></pre><p>Take a look at the assembly code to see what's been generated.</p> <h3>Assembly</h3> <p>Use the assembly code you've just generated to create an object file:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ <span class="kw2">as</span> <span class="re5">-o</span> hellogcc.o hellogcc.s<br /> <br /> $ <span class="kw2">ls</span><br /> hellogcc.c  hellogcc.i  hellogcc.o  hellogcc.s</div></div></pre><h3>Linking</h3> <p>To produce an executable file, you must link the object file to the libraries it depends on. This isn't quite as easy as the previous steps, but it's educational:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ <span class="kw2">ld</span> <span class="re5">-o</span> hellogcc hellogcc.o<br /> ld: warning: cannot <span class="kw2">find</span> entry symbol _start; defaulting to 0000000000401000<br /> ld: hellogcc.o: <span class="kw1">in</span> <span class="kw1">function</span> <span class="sy0">`</span>main<span class="sy0">`</span>:<br /> hellogcc.c:<span class="br0">(</span>.text+0xa<span class="br0">)</span>: undefined reference to <span class="sy0">`</span>puts<span class="st_h">'</span></div></div></pre><p>An error referencing an<code> undefined puts</code> occurs after the linker is done looking at the <code>libc.so</code> library. You must find suitable linker options to link the required libraries to resolve this. This is no small feat, and it's dependent on how your system is laid out.</p> <p>When linking, you must link code to core runtime (CRT) objects, a set of subroutines that help binary executables launch. The linker also needs to know where to find important system libraries, including libc and libgcc, notably within special start and end instructions. These instructions can be delimited by the <code>--start-group</code> and <code>--end-group</code> options or using paths to <code>crtbegin.o</code> and <code>crtend.o</code>.</p> <p>This example uses paths as they appear on a RHEL 8 install, so you may need to adapt the paths depending on your system.</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ <span class="kw2">ld</span> <span class="re5">-dynamic-linker</span> \<br /> <span class="sy0">/</span>lib64<span class="sy0">/</span>ld-linux-x86-<span class="nu0">64</span>.so.2 \<br /> <span class="re5">-o</span> hello \<br /> <span class="sy0">/</span>usr<span class="sy0">/</span>lib64<span class="sy0">/</span>crt1.o <span class="sy0">/</span>usr<span class="sy0">/</span>lib64<span class="sy0">/</span>crti.o \<br /> <span class="re5">--start-group</span> \<br /> -L<span class="sy0">/</span>usr<span class="sy0">/</span>lib<span class="sy0">/</span>gcc<span class="sy0">/</span>x86_64-redhat-linux<span class="sy0">/</span><span class="nu0">8</span> \<br /> -L<span class="sy0">/</span>usr<span class="sy0">/</span>lib64 -L<span class="sy0">/</span>lib64 hello.o \<br /> <span class="re5">-lgcc</span> \<br /> <span class="re5">--as-needed</span> -lgcc_s \<br /> <span class="re5">--no-as-needed</span> <span class="re5">-lc</span> <span class="re5">-lgcc</span> \<br /> <span class="re5">--end-group</span><br /> <span class="sy0">/</span>usr<span class="sy0">/</span>lib64<span class="sy0">/</span>crtn.o </div></div></pre><p>The same linker procedure on Slackware uses a different set of paths, but you can see the similarity in the process:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ <span class="kw2">ld</span> <span class="re5">-static</span> <span class="re5">-o</span> hello \<br /> -L<span class="sy0">/</span>usr<span class="sy0">/</span>lib64<span class="sy0">/</span>gcc<span class="sy0">/</span>x86_64-slackware-linux<span class="sy0">/</span>11.2.0<span class="sy0">/</span> \<br /> <span class="sy0">/</span>usr<span class="sy0">/</span>lib64<span class="sy0">/</span>crt1.o <span class="sy0">/</span>usr<span class="sy0">/</span>lib64<span class="sy0">/</span>crti.o \<br /> hello.o <span class="sy0">/</span>usr<span class="sy0">/</span>lib64<span class="sy0">/</span>crtn.o \<br /> <span class="re5">--start-group</span> <span class="re5">-lc</span> <span class="re5">-lgcc</span> -lgcc_eh \<br /> <span class="re5">--end-group</span></div></div></pre><p>Now run the resulting executable:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ .<span class="sy0">/</span>hello<br /> Hello, GCC<span class="sy0">!</span></div></div></pre><h2>Some helpful utilities</h2> <p>Below are a few utilities that help examine the file type, symbol table, and the libraries linked with the executable.</p> <p>Use the <code>file</code> utility to determine the type of file:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ <span class="kw2">file</span> hellogcc.c<br /> hellogcc.c: C <span class="kw3">source</span>, ASCII text<br /> <br /> $ <span class="kw2">file</span> hellogcc.o<br /> hellogcc.o: ELF <span class="nu0">64</span>-bit LSB relocatable, x86-<span class="nu0">64</span>, version <span class="nu0">1</span> <span class="br0">(</span>SYSV<span class="br0">)</span>, not stripped<br /> <br /> $ <span class="kw2">file</span> hellogcc<br /> hellogcc: ELF <span class="nu0">64</span>-bit LSB executable, x86-<span class="nu0">64</span>, version <span class="nu0">1</span> <span class="br0">(</span>SYSV<span class="br0">)</span>, dynamically linked, interpreter <span class="sy0">/</span>lib64<span class="sy0">/</span>ld-linux-x86-<span class="nu0">64</span>.so.2, BuildID<span class="br0">[</span>sha1<span class="br0">]</span>=bb76b241d7d00871806e9fa5e814fee276d5bd1a, <span class="kw1">for</span> GNU<span class="sy0">/</span>Linux 3.2.0, not stripped</div></div></pre><p>The use the <code>nm</code> utility to list symbol tables for object files:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ <span class="kw2">nm</span> hellogcc.o<br /> 0000000000000000 T main<br />                           U puts</div></div></pre><p>Use the <code>ldd</code> utility to list dynamic link libraries:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ <span class="kw2">ldd</span> hellogcc<br /> linux-vdso.so.1 <span class="br0">(</span>0x00007ffe3bdd7000<span class="br0">)</span><br /> libc.so.6 =<span class="sy0">&gt;</span> <span class="sy0">/</span>lib64<span class="sy0">/</span>libc.so.6 <span class="br0">(</span>0x00007f223395e000<span class="br0">)</span><br /> <span class="sy0">/</span>lib64<span class="sy0">/</span>ld-linux-x86-<span class="nu0">64</span>.so.2 <span class="br0">(</span>0x00007f2233b7e000<span class="br0">)</span></div></div></pre><h2>Wrap up</h2> <p>In this article, you learned the various intermediate steps in GCC compilation and the utilities to examine the file type, symbol table, and libraries linked with an executable. The next time you use GCC, you'll understand the steps it takes to produce a binary file for you, and when something goes wrong, you know how to step through the process to resolve problems.</p> </div> <div class="clearfix text-formatted field field--name-field-article-subhead field--type-text-long field--label-hidden field__item"><p>Get a behind-the-scenes look at the steps it takes to produce a binary file so that when something goes wrong, you know how to step through the process to resolve problems.</p> </div> <div class="field field--name-field-lead-image field--type-entity-reference field--label-hidden field__item"><article class="media media--type-image media--view-mode-caption"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="/sites/default/files/lead-images/build_structure_tech_program_code_construction.png" width="520" height="292" alt="GitHub launches Open Source Friday " title="GitHub launches Open Source Friday " loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>Opensource.com</p> </div> </article> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/tags/programming" hreflang="en">Programming</a></div> </div> <div class="hidden field field--name-field-listicle-title field--type-string field--label-hidden field__item">What to read next</div> <div class="field field--name-field-default-license field--type-list-string field--label-hidden field__item"><a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"> <img alt="Creative Commons License" src="/themes/osdc/assets/img/cc-by-sa-4.png" title="This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License." /></a>This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.</div> <section id='comments' class="field field--name-field-comments field--type-comment field--label-hidden comment-wrapper"> <div class="comments__count"> <div class="login"><a href="/user/register?absolute=1">Register</a> or <a href="/user/login?current=/rss.xml&amp;absolute=1">Login</a> to post a comment.</div> </div> </section> Fri, 20 May 2022 07:00:00 +0000 Jayashree Huttanagoudar 70018 at https://opensource.com https://opensource.com/article/22/5/gnu-c-compiler#comments Use this open source screen reader on Windows https://opensource.com/article/22/5/open-source-screen-reader-windows-nvda <span class="field field--name-title field--type-string field--label-hidden">Use this open source screen reader on Windows</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/users/petercheer" class="username">Peter Cheer</a></span> <span class="field field--name-created field--type-created field--label-hidden">Thu, 05/19/2022 - 03:00</span> <div data-drupal-selector="rate-node-70019" class="rate-widget-thumbs-up" title="Register or Login to like."> <div class="rate-thumbs-up-btn-up vote-pending">3 readers like this</div> <div class="rate-score">3 readers like this</div> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Screen readers are a specialized area of assistive technology software that reads and then speaks the content of a computer screen. People with no sight at all are just a fraction of those with visual impairments, and screen reader software can help all groups. Screen readers are mostly specific to an operating system, and they're used by people with visual impairments and accessibility trainers, as well as developers and accessibility consultants wanting to test how accessible a website or application is.</p> <p></p><div class="embedded-resource-list callout-float-right"> <div class="field field--name-title field--type-string field--label-hidden field__item">More great content</div> <div class="field field--name-links field--type-link field--label-hidden field__items"> <div class="field__item"><a href="https://www.redhat.com/en/services/training/rh024-red-hat-linux-technical-overview?intcmp=7016000000127cYAAQ">Free online course: RHEL technical overview</a></div> <div class="field__item"><a href="https://developers.redhat.com/cheat-sheets/advanced-linux-commands/?intcmp=7016000000127cYAAQ">Learn advanced Linux commands</a></div> <div class="field__item"><a href="https://opensource.com/downloads/cheat-sheets?intcmp=7016000000127cYAAQ">Download cheat sheets</a></div> <div class="field__item"><a href="https://opensource.com/tags/linux?intcmp=7016000000127cYAAQ">Find an open source alternative</a></div> <div class="field__item"><a href="https://opensource.com/resources?intcmp=7016000000127cYAAQ">Explore open source resources</a></div> </div> </div> <h2 id="nvda">How to use the NVDA screen reader</h2> <p>The <a href="https://webaim.org/projects" target="_blank">WebAIM screen reader user surveys</a> began in 2009 and ran to 2021. In the first survey, the most common screen reader used was JAWS at 74%. It is a commercial product for Microsoft Windows, and the long-time market leader. NVDA, then a relatively new open source screen reader for Windows came in at just 8%. Fast forward to 2021 and JAWS comes in with 53.7% with NVDA at 30.7%.</p> <p>You can download the latest release of NVDA from the <a href="https://www.nvaccess.org" target="_blank">NVAccess website</a>. Why do I use NVDA and recommend it to my MS Windows using clients? Well, it is open source, fast, powerful, easy to install, supports a wide variety of languages, can be run as a portable application, has a large user base, and there is a regular release cycle for new versions.</p> <p>NVDA has been translated into fifty-five languages and is used in one-hundred and seventy-five different countries. There is also an active developer community with their own <a href="https://addons.nvda-project.org/index.en.html" target="_blank">Community Add-ons website</a>. Any add-ons you choose to install will depend on your needs and there are a lot to choose from, including extensions for common video conferencing platforms.</p> <p>Like all screen readers, there are a lot of key combinations to learn with NVDA. Using any screen reader proficiently takes training and practice.</p> <article class="align-center media media--type-image media--view-mode-default"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="https://opensource.com/sites/default/files/2022-05/nvda1.png" width="747" height="421" alt="Image of NVDA welcome screen" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>(Peter Cheer, CC BY-SA 4.0)</p> </div> </article> <p>Teaching NVDA to people familiar with computers and who have keyboard skills is not too difficult. Teaching basic computer skills (without the mouse, touch pad, and keyboard skills) and working with NVDA to a complete beginner is far more of a challenge. Individual learning styles and preferences differ. In addition, people may not need to learn how to do everything if all that they want to do is browse the web and use email. A good source of links to NVDA tutorials and resources is <a href="http://www.accessibilitycentral.net/" target="_blank">Accessibility Central</a>.</p> <p>It becomes easier once you have mastered operating NVDA with keyboard commands, but there is also a menu-driven system for many configuration tasks.</p> <article class="align-center media media--type-image media--view-mode-default"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="https://opensource.com/sites/default/files/2022-05/nvda2.png" width="728" height="324" alt="Image of NVDA menu" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>(Peter Cheer, CC BY-SA 4.0)</p> </div> </article> <h2 id="test-for-accessibility">Test for accessibility</h2> <p>The inaccessibility of some websites to screen reader users has been a problem for many years, and still is despite disability equality legislation like the Americans with Disabilities Act (ADA). An excellent use for NVDA in the sighted community is for website accessibility testing. NVDA is free to download, and by running a portable version, website developers don't even need to install it. Run NVDA, turn off your monitor or close your eyes, and see how well you can navigate a website or application.</p> <p>NVDA can also be used for testing when working through the (often ignored) task of properly <a href="https://www.youtube.com/watch?v=rRzWRk6cXIE" target="_blank">tagging a PDF document for accessibility</a>.</p> <p>There are several guides that concentrate on using NVDA for accessibility testing. I can recommend <a href="https://www.unimelb.edu.au/accessibility/tools/testing-web-pages-with-nvda" target="_blank">Testing Web Pages with NVDA</a> and Using <a href="https://webaim.org/articles/nvda" target="_blank">NVDA to Evaluate Web Accessibility</a>.</p> </div> <div class="clearfix text-formatted field field--name-field-article-subhead field--type-text-long field--label-hidden field__item"><p>In honor of Global Accessibility Awareness Day, learn about the NVDA open source screen reader and how you can get involved to improve accessibility for all web users.</p> </div> <div class="field field--name-field-lead-image field--type-entity-reference field--label-hidden field__item"><article class="media media--type-image media--view-mode-caption"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="/sites/default/files/lead-images/wfh_work_home_laptop_work.png" width="1041" height="584" alt="Working from home at a laptop" title="Working from home at a laptop" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>Opensource.com</p> </div> </article> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/tags/accessibility" hreflang="en">Accessibility</a></div> <div class="field__item"><a href="/tags/windows" hreflang="en">Windows</a></div> </div> <div class="hidden field field--name-field-listicle-title field--type-string field--label-hidden field__item">What to read next</div> <div class="field field--name-field-default-license field--type-list-string field--label-hidden field__item"><a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"> <img alt="Creative Commons License" src="/themes/osdc/assets/img/cc-by-sa-4.png" title="This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License." /></a>This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.</div> <section id='comments' class="field field--name-field-comments field--type-comment field--label-hidden comment-wrapper"> <div class="comments__count"> <div class="login"><a href="/user/register?absolute=1">Register</a> or <a href="/user/login?current=/rss.xml&amp;absolute=1">Login</a> to post a comment.</div> </div> </section> Thu, 19 May 2022 07:00:00 +0000 Peter Cheer 70019 at https://opensource.com https://opensource.com/article/22/5/open-source-screen-reader-windows-nvda#comments Near zero marginal cost societies and the impact on why we work https://opensource.com/open-organization/22/5/near-zero-marginal-cost-societies-and-impact-why-we-work <span class="field field--name-title field--type-string field--label-hidden">Near zero marginal cost societies and the impact on why we work</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/users/ron-mcfarland" class="username">Ron McFarland</a></span> <span class="field field--name-created field--type-created field--label-hidden">Thu, 05/19/2022 - 03:00</span> <div data-drupal-selector="rate-node-70014" class="rate-widget-thumbs-up" title="Register or Login to like."> <div class="rate-thumbs-up-btn-up vote-pending">3 readers like this</div> <div class="rate-score">3 readers like this</div> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>I have read Jeremy Rifkin's book <a href="https://www.goodreads.com/book/show/18594514-the-zero-marginal-cost-society" target="_blank">The Zero Marginal Cost Society: The Internet of Things, the Collaborative Commons, and the Eclipse of Capitalism</a>, which has a strong connection to open organization principles, particularly community building. Rifkin also writes about the future of green energy generation and energy use in logistics. This is the second of three articles in this series. In my previous article, I examined the Collaborative Commons. In this article, I look at its impact on energy production and supply.</p> <p>Within the next 25 years, Rifkin believes most of our energy for home heating, running appliances, powering businesses, driving vehicles, and operating the whole economy will be nearly free with on-site power solar, wind and geothermal energy generation. This is starting already, through both individual and micropower plants. The payback is around two to eight years.</p> <p>What would be the best organizational structure to manage nearly free green energy? Furthermore, through an intelligent communication and energy system, an organization could generate business anywhere in the world, and share energy across a continental energy internet. On top of that, it could produce and sell goods at a fraction charged by global manufacturing giants.</p> <h2 id="the-internet-of-things-iot-is-on-the-way">The Internet of Things is on the way</h2> <p>According to Rifkin, the Internet of Things (IoT) will connect every machine, business, residence, and vehicle in an intelligent network that consists of not just a communications internet like now, but in the future an energy internet, and a logistics internet. They will all be embedded in a single operating system. Energy use will be completely monitored. Rifkin believes that within 10 years, many smart energy meters will be in use (by 2025). All this investment will reduce at least 10% of the waste in the current industrial system.</p> <p>All this will be possible with the reduction of costs of sensors and actuators embedded in devices. Radio-frequency identification (RFID) chip prices have fallen by 40% in around 2012-2013. Micro-electromechanical system (MEMS), including gyroscopes, accelerometers, and pressure sensors, have also dropped by 80-90% in price over the past five years (up to 2015 when this book was published).</p> <p>This will increase device connections, to as many as 1,000 connections on one person's devices, appliances, and facilities. This connection is what young people love, total inclusion in a global virtual public square to share everything. They thrive on transparency, collaboration, and inclusivity with care taken to an appropriate level of privacy. So, you can see, the time is right for the growth of a Collaborative Commons in society.</p> <p></p><div class="embedded-resource-list callout-float-right"> <div class="field field--name-title field--type-string field--label-hidden field__item">Open Organization resources</div> <div class="field field--name-links field--type-link field--label-hidden field__items"> <div class="field__item"><a href="https://theopenorganization.org/?intcmp=7016000000127cYAAQ">Download resources</a></div> <div class="field__item"><a href="https://www.theopenorganization.community/?intcmp=7016000000127cYAAQ">Join the community</a></div> <div class="field__item"><a href="https://opensource.com/open-organization/resources/open-org-definition?intcmp=7016000000127cYAAQ">What is an open organization?</a></div> <div class="field__item"><a href="https://opensource.com/open-organization/resources/open-org-maturity-model?intcmp=7016000000127cYAAQ">How open is your organization?</a></div> </div> </div> <h2 id="exponential-curve">Exponential curve</h2> <p>Question: Would you accept US $1,000,000 today or US $1.00 that doubled every day for 30 days? (In 30 days it will be US $536,870,912. That is 500 times more). In 31 days, over one billion. Exponential growth is deceptively fast. That is how fast costs are coming down according to Rifkin. This will turn the entire fossil fuel industry investments into stranded assets. We should be planning for the Collaborative Commons using all open organization principles now, as the situation will be ideal for them very soon.</p> <h2 id="next-is-the-near-free-energy-internet">Next, a free energy internet</h2> <p>At this point in time there is free information for learning if you look for it. The next step is free energy (solar, wind, geothermal, biomass, hydro). After initial investments (research, development, deployment), Rifkin forecasts that unit costs will rapidly come down. The information internet and near zero-cost renewables will merge into the energy internet, powering homes, offices, and factories. Ideally, there will be energy that's loaded into buildings and partially stored in the form of hydrogen, distributed over a green-electricity internet, and connected to plug-in, zero-emission transportation. The development of renewable energy establishes a five pillar mechanism that will allow billions of people to share energy at near zero marginal cost in the IoT world</p> <h2 id="solar-energy">Solar energy</h2> <p>If you start collecting energy from the sun, facilities only need to obtain 00.1% of the sun's energy that reaches the Earth. That would provide six times the energy we now use globally.</p> <p><a href="https://us.sunpower.com" target="_blank">SunPower Corporation</a> is one company doing that. It supports making homes energy producers. The price of solar photovoltaic (PV) cells tends to drop by 20% for every doubling of industry capacity. Solar panels are increasing, and their ability to capture more energy per panel is increasing. Expect to see the development of thinner solar panels, and paper thin solar sheets. Eventually there will be solar energy paint and solar energy windows in the future.</p> <p>When too much energy is generated, it must be sold elsewhere or stored in batteries or used to produce hydrogen. This technology is coming to the market and will dominate it very soon. With these technologies alone, electricity is on the way to have zero marginal cost.</p> <h2 id="wind-power-generation">Wind power generation</h2> <p>Wind power has been growing exponentially since the 1990s, and is now nearing fossil fuel and nuclear power generation levels (as of 2015). With the lowering costs of windmill production, installation, and maintenance, wind power is doubling every 2-½ years. With the increase of solar and wind energy sources, governments do not need to subsidize them with tariffs any longer.</p> <p><a href="https://www.energywatchgroup.org" target="_blank">Energy Watch Group</a> is tracking this. According to Rifkin geothermal energy, biomass, and wave and tidal power will likely reach their own exponential takeoff stage within the next decade. He believes that all this will happen in the first half of the twenty-first century. If this capacity doubles eight more times, by 2028, 80% of all energy generation will be from these renewables.</p> <h2 id="the-collaborative-age-will-soon-be-here">The collaborative age will soon be here</h2> <p>With all the above developments, society's working and living environment are changing. According to the <a href="https://www.forbes.com/sites/ricoheurope/2020/02/06/moving-from-the-information-age-to-the-collaboration-age" target="_blank">collaborative age</a>: "This means ensuring that people can collaborate on tasks without friction. That humans and machines work seamlessly together. And automation — machine to machine collaboration — will be crucial. Those businesses that get these elements right will be able to boost employee satisfaction and attract the best talent. They will reduce costs by automating mundane tasks and by requiring a smaller office footprint. The social impact-focused organizations that <a href="http://www.zythepsary.com/author/admin" target="_blank">Laura Hilliger</a> and <a href="https://ch.linkedin.com/in/heatherleson" target="_blank">Heather Leson</a> write about how to take advantage of this new age.</p> <h2 id="making-the-transition">Making the transition</h2> <p>It sounds good, but how do businesses transition from the information age to the collaboration age? One area will be in decentralized production through 3D printing technology (<a href="https://en.wikipedia.org/wiki/3D_printing" target="_blank">additive manufacturing</a>, not cutting away and creating waste).</p> <p>Instead of shipping goods, in the future, software will be shipped for many items to be manufactured locally, avoiding all shipping costs and making manufacturing become on-site near where the market need is. Locally, newly developed molten plastics, molten metal, or other feedstock inside a printer will be used for fabrication. This will give one 3D printer the ability to produce tens of thousands of products (like jewelry, airplane parts, and human prostheses).</p> <h2 id="centralized-manufacturing-vs-local-production-which-rifkin-projects-will-come">Centralized manufacturing vs local production which Rifkin projects will come</h2> <p>Rifkin believes lower marketing costs are possible by using the IoT economy and using global internet marketing sites at almost zero marginal cost.</p> <ol> <li> <p>There is little human involvement in the local 3D process (giving the name "infofacture" rather than manufacture. They ship the information required for local manufacturing, like downloading music today. It is just code that you receive.</p> </li> <li> <p>The code for 3D printing is open source, so people can learn and improve designs, becoming further prosumers in a wide range of items (no intellectual-property protection barriers). This will lead to exponential growth over the next several decades, offering more complicated products at lower prices and near zero marginal cost.</p> </li> <li> <p>There is great waste with subtraction processes (current manufacturing processes) producing great waste with each process. (1/10 the materials required. This material could be developed from subatomic particles that are available anywhere in the local environment, like recycled glass, fabrics, ceramics, and stainless steel. Composite-fiber concrete could be extruded form-free and be strong enough for building construction walls [probably available in two decades].)</p> </li> <li> <p>3D printing processes have fewer moving parts and less spare parts. Therefore, expensive retooling and changeover delays will be less extensive.</p> </li> <li> <p>Materials will be more durable, recyclable, and less polluting.</p> </li> <li> <p>Local distributed production, through IoT, will spread globally at an exponential rate with little shipping cost and less use of energy.</p> </li> </ol> <p>Rifkin cites Etsy as an example of this model. You can find things you are interested in, and have them produced locally using their network. They sell the code, and you can have it supplied in your area.</p> <p>Rifkin feels that in the future, small and medium sized 3D businesses, infofacturing more sophisticated products, will likely cluster in local technology parks to establish an optimum lateral scale (another form of community development). Here are current examples:</p> <ol> <li> <p><a href="https://reprap.org/wiki/RepRap" target="_blank">RepRap</a>: This is a manufacturing machine that can produce itself and all its parts.</p> </li> <li> <p><a href="https://www.thingiverse.com" target="_blank">Thingiverse</a> The largest 3D printing community. They share under the General Public Licenses (GPL) and Creative Commons Licenses.</p> </li> <li> <p>Fab Lab: Open source peer-to-peer learning in manufacturing. It is being provided to local, distant communities in developing countries.</p> </li> <li> <p>3D Printed automobiles (<a href="https://www.popularmechanics.com/cars/a9645/urbee-2-the-3d-prinhttps://www.popularmechanics.com/cars/a9645/urbee-2-the-3d-printed-car-that-will-drive-across-the-country-16119485" target="_blank">Urbee vehicle</a>) is already being tested.</p> </li> <li> <p><a href="https://phys.org/news/2013-02-kor-ecologic-urbee-car-d.html" target="_blank">KOR EcoLogic</a> has an urban electric vehicle.</p> </li> </ol> <h2 id="the-makers-movement-principles">The makers' movement principles</h2> <p>Here are the principles that these ecosystems follow:</p> <ol> <li> <p>They use open source shared software.</p> </li> <li> <p>They promote a collaborative learning culture.</p> </li> <li> <p>They believe that it will build a self-sufficient community.</p> </li> <li> <p>They are committed to sustainable production practices.</p> </li> </ol> <h2 id="the-future-of-work-and-collaborative-commons">The future of work and collaborative commons</h2> <p>When technology replaces workers, capital investments replace labor investments. In 2007, companies used 6 times more computers and software than 20 years before, doubling the amount of capital used per hour of employee work. The robot workforce is on the rise. China, India, Mexico, and other emerging nations are learning that the cheapest workers in the world are not as cheap, efficient, or productive as the information technology, robotics, and artificial intelligence that replaces them.</p> <p>Going back to Rifkin, the first industrial revolution ended slave and serf labor. The second industrial revolution will dramatically shrink agricultural and craft labor. Rifkin believes the third industrial revolution will be a decline in mass wage labor in the manufacturing, service industries, and salaried professional labor in large parts of the knowledge sector.</p> <p>Rifkin believes that an abundance, zero marginal cost economy, will change our notion of economic processes. He thinks the old paradigm of owners and workers, sellers and consumers will break down. Consumers will start producing for themselves (and a few others), eliminating their distinction. Prosumers will increasingly be able to produce, consume, and share their own goods and services with one another on the Collaborative Commons at diminishing marginal costs approaching zero, bringing to the fore new ways of organizing economic life beyond the traditional capitalist market mode.</p> <p>Rifkin forecasts that in the future, greater importance will be placed on the Collaborative Commons and be as important as hard work was in the market economy (one's ability to cooperate and collaborate as opposed to just working hard). The amassing of social capital will become as valued as the accumulation of market capital. Attachment to community and the search for transcendence and meaning comes to define the measure of one's material wealth. All the <a href="https://theopenorganization.org/definition/open-organization-definition/" target="_blank">open organization principles</a> we write about will be exponentially more important in the future.</p> <p>The IoT will free human beings from the capitalist market economy to pursue nonmaterial shared interests on the collaborative commons. Many — but not all — of our basic material needs will be met for nearly free in a near zero marginal cost society. It will be abundance over scarcity.</p> <h2 id="prosumer-and-the-entry-of-the-smart-economy">Prosumer and the entry of the smart economy</h2> <p>Rifkin writes that as capitalist economies step aside in some global commodities, in the collaborative commons, sellers and buyers will give way to prosumers, property rights will make room for open source sharing, ownership will be less important than access, markets will be superseded by networks, and the marginal cost of supplying information, generating energy, manufacturing products, and teaching students will become nearly zero.</p> <h2 id="internet-of-energy-is-on-the-way">Internet of energy is on the way</h2> <p>Financing of the IoT will not come from wealthy capitalists and corporate shareholders, but from hundreds of millions of consumers and taxpayers. No one owns the internet. It is only in operation because a set of agreed-upon protocols were established that allows computer networks to communicate with each other. It is a virtual public square for all who pay for a connection to use it. Next comes distributed renewable energies that will be distributed in the same way. Supported by feed-in tariffs and other fund-raising methods, governments will pay for the initial research, but after that fixed investment, the public will be able to connect and use it freely. Once underway, governmental centralized operations will move to distributed ownership. The <a href="https://www.epri.com" target="_blank">Electric Power Research Institute</a> (EPRI), is studying how to build a national energy internet over the next 20 years.</p> <p>This is not just supplying electricity. Every device in every building will be equipped with sensors and software that connect to the IoT, feeding real-time information on electricity use to both the on-site prosumer and the rest of the network. The entire network will know how much electricity is being used by every appliance at any moment — thermostats, washing machines, dishwashers, televisions, hair dryers, toasters, ovens, and refrigerators.</p> <p>This is not happening in the future, but now. It is not just being considered but being done now. <a href="https://www.intwineconnect.com" target="_blank">Intwine Energy</a> can supply the above process now. The issue is getting it into the greater global population. A group of young <a href="https://www.cleanweb.co" target="_blank">social entrepreneurs</a> are now using social media to mobilize their peers to create, operate and use the energy internet.</p> <h2 id="a-new-world-of-abundance-beyond-our-needs">A new world of abundance beyond our needs</h2> <p>Rifkin thinks society has to start envisioning an entire different living environment. Imagine a world in which you can just give away things you once had to pay for, or had to sell at a profit. No one charges us for each internet connected phone call. He believes these give-away goods need not be covered by governments, like telecommunication, roads, bridges, public schools or hospitals. They need not be considered totally private property to be sold and bought, either. These goods have to be supplied in communities with rules, responsibilities and joint benefits (information, energy, local production, and online education). Not governed by the markets or governments, but by networked commons because of the <a href="https://blogs.pugetsound.edu/econ/2018/03/09/comedy-of-the-commons" target="_blank">tragedy of the commons</a>. It governs and enforces distributed, peer-to-peer, laterally scaled economic activities.</p> <p>Rifkin feels the Collaborative Commons as a governing body is extremely important. This is where local (project) leadership comes in. The goals, processes, tasks and responsibilities must be successfully executed, after they have been decided and agreed on. Furthermore, "social capital" is a major factor. It must be widely introduced and deepened in quality. Community exchange, interaction and contribution is far more important than selling to distant capital markets. If that is the case, our <a href="https://github.com/open-organization/open-org-leaders-manual/raw/master/second-edition/open_org_leaders_manual_2_3.pdf" target="_blank">open organization leadership</a> will be extremely important.</p> <h2 id="the-public-square-versus-private-ownership">The public square versus private ownership</h2> <p>"The public square at — least before the Internet, is where we communicate, socialize, revel in each other's company, establish communal bonds, and create social capital and trust. These are all indispensable elements for a nurturing community." Historically, Japanese villages were built like that to survive natural, economic and political disasters like earthquakes and typhoons. They put common interests over self-interests This is what the open organization principle of community is all about.</p> <p>The right to be included, to have access to one another, which is the right to participate together, is a fundamental right of all. Private property, the right to enclose, own, and exclude is merely a qualified deviation from the norm. For some reason, having massive private property rights have gained in importance in more recent modern times. This will all be reversed in the years ahead according to Rifkin.</p> <p>Rifkin writes that the world will move to these commons:</p> <ol> <li> <p>Public square commons</p> </li> <li> <p>Land commons</p> </li> <li> <p>Virtual commons</p> </li> <li> <p>Knowledge commons (languages, cultures, human knowledge and wisdom)</p> </li> <li> <p>Energy Commons</p> </li> <li> <p>Electromagnetic spectrum commons</p> </li> <li> <p>Ocean commons</p> </li> <li> <p>Fresh water commons</p> </li> <li> <p>Atmosphere commons</p> </li> <li> <p>Biosphere commons.</p> </li> </ol> <p>The past 200 years of capitalism, the enclosed, privatized, and commodification of the market must be put under review. How would they be most effective in a transparent, non-hierarchical and collaborative culture? It comes down to two views, the capitalist (I own it. It is mine, and you can't use it) and the collaborationist (This is for everyone to use, and there are rules and guidelines to use it, so everyone can get their fair share). Today's cooperatives are good at this, like the <a href="https://www.ica.coop/en" target="_blank">International Co-operative Alliance (ICA)</a>. Cooperatives have to generate motivation for the greater community good, and that motivation must be greater than any profit motive. That is their challenge but this not new, as one in seven people on the earth are in some kind of cooperative now.</p> <p>As I've presented in this article, the IoT will become our working and living environment. Also, energy costs are projected to go to near zero. With those changes, community collaboration and cooperation will become ever more important over hard work. In the last part of this series I will look at Collaborative Commons in logistics and other economic activity.</p> </div> <div class="clearfix text-formatted field field--name-field-article-subhead field--type-text-long field--label-hidden field__item"><p>As the IoT becomes our working and living environment, energy costs will come closer to zero and community collaboration will be critical.</p> </div> <div class="field field--name-field-lead-image field--type-entity-reference field--label-hidden field__item"><article class="media media--type-image media--view-mode-caption"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="/sites/default/files/lead-images/BUSINESS_networks.png" width="520" height="292" alt="A network of people" title="A network of people" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>Opensource.com</p> </div> </article> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/tags/open-organization" hreflang="en">The Open Organization</a></div> </div> <div class="field field--name-field-listicle-title field--type-string field--label-hidden field__item">What to read next</div> <div class="field field--name-field-listicles field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/open-organization/22/5/zero-marginal-cost-collaborative-commons" hreflang="en">How collaborative commons and open organization principles align</a></div> </div> <div class="field field--name-field-default-license field--type-list-string field--label-hidden field__item"><a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"> <img alt="Creative Commons License" src="/themes/osdc/assets/img/cc-by-sa-4.png" title="This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License." /></a>This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.</div> <section id='comments' class="field field--name-field-comments field--type-comment field--label-hidden comment-wrapper"> <div class="comments__count"> <div class="login"><a href="/user/register?absolute=1">Register</a> or <a href="/user/login?current=/rss.xml&amp;absolute=1">Login</a> to post a comment.</div> </div> </section> Thu, 19 May 2022 07:00:00 +0000 Ron McFarland 70014 at https://opensource.com https://opensource.com/open-organization/22/5/near-zero-marginal-cost-societies-and-impact-why-we-work#comments A guide to Pipy, a programmable network proxy for cloud https://opensource.com/article/22/5/pipy-programmable-network-proxy-cloud <span class="field field--name-title field--type-string field--label-hidden">A guide to Pipy, a programmable network proxy for cloud</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/users/alinaqvi" class="username">Ali Naqvi</a></span> <span class="field field--name-created field--type-created field--label-hidden">Wed, 05/18/2022 - 03:00</span> <div data-drupal-selector="rate-node-70024" class="rate-widget-thumbs-up" title="Register or Login to like."> <div class="rate-thumbs-up-btn-up vote-pending">2 readers like this</div> <div class="rate-score">2 readers like this</div> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Pipy is an open source, cloud-native, network stream processor. It is modular by design and can create a high-performance network proxy. It's written in C++ and is built on top of the Asio asynchronous I/O library. Pipy is ideal for a variety of use cases ranging from edge routers, load balancers, proxy solutions, API gateways, static HTTP servers, service mesh sidecars, and more.</p> <p>Pipy also comes with built-in JavaScript support through PipyJS. PipyJS is highly customizable and predictable in performance, with no garbage collection overhead. Currently, PipyJS is part of the Pipy code base, but it has no dependency on it and in the future it may be moved to a standalone package.</p> <h2 id="quick-start">Pipy quick start guide</h2> <p>You can run the production version of Pipy using Podman or Docker with one of the tutorial scripts provided on the official Pipy Git repository. The Pipy container image can be configured with a few environment variables:</p> <ul> <li> <p><code>PIPY_CONFIG_FILE=&lt;/path/to/config-file&gt;</code> sets the location of the Pipy configuration file.</p> </li> <li> <p><code>PIPY_SPAWN=n</code> sets the number of Pipy instances you want to start, where <code>n</code> is the number of instances. This is a zero-based index, so 0 represents 1 instance. For example, use <code>PIPY_SPAWN=3</code> for 4 instances.</p> </li> </ul> <p>Start the Pipy server with this example script:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ docker run <span class="re5">--rm</span> <span class="re5">-e</span> <span class="re2">PIPY_CONFIG_FILE</span>=\<br /> https:<span class="sy0">//</span>raw.githubusercontent.com<span class="sy0">/</span>flomesh-io<span class="sy0">/</span>pipy<span class="sy0">/</span>main<span class="sy0">/</span>tutorial<span class="sy0">/</span>01-hello \<br /> <span class="re5">-e</span> <span class="re2">PIPY_SPAWN</span>=<span class="nu0">1</span> <span class="re5">-p</span> <span class="nu0">8080</span>:<span class="nu0">8080</span> flomesh<span class="sy0">/</span>pipy-pjs:latest</div></div></pre><p>You may notice that instead of a local file, this code provides a link to a remote Pipy script through the environment variable <code>PIPY_CONFIG_FILE</code>. Pipy is smart enough to handle that.</p> <p>For your reference, here are the contents of the file <code>tutorial/01-hello/hello.js</code>:</p> <pre> <div class="geshifilter"><div class="javascript geshifilter-javascript">pipy<span class="br0">(</span><span class="br0">)</span><br /> .<span class="me1">listen</span><span class="br0">(</span><span class="nu0">8080</span><span class="br0">)</span><br /> .<span class="me1">serveHTTP</span><span class="br0">(</span><br /> <span class="kw1">new</span> Message<span class="br0">(</span><span class="st0">'Hi, there!<span class="es0">\n</span>'</span><span class="br0">)</span><br /> <span class="br0">)</span></div></div></pre><p>This simple script defines one Port pipeline, which listens on port 8080 and returns "Hi, there!" for each HTTP request received on the listening port.</p> <p>As you've exposed local port 8080 with the docker run command, you can proceed with a test on the same port:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash"><span class="co4">$ </span>curl http:<span class="sy0">//</span>localhost:<span class="nu0">8080</span></div></div></pre><p>Executing the above command displays <code><strong>Hi, there!</strong></code> on the console.</p> <p>For learning, development, or debugging purposes it's recommended to proceed with the local installation (either build Pipy from sources or download a release for your OS) of Pipy, as it comes with an admin web console along with documentation and tutorials.</p> <p>Once installed locally, running <code>pipy</code> without any arguments starts the admin console on port 6060, but it can be configured to listen on the different port with the <code>--admin-port</code> option.</p> <article class="align-center media media--type-image media--view-mode-default"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="https://opensource.com/sites/default/files/2022-05/pipy1.png" width="972" height="771" alt="Pipy admin console listening on port 6060" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>(Ali Naqvi, CC BY-SA 40)</p> </div> </article> <p>To build Pipy from source, or to install a precompiled binary for your operating system, refer to README.md on the <a href="https://github.com/flomesh-io/pipy" target="_blank">Pipy</a> Git repository.</p> <p></p><div class="embedded-resource-list callout-float-right"> <div class="field field--name-title field--type-string field--label-hidden field__item">Explore the open source cloud</div> <div class="field field--name-links field--type-link field--label-hidden field__items"> <div class="field__item"><a href="https://www.redhat.com/en/services/training/do092-developing-cloud-native-applications-microservices-architectures?intcmp=7013a000002gp8aAAA">Free online course: Developing cloud-native applications with microservices</a></div> <div class="field__item"><a href="https://www.redhat.com/en/engage/managed-cloud-services-s-202202210207?intcmp=7013a000002gp8aAAA">eBook: Modernize your IT with managed cloud services</a></div> <div class="field__item"><a href="https://cloud.redhat.com/products/dedicated/?intcmp=7013a000002gp8aAAA">Try for 60 days: Red Hat OpenShift Dedicated</a></div> <div class="field__item"><a href="https://www.redhat.com/en/services/training/do080-deploying-containerized-applications-technical-overview?intcmp=7013a000002gp8aAAA">Free online course: Containers, Kubernetes and Red Hat OpenShift</a></div> <div class="field__item"><a href="https://www.redhat.com/en/topics/containers/what-is-kubernetes?intcmp=7013a000002gp8aAAA">What is Kubernetes?</a></div> <div class="field__item"><a href="https://www.redhat.com/en/topics/edge-computing?intcmp=7013a000002gp8aAAA">Understanding edge computing</a></div> <div class="field__item"><a href="https://www.redhat.com/architect/?intcmp=7013a000002gp8aAAA">Latest articles for IT architects</a></div> </div> </div> <h3 id="running-pipy-in-a-terminal">Running Pipy in a terminal</h3> <p>To start a Pipy proxy, run Pipy with a PipyJS script file, for example, the script in <code>tutorial/01-hello/hello.js</code> if you need a simple echo server that responds with the same message body received with every incoming request:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash"><span class="co4">$ </span>pipy tutorial<span class="sy0">/</span>01-hello<span class="sy0">/</span>hello.js</div></div></pre><p>Alternatively, while developing and debugging, one can start Pipy with a builtin web UI:</p> <pre> <span class="geshifilter"><code class="bash geshifilter-bash"><span class="co4">$ </span> pipy tutorial<span class="sy0">/</span>01-hello<span class="sy0">/</span>hello.js <span class="re5">--admin-port</span>=<span class="nu0">6060</span></code></span></pre><p>To see all command-line options, use the <code>--help</code> flag:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash"><span class="co4">$ </span> pipy <span class="re5">--help</span></div></div></pre><h2 id="pipy-is-a-stream-processor">Pipy is a stream processor</h2> <p>Pipy operates on network streams using an event-driven pipeline where it consumes the input stream, performs user-provided transformations, and outputs the stream. A pipy data stream takes raw data and abstracts it into an event. An event can belong to one of four categories:</p> <ul> <li><strong>Data</strong>: Network streams are composed of data bytes and come in chunks. Pipy abstracts out chunks into a Data event.</li> <li> <p><strong>MessageStart, MessageEnd, StreamEnd</strong>: These three non-data events work as markers, giving the raw byte streams high-level semantics for business logic to rely on.</p> </li> </ul> <h2 id="pipy-design">Pipy Design</h2> <p>The internal workings of Pipy are similar to <a href="https://opensource.com/article/19/4/interprocess-communication-linux-channels" target="_blank">Unix Pipelines</a> but unlike Unix pipelines, which deal with discreet bytes, Pipy deals with streams of events.</p> <p>Pipy processes incoming streams through a chain of filters, where each filter deals with general concerns like request logging, authentication, SSL offloading, request forwarding, and so on. Each filter reads from its input and writes to its output, with the output of one filter connected to the input of the next.</p> <h3 id="pipelines">Pipelines</h3> <p>A chain of filters is called a pipeline and Pipy categorizes pipelines in 3 different categories according to their input sources.</p> <ul> <li> <p><strong>Port pipeline:</strong> Reads in Data events from a network port, processes them, and then writes the result back to the same port. This is the most commonly used request and response model. For instance, when Pipy works like an HTTP server, the input to a Port pipeline is an HTTP request from the clients, and the output from the pipeline would be an HTTP response sent back to clients.</p> </li> <li> <p><strong>Timer pipeline:</strong> Gets a pair of MessageStart and MessageEnd events as its input periodically. Useful when <a href="https://en.wikipedia.org/wiki/Cron" target="_blank">Cron</a> <a href="https://en.wikipedia.org/wiki/Cron" target="_blank">job-like</a> functionality is required.</p> </li> <li> <p><strong>Sub-pipeline:</strong> Works in conjunction with a join filter, such as link, which takes in events from its predecessor pipeline, feeds them into a sub-pipeline for processing, reads back the output from the sub-pipeline, and then pumps it down to the next filter.</p> <p>The best way to look at sub-pipelines and join filters is to think of them as callees and callers of a subroutine in procedural programming. The input to the joint filter is the subroutine's parameters, the output from the joint filter is its return value.</p> <p>A root pipeline, such as Port or Timer, cannot be called from join filters.</p> <p>To get a list of builtin filters and their parameters:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$  pipy <span class="re5">--list-filters</span><br /> $  pipy <span class="re5">--help-filters</span></div></div></pre></li> </ul> <h3 id="context">Context</h3> <p>Another important notion in Pipy is that of contexts. A context is a set of variables attached to a pipeline. Every pipeline gets access to the same set of variables across a Pipy instance. In other words, contexts have the same shape. When you start a Pipy instance, the first thing you do is define the shape of the context by defining variable(s) and their initial values.</p> <p>Every root pipeline clones the initial context you define at the start. When a sub-pipeline starts, it either shares or clones its parent's context, depending on which joint filter you use. For instance, a link filter shares its parent's context while a demux filter clones it.</p> <p>To the scripts embedded in a pipeline, these context variables are their global variables, which means that these variables are always accessible to scripts from anywhere if they live in the same script file.</p> <p>This might seem odd to a seasoned programmer because global variables usually mean they are globally unique. You have only one set of these variables, whereas in Pipy we can have many sets of them (contexts) depending on how many root pipelines are open for incoming network connections and how many sub-pipelines clone their parents' contexts.</p> <h2 id="writing-a-network-proxy">Writing a Network Proxy</h2> <p>Suppose you're running separate instances of different services and you want to add a proxy to forward traffic to the relevant services based on the request URL path. This would give you the benefit of exposing a single URL and scaling your services in the back end without users having to remember a distinct service URL. In normal situations, your services would be running on different nodes and each service could have multiple instances running. In this example, assume you're running the services below, and want to distribute traffic to them based on the URI.</p> <ul> <li> <p>service-hi at <code>/hi/*</code> (127.0.0.1:8080, 127.0.0.1:8082)</p> </li> <li> <p>service-echo at <code>/echo</code> (127.0.0.1:8081)</p> </li> <li> <p>service-tell-ip at <code>/ip_/_*</code> (127.0.0.1:8082)</p> </li> </ul> <p>Pipy scripts are written in JavaScript, and you can use any text editor of your choice to edit them. Alternatively, if you have installed Pipy locally, you can use Pipy admin Web UI, which comes with syntax highlighting, auto-completion, hints, as well as the ability to run scripts, all from the same console.</p> <p>Start a Pipy instance, without any arguments, so the Pipy admin console launches on port 6060. Now open your favorite web browser and navigate to <a href="http://localhost:6060" target="_blank">[http://localhost:6060](http://localhost:6060/</a> to see the built-in Pipy Administration Web UI.</p> <article class="align-center media media--type-image media--view-mode-default"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="https://opensource.com/sites/default/files/2022-05/pipy2.png" width="972" height="771" alt="Built-in Pipy administration web UI" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>(Ali Naqvi, CC BY-SA 40)</p> </div> </article> <h2 id="create-a-pipy-program">Create a Pipy program</h2> <p>A good design practice is that code and configurations are separated. Pipy supports such modular design through its Plugins, which you can think of as JavaScript modules. That said, you store your configuration data in the config folder, and your coding logic in separate files under the plugins folder. The main proxy server script is stored in the root folder, the main proxy script (<code>proxy.js</code>) will include and combine the functionality defined in separate modules. In the end, your final folder structure is:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">├── config<br /> │ ├── balancer.json<br /> │ ├── proxy.json<br /> │ └── router.json<br /> ├── plugins<br /> │ ├── balancer.js<br /> │ ├── default.js<br /> │ └── router.js<br /> └── proxy.js</div></div></pre><p> </p> <p>      1.Click <strong>New Codebase</strong>, enter <code>/proxy</code> for the Codebase <em>name</em> in the dialog and then click <strong>Create</strong>.</p> <ol start="2"> <li> <p>Click the <strong>+</strong> button to add a new file. Enter <code>/config/proxy.json</code> for its filename and then click <strong>Create</strong>. This is the configuration file used to configure your proxy.</p> </li> <li> <p>You now see <code>proxy.json</code> listed under the config folder in the left pane. Click on the file to open it and add the configuration shown below and make sure you save your file by clicking the disk icon on the top panel.<br />  </p> <pre> <code class="language-json">{ "listen": 8000, "plugins": [ "plugins/router.js", "plugins/balancer.js", "plugins/default.js" ] }</code></pre></li> <li> <p>Repeat steps 2 and 3 to create another file, /config/router.json, to store route information. Enter this configuration data:</p> <pre> <code class="language-json">{ "routes": { "/hi/*": "service-hi", "/echo": "service-echo", "/ip/*": "service-tell-ip" } }</code></pre></li> <li> <p>Repeat steps 2 and 3 to create another file, /config/balancer.json to store your service-to-target map. Enter the following data:</p> <pre> <code class="language-json">{ "services": { "service-hi" : ["127.0.0.1:8080", "127.0.0.1:8082"], "service-echo" : ["127.0.0.1:8081"], "service-tell-ip" : ["127.0.0.1:8082"] } }</code></pre></li> <li> <p>Now it's time to write your very first Pipy script, which will be used as a default fallback when your server receives a request for which you don't have any target (an endpoint) configured. Create the file <code>/plugins/default.js</code>. The name here is just a convention and Pipy doesn't rely on names, so you can choose any name you like. The script will contain the code shown below, which returns the HTTP Status code 404 with a message of No handler found:<br />  </p> <pre> <div class="geshifilter"><div class="javascript geshifilter-javascript">pipy<span class="br0">(</span><span class="br0">)</span><br /> .<span class="me1">pipeline</span><span class="br0">(</span><span class="st0">'request'</span><span class="br0">)</span><br /> .<span class="me1">replaceMessage</span><span class="br0">(</span><br /> <span class="kw1">new</span> Message<span class="br0">(</span><span class="br0">{</span> status<span class="sy0">:</span> <span class="nu0">404</span> <span class="br0">}</span><span class="sy0">,</span> <span class="st0">'No handler found'</span><span class="br0">)</span><span class="br0">)</span></div></div></pre></li> </ol> <p>       7.Create the file <code>/plugins/router.js</code>, which stores your routing logic:</p> <pre> <div class="geshifilter"><div class="javascript geshifilter-javascript"><span class="br0">(</span>config <span class="sy0">=&gt;</span><br /> pipy<span class="br0">(</span><span class="br0">{</span><br /> _router<span class="sy0">:</span> <span class="kw1">new</span> algo.<span class="me1">URLRouter</span><span class="br0">(</span>config.<span class="me1">routes</span><span class="br0">)</span><span class="sy0">,</span> <span class="br0">}</span><span class="br0">)</span><br /> .<span class="kw5">export</span><span class="br0">(</span><span class="st0">'router'</span><span class="sy0">,</span> <span class="br0">{</span><br /> __serviceID<span class="sy0">:</span> <span class="st0">''</span><span class="sy0">,</span> <span class="br0">}</span><span class="br0">)</span><br /> .<span class="me1">pipeline</span><span class="br0">(</span><span class="st0">'request'</span><span class="br0">)</span><br /> .<span class="me1">handleMessageStart</span><span class="br0">(</span><br /> msg <span class="sy0">=&gt;</span> <span class="br0">(</span><br /> __serviceID <span class="sy0">=</span> _router.<span class="me1">find</span><span class="br0">(</span><br /> msg.<span class="me1">head</span>.<span class="me1">headers</span>.<span class="me1">host</span><span class="sy0">,</span><br /> msg.<span class="me1">head</span>.<span class="me1">path</span><span class="sy0">,</span> <span class="br0">)</span><br /> <span class="br0">)</span> <span class="br0">)</span><br /> <span class="br0">)</span><span class="br0">(</span>JSON.<span class="me1">decode</span><span class="br0">(</span>pipy.<span class="me1">load</span><span class="br0">(</span><span class="st0">'config/router.json'</span><span class="br0">)</span><span class="br0">)</span><span class="br0">)</span></div></div></pre><ol start="8"> <li> <p>Create the file <code>/plugins/balancer.js</code>, which stores your load balancing logic as a side-note. Pipy comes with multiple Load Balancing algorithms, but for simplicity, you're using the Round Robin algorithm here.</p> <pre> <div class="geshifilter"><div class="javascript geshifilter-javascript"><span class="br0">(</span>config <span class="sy0">=&gt;</span><br /> <br /> pipy<span class="br0">(</span><span class="br0">{</span><br />   _services<span class="sy0">:</span> <span class="br0">(</span><br />     <span class="kw4">Object</span>.<span class="me1">fromEntries</span><span class="br0">(</span><br />       <span class="kw4">Object</span>.<span class="me1">entries</span><span class="br0">(</span>config.<span class="me1">services</span><span class="br0">)</span>.<span class="me1">map</span><span class="br0">(</span><br />         <span class="br0">(</span><span class="br0">[</span>k<span class="sy0">,</span> v<span class="br0">]</span><span class="br0">)</span> <span class="sy0">=&gt;</span> <span class="br0">[</span><br />           k<span class="sy0">,</span> <span class="kw1">new</span> algo.<span class="me1">RoundRobinLoadBalancer</span><span class="br0">(</span>v<span class="br0">)</span><br />         <span class="br0">]</span><br />       <span class="br0">)</span><br />     <span class="br0">)</span><br />   <span class="br0">)</span><span class="sy0">,</span><br /> <br />   _balancer<span class="sy0">:</span> <span class="kw2">null</span><span class="sy0">,</span><br />   _balancerCache<span class="sy0">:</span> <span class="kw2">null</span><span class="sy0">,</span><br />   _target<span class="sy0">:</span> <span class="st0">''</span><span class="sy0">,</span><br /> <span class="br0">}</span><span class="br0">)</span><br /> <br /> .<span class="kw5">import</span><span class="br0">(</span><span class="br0">{</span><br />   __turnDown<span class="sy0">:</span> <span class="st0">'proxy'</span><span class="sy0">,</span><br />   __serviceID<span class="sy0">:</span> <span class="st0">'router'</span><span class="sy0">,</span><br /> <span class="br0">}</span><span class="br0">)</span><br /> <br /> .<span class="me1">pipeline</span><span class="br0">(</span><span class="st0">'session'</span><span class="br0">)</span><br />   .<span class="me1">handleStreamStart</span><span class="br0">(</span><br />     <span class="br0">(</span><span class="br0">)</span> <span class="sy0">=&gt;</span> <span class="br0">(</span><br />       _balancerCache <span class="sy0">=</span> <span class="kw1">new</span> algo.<span class="me1">Cache</span><span class="br0">(</span><br />         <span class="co1">// k is a balancer, v is a target</span><br />         <span class="br0">(</span>k  <span class="br0">)</span> <span class="sy0">=&gt;</span> k.<span class="me1">select</span><span class="br0">(</span><span class="br0">)</span><span class="sy0">,</span><br />         <span class="br0">(</span>k<span class="sy0">,</span>v<span class="br0">)</span> <span class="sy0">=&gt;</span> k.<span class="me1">deselect</span><span class="br0">(</span>v<span class="br0">)</span><span class="sy0">,</span><br />       <span class="br0">)</span><br />     <span class="br0">)</span><br />   <span class="br0">)</span><br />   .<span class="me1">handleStreamEnd</span><span class="br0">(</span><br />     <span class="br0">(</span><span class="br0">)</span> <span class="sy0">=&gt;</span> <span class="br0">(</span><br />       _balancerCache.<span class="me1">clear</span><span class="br0">(</span><span class="br0">)</span><br />     <span class="br0">)</span><br />   <span class="br0">)</span><br /> <br /> .<span class="me1">pipeline</span><span class="br0">(</span><span class="st0">'request'</span><span class="br0">)</span><br />   .<span class="me1">handleMessageStart</span><span class="br0">(</span><br />     <span class="br0">(</span><span class="br0">)</span> <span class="sy0">=&gt;</span> <span class="br0">(</span><br />       _balancer <span class="sy0">=</span> _services<span class="br0">[</span>__serviceID<span class="br0">]</span><span class="sy0">,</span><br />       _balancer <span class="sy0">&amp;&amp;</span> <span class="br0">(</span>_target <span class="sy0">=</span> _balancerCache.<span class="kw1">get</span><span class="br0">(</span>_balancer<span class="br0">)</span><span class="br0">)</span><span class="sy0">,</span><br />       _target <span class="sy0">&amp;&amp;</span> <span class="br0">(</span>__turnDown <span class="sy0">=</span> <span class="kw2">true</span><span class="br0">)</span><br />     <span class="br0">)</span><br />   <span class="br0">)</span><br />   .<span class="me1">link</span><span class="br0">(</span><br />     <span class="st0">'forward'</span><span class="sy0">,</span> <span class="br0">(</span><span class="br0">)</span> <span class="sy0">=&gt;</span> <span class="kw4">Boolean</span><span class="br0">(</span>_target<span class="br0">)</span><span class="sy0">,</span><br />     <span class="st0">''</span><br />   <span class="br0">)</span><br /> <br /> .<span class="me1">pipeline</span><span class="br0">(</span><span class="st0">'forward'</span><span class="br0">)</span><br />   .<span class="me1">muxHTTP</span><span class="br0">(</span><br />     <span class="st0">'connection'</span><span class="sy0">,</span><br />     <span class="br0">(</span><span class="br0">)</span> <span class="sy0">=&gt;</span> _target<br />   <span class="br0">)</span><br /> <br /> .<span class="me1">pipeline</span><span class="br0">(</span><span class="st0">'connection'</span><span class="br0">)</span><br />   .<span class="me1">connect</span><span class="br0">(</span><br />     <span class="br0">(</span><span class="br0">)</span> <span class="sy0">=&gt;</span> _target<br />   <span class="br0">)</span><br /> <br /> <span class="br0">)</span><span class="br0">(</span>JSON.<span class="me1">decode</span><span class="br0">(</span>pipy.<span class="me1">load</span><span class="br0">(</span><span class="st0">'config/balancer.json'</span><span class="br0">)</span><span class="br0">)</span><span class="br0">)</span></div></div></pre></li> <li> <p>Now write the entry point, or the proxy server script, to use the above plugins. Creating a new code base (step 1) creates a default <code>main.js</code> file as an entry point. You can use that as your main entry point, or if you prefer to go with a different name, feel free to delete <code>main.js</code> and create a new file with the name of your choice. For this example, delete it and create a new file named <code>/proxy.js</code>. Make sure you click the top flag icon to make it the main entry point, to ensure script execution is started when you hit the run button (the arrow icon on the right).</p> <pre> <div class="geshifilter"><div class="javascript geshifilter-javascript"><span class="br0">(</span>config <span class="sy0">=&gt;</span><br /> <br /> pipy<span class="br0">(</span><span class="br0">)</span><br /> <br /> .<span class="kw5">export</span><span class="br0">(</span><span class="st0">'proxy'</span><span class="sy0">,</span> <span class="br0">{</span><br />   __turnDown<span class="sy0">:</span> <span class="kw2">false</span><span class="sy0">,</span><br /> <span class="br0">}</span><span class="br0">)</span><br /> <br /> .<span class="me1">listen</span><span class="br0">(</span>config.<span class="me1">listen</span><span class="br0">)</span><br />   .<span class="me1">use</span><span class="br0">(</span>config.<span class="me1">plugins</span><span class="sy0">,</span> <span class="st0">'session'</span><span class="br0">)</span><br />   .<span class="me1">demuxHTTP</span><span class="br0">(</span><span class="st0">'request'</span><span class="br0">)</span><br /> <br /> .<span class="me1">pipeline</span><span class="br0">(</span><span class="st0">'request'</span><span class="br0">)</span><br />   .<span class="me1">use</span><span class="br0">(</span><br />     config.<span class="me1">plugins</span><span class="sy0">,</span><br />     <span class="st0">'request'</span><span class="sy0">,</span><br />     <span class="st0">'response'</span><span class="sy0">,</span><br />     <span class="br0">(</span><span class="br0">)</span> <span class="sy0">=&gt;</span> __turnDown<br />   <span class="br0">)</span><br /> <br /> <span class="br0">)</span><span class="br0">(</span>JSON.<span class="me1">decode</span><span class="br0">(</span>pipy.<span class="me1">load</span><span class="br0">(</span><span class="st0">'config/proxy.json'</span><span class="br0">)</span><span class="br0">)</span><span class="br0">)</span></div></div></pre></li> </ol> <p>So far, your workspace looks like this:</p> <article class="align-center media media--type-image media--view-mode-default"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="https://opensource.com/sites/default/files/2022-05/pipy3.png" width="944" height="593" alt="Image of workspace" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>(Ali Naqvi, CC BY-SA 40)</p> </div> </article> <p>To run your script, click the play icon button (4th from right). Pipy runs your proxy script, and you see output similar to this:</p> <article class="align-center media media--type-image media--view-mode-default"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="https://opensource.com/sites/default/files/2022-05/pipy4.png" width="950" height="680" alt="Image of output" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>(Ali Naqvi, CC BY-SA 40)</p> </div> </article> <p>This shows that your proxy server is listening on port 8000 (which you configured in your <code>/config/proxy.json</code>). Use <a href="https://www.redhat.com/sysadmin/social-media-curl" target="_blank">curl to run a test</a>:<br />  </p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ curl <span class="re5">-i</span> <span class="br0">[</span>http:<span class="sy0">//</span>localhost:<span class="nu0">8000</span><span class="br0">]</span><span class="br0">(</span>http:<span class="sy0">//</span>localhost:<span class="nu0">8000</span><span class="br0">)</span><br /> HTTP<span class="sy0">/</span><span class="nu0">1.1</span> <span class="nu0">404</span> Not Found<br /> content-length: <span class="nu0">10</span><br /> connection: keep-alive<br /> No handler found</div></div></pre><p>That response makes sense because you haven't configured any target for root. Try one of your configured routes, such as <code>/hi</code>:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ curl <span class="re5">-i</span> <span class="br0">[</span>http:<span class="sy0">//</span>localhost:<span class="nu0">8000</span><span class="sy0">/</span>hi<span class="br0">]</span><span class="br0">(</span>http:<span class="sy0">//</span>localhost:<span class="nu0">8000</span><span class="sy0">/</span>hi<span class="br0">)</span><br /> HTTP<span class="sy0">/</span><span class="nu0">1.1</span> <span class="nu0">502</span> Connection Refused<br /> content-length: <span class="nu0">0</span><br /> connection: keep-alive</div></div></pre><p>You get <code>502 Connection Refused</code> because you have no service running on your configured target port.</p> <p>You can update <code>/config/balancer.json</code> with details like the host and port of your already running services to make it fit for your use case, or you can just write a script in Pipy to listen on your configured ports, and return simple messages.</p> <p>Save this code to a file on your local computer named <code>mock-proxy.js</code>, and remember the location where you stored it:</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">pipy<span class="br0">(</span><span class="br0">)</span><br /> <br /> .listen<span class="br0">(</span><span class="nu0">8080</span><span class="br0">)</span><br />   .serveHTTP<span class="br0">(</span><br />     new Message<span class="br0">(</span><span class="st_h">'Hi, there!\n'</span><span class="br0">)</span><br />   <span class="br0">)</span><br /> <br /> .listen<span class="br0">(</span><span class="nu0">8081</span><span class="br0">)</span><br />   .serveHTTP<span class="br0">(</span><br />     msg =<span class="sy0">&gt;</span> new Message<span class="br0">(</span>msg.body<span class="br0">)</span><br />   <span class="br0">)</span><br /> <br /> .listen<span class="br0">(</span><span class="nu0">8082</span><span class="br0">)</span><br />   .serveHTTP<span class="br0">(</span><br />     msg =<span class="sy0">&gt;</span> new Message<span class="br0">(</span><br />       <span class="sy0">`</span>You are requesting <span class="co1">${msg.head.path}</span> from <span class="co1">${__inbound.remoteAddress}</span>\n<span class="sy0">`</span><br />     <span class="br0">)</span><br />   <span class="br0">)</span></div></div></pre><p>Open a new terminal window and run this script with Pipy (change <code>/path/to</code> to the location where you stored this script file):<br />  </p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">$ pipy <span class="sy0">/</span>path<span class="sy0">/</span>to<span class="sy0">/</span>mock-proxy.js<br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> Module <span class="sy0">/</span>mock-proxy.js<br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> ================<br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> <span class="br0">[</span>Listen on :::<span class="nu0">8080</span><span class="br0">]</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> -----<span class="sy0">&gt;|</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> <span class="sy0">|</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> serveHTTP<br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> <span class="sy0">|</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> <span class="sy0">&lt;</span>-----<span class="sy0">|</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> <span class="br0">[</span>Listen on :::<span class="nu0">8081</span><span class="br0">]</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> -----<span class="sy0">&gt;|</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> <span class="sy0">|</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> serveHTTP<br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> <span class="sy0">|</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> <span class="sy0">&lt;</span>-----<span class="sy0">|</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> <span class="br0">[</span>Listen on :::<span class="nu0">8082</span><span class="br0">]</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> -----<span class="sy0">&gt;|</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> <span class="sy0">|</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> serveHTTP<br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> <span class="sy0">|</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span> <span class="sy0">&lt;</span>-----<span class="sy0">|</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>config<span class="br0">]</span><br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>listener<span class="br0">]</span> Listening on port <span class="nu0">8080</span> at ::<br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>listener<span class="br0">]</span> Listening on port <span class="nu0">8081</span> at ::<br /> <span class="nu0">2022</span>-01-<span class="nu0">11</span> <span class="nu0">18</span>:<span class="nu0">56</span>:<span class="nu0">31</span> <span class="br0">[</span>INF<span class="br0">]</span> <span class="br0">[</span>listener<span class="br0">]</span> Listening on port <span class="nu0">8082</span> at ::</div></div></pre><p>You now have your mock services listening on ports 8080, 8081, and 8082. Do a test again on your proxy server to see the correct response returned from your mock service.</p> <h2 id="summary">Summary</h2> <p>You've used a number of Pipy features, including variable declaration, importing and exporting variables, plugins, Pipelines, sub-pipelines, filter chaining, Pipy filters like <code>handleMessageStart</code>, <code>handleStreamStart</code>, and link, and Pipy classes like JSON, <code>algo.URLRouter</code>, <code>algo.RoundRobinLoadBalancer</code>, <code>algo.Cache</code>, and others. For more information, read the excellent <a href="https://flomesh.io" target="_blank">Pipy documentation</a>, and through Pipy's admin web UI, and follow the step-by-step tutorials that come with it.</p> <h2 id="conclusion">Conclusion</h2> <p>Pipy from <a href="https://flomesh.io" target="_blank">Flomesh</a> is an open source, extremely fast, and lightweight network traffic processor. You can use it in a variety of use cases ranging from edge routers, load balancing and proxying (forward and reverse), API gateways, static HTTP servers, service mesh sidecars, and many other applications. Pipy is in active development and is maintained by full-time committers and contributors.</p> </div> <div class="clearfix text-formatted field field--name-field-article-subhead field--type-text-long field--label-hidden field__item"><p>Pipy is an open source, extremely fast, and lightweight network traffic processor. It has a variety of use cases including edge routers, load balancing and proxying, API gateways, static HTTP servers, service mesh sidecars, and many other applications.</p> </div> <div class="field field--name-field-lead-image field--type-entity-reference field--label-hidden field__item"><article class="media media--type-image media--view-mode-caption"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="/sites/default/files/lead-images/lenovo-thinkpad-laptop-concentration-focus-windows-office.png" width="799" height="447" alt="Business woman on laptop sitting in front of window" title="Woman using laptop concentrating" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>Image by Mapbox Uncharted ERG, <a href="https://creativecommons.org/licenses/by/3.0/us/" rel="noreferrer nofollow" target="_blank">CC-BY 3.0 US</a></p> </div> </article> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/tags/containers" hreflang="en">Containers</a></div> <div class="field__item"><a href="/tags/networking" hreflang="en">Networking</a></div> </div> <div class="hidden field field--name-field-listicle-title field--type-string field--label-hidden field__item">What to read next</div> <div class="field field--name-field-default-license field--type-list-string field--label-hidden field__item"><a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"> <img alt="Creative Commons License" src="/themes/osdc/assets/img/cc-by-sa-4.png" title="This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License." /></a>This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.</div> <section id='comments' class="field field--name-field-comments field--type-comment field--label-hidden comment-wrapper"> <div class="comments__count"> <div class="login"><a href="/user/register?absolute=1">Register</a> or <a href="/user/login?current=/rss.xml&amp;absolute=1">Login</a> to post a comment.</div> </div> </section> Wed, 18 May 2022 07:00:00 +0000 Ali Naqvi 70024 at https://opensource.com https://opensource.com/article/22/5/pipy-programmable-network-proxy-cloud#comments Travel off the grid and still send emails with putmail https://opensource.com/article/22/5/send-email-putmail <span class="field field--name-title field--type-string field--label-hidden">Travel off the grid and still send emails with putmail</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/users/ksonney" class="username">Kevin Sonney</a></span> <span class="field field--name-created field--type-created field--label-hidden">Tue, 05/17/2022 - 03:00</span> <div data-drupal-selector="rate-node-70021" class="rate-widget-thumbs-up" title="Register or Login to like."> <div class="rate-thumbs-up-btn-up vote-pending">2 readers like this</div> <div class="rate-score">2 readers like this</div> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p><em>Automation is a hot topic right now. In my day job as an SRE part of my remit is to automate as many repeating tasks as possible. But how many of us do that in our daily, not-work, lives? This year, I am focused on automating away the toil so that we can focus on the things that are important.</em></p> <p>In "normal times" my wife and I travel a lot. And as anyone who similarly travels a lot knows, connectivity can be very expensive. We were recently on a cruise and the "Premium" ship-board internet cost upwards of $200 for the full 7 days, and even then it had all the drawbacks of satellite internet in terms of speed and congestion. So to make my life easier, I set up <a href="https://www.offlineimap.org/">offlineimap</a> to download my mail, <a href="https://www.dovecot.org/">dovecot</a> to let me use an IMAP client to read my mail, and <a href="https://marlam.de/msmtp/">msmtp</a> to send mail from my various accounts. I covered much of <a href="https://opensource.com/article/20/1/sync-email-offlineimap">this setup in 2020</a>, and the rest is documented in many places online.</p> <p></p><div class="embedded-resource-list callout-float-right"> <div class="field field--name-title field--type-string field--label-hidden field__item">More great content</div> <div class="field field--name-links field--type-link field--label-hidden field__items"> <div class="field__item"><a href="https://www.redhat.com/en/services/training/rh024-red-hat-linux-technical-overview?intcmp=7016000000127cYAAQ">Free online course: RHEL technical overview</a></div> <div class="field__item"><a href="https://developers.redhat.com/cheat-sheets/advanced-linux-commands/?intcmp=7016000000127cYAAQ">Learn advanced Linux commands</a></div> <div class="field__item"><a href="https://opensource.com/downloads/cheat-sheets?intcmp=7016000000127cYAAQ">Download cheat sheets</a></div> <div class="field__item"><a href="https://opensource.com/tags/linux?intcmp=7016000000127cYAAQ">Find an open source alternative</a></div> <div class="field__item"><a href="https://opensource.com/resources?intcmp=7016000000127cYAAQ">Explore open source resources</a></div> </div> </div> <p>What is not often discussed is that you still need to be online to send mail. The most common recommended solution for sending mail is msmtp, and it always rejects mail if it can't connect to the desired host. But it does have a daemon option (<code>msmtpd</code>) that can be used to accept local SMTP connections and forward them to another program. By default, this is <code>msmtp</code> itself. But again, I don't want to send things now, I want to send things when I have a connection, which is when I stumbled upon <a href="https://github.com/tgray/putmail">putmail</a>.</p> <p><code>Putmail</code> is a set of Python scripts that sends mail to pre-configured smtp servers based on the <code>From</code> address in a mail message. It is stable (unmodified since 2011), and just works. If you, like me, have multiple email addresses which have to be sent via multiple SMTP relays, this is just the thing you need. Each email address you send from has its own configuration file, and since <code>putmail</code> decides on which to use based on the message itself, there's no need to have to set up multiple sending setups in a single mail client.</p> <p>As an example, to send with a <code>gmail</code> account, you would create the file <code>.putmail/yourname@gmail.com</code> and fill in the following information.</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">yourname<span class="sy0">@</span>gmail.com putmail configuration<br /> <span class="br0">[</span>config<span class="br0">]</span><br /> email = yourname<span class="sy0">@</span>gmail.com<br /> server = smtp.gmail.com<br /> port = <span class="nu0">587</span><br /> username = yourname<span class="sy0">@</span>gmail.com<br /> password = XXXXXXXXXXXXXXXXX<br /> tls = on</div></div></pre><p>And that's it. Configure a mail client to send via <code>putmail.py</code> instead of <code>sendmail</code> or <code>msmtp</code> and send a message.</p> <p>The next best things are the <code>putmail_enque.py</code> and <code>putmail_dequeue.py</code> scripts. The first takes an email and stores it to send later. The second loops through the queue and delivers the mail. By specifying <code>putmail_enqueue.py</code> as the program <code>msmtpd</code> runs, I can "send" an email now, and it just waits for me to run <code>putmail_dequeue.py</code> later. Here is my <code>msmtpd</code> startup command, specifying <code>putmail_enqueue.py</code> as the item to be used for mail delivery.</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash">msmtpd <span class="re5">--port</span>=<span class="nu0">1025</span> <span class="re5">--log</span>=<span class="sy0">/</span>tmp<span class="sy0">/</span>msmtpd.log <span class="re5">--command</span>=<span class="st_h">'putmail_enqueue.py -f %F'</span> -</div></div></pre><p>I use the following script as a <code>presynchook</code> in <code>offlineimap</code> to check to see if I am connected, and if so, send mail.</p> <pre> <div class="geshifilter"><div class="bash geshifilter-bash"><span class="co0">#!/bin/bash</span><br /> <span class="kw3">echo</span> Sending queued messages \<span class="br0">(</span><span class="kw1">if</span> any\<span class="br0">)</span><br /> <span class="re2">QUEUEDMAIL</span>=$<span class="br0">(</span><span class="kw2">find</span> <span class="re1">$HOME</span><span class="sy0">/</span>.putmail<span class="sy0">/</span>queue <span class="re5">-type</span> f <span class="sy0">|</span> <span class="kw2">wc</span> -l<span class="br0">)</span><br /> <span class="kw1">if</span> <span class="br0">[</span> <span class="re1">$QUEUEDMAIL</span> <span class="re5">-ne</span> <span class="nu0">0</span> <span class="br0">]</span>; <span class="kw1">then</span><br />   <span class="kw2">ping</span> <span class="re5">-n</span> <span class="re5">-c</span> <span class="nu0">1</span> imap.gmail.com <span class="sy0">&gt;/</span>dev<span class="sy0">/</span>null <span class="nu0">2</span><span class="sy0">&gt;/</span>dev<span class="sy0">/</span>null<br />   <span class="kw1">if</span> <span class="br0">[</span> <span class="re4">$?</span> <span class="re5">-eq</span> <span class="nu0">0</span> <span class="br0">]</span>; <span class="kw1">then</span><br />     putmail_dequeue.py<br />   <span class="kw1">fi</span><br /> <span class="kw1">fi</span></div></div></pre><p>After all that, I can use any mail client I wish and send mail with a standard SMTP call to <code>localhost:1025</code> and have it delivered next time I'm connected to the internet. And the best part is, I don't have to change my workflow for email if I'm home or traveling — it all just happens automatically in the background.</p> </div> <div class="clearfix text-formatted field field--name-field-article-subhead field--type-text-long field--label-hidden field__item"><p>Configure your mail client to automatically send emails next time you have an internet connection.</p> </div> <div class="field field--name-field-lead-image field--type-entity-reference field--label-hidden field__item"><article class="media media--type-image media--view-mode-caption"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="/sites/default/files/lead-images/email_chat_communication_message.png" width="1041" height="584" alt="Chat via email" title="Chat via email" loading="lazy" /> </div> </article> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/tags/email" hreflang="en">Email</a></div> </div> <div class="field field--name-field-listicle-title field--type-string field--label-hidden field__item">What to read next</div> <div class="field field--name-field-listicles field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/article/22/5/gmailctl-linux-command-line-tool" hreflang="en">Manage your Gmail filters from the Linux command line</a></div> </div> <div class="field field--name-field-default-license field--type-list-string field--label-hidden field__item"><a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"> <img alt="Creative Commons License" src="/themes/osdc/assets/img/cc-by-sa-4.png" title="This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License." /></a>This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.</div> <section id='comments' class="field field--name-field-comments field--type-comment field--label-hidden comment-wrapper"> <div class="comments__count"> <div class="login"><a href="/user/register?absolute=1">Register</a> or <a href="/user/login?current=/rss.xml&amp;absolute=1">Login</a> to post a comment.</div> </div> </section> Tue, 17 May 2022 07:00:00 +0000 Kevin Sonney 70021 at https://opensource.com https://opensource.com/article/22/5/send-email-putmail#comments 4 ways you can preserve the Earth's livability with open source https://opensource.com/article/22/5/preserve-earths-livability-open-source <span class="field field--name-title field--type-string field--label-hidden">4 ways you can preserve the Earth&#039;s livability with open source</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/users/tobias-augspurger" class="username">Tobias Augspurger</a></span> <span class="field field--name-created field--type-created field--label-hidden">Tue, 05/17/2022 - 03:00</span> <div data-drupal-selector="rate-node-70012" class="rate-widget-thumbs-up" title="Register or Login to like."> <div class="rate-thumbs-up-btn-up vote-pending">5 readers like this</div> <div class="rate-score">5 readers like this</div> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Earth's uniqueness in creating a stable environment for life in a completely hostile space is a miracle. Various life forms have taken billions of years to build up the natural resources humans depend on, such as a protective atmosphere, fertile soil, stable weather, and clean drinking water.</p> <p>As a movement to democratize technology development and knowledge creation, open source has the potential to become the central driver in preserving this stability. Here are four different ways you can preserve the livability of the planet by using, supporting, and participating in open source projects, and more than 20 resources to help you get started.</p> <h2>Measure, optimize, and reduce</h2> <p>Before taking action, it is important to assess your impact on the environment in a scientific way. With more accurate information, you can focus your efforts where the most potential lies. Open science discloses the models behind these measurements, which reduces uncertainties in the long term through continuous improvement and observation. Open source tools make it possible to remain objective and make meaningful comparisons to guide decision making.</p> <p>These decisions happen constantly, both in the consumption of everyday resources and in the use and development of digital products. Software developers find their work in digital products all over the world. Measuring and reducing the energy consumption of these products is the goal of open source tools like <a href="https://github.com/hubblo-org/scaphandre" target="_blank">Scaphandre</a>, <a href="https://github.com/cloud-carbon-footprint/cloud-carbon-footprint" target="_blank">Cloud Carbon Footprint</a>, and <a href="https://github.com/kube-green/kube-green" target="_blank">kube-green</a>. These tools help you track power consumption, estimate carbon emissions, and even shut down resources when they are not needed.</p> <article class="align-center media media--type-image media--view-mode-default"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="https://opensource.com/sites/default/files/2022-05/cloud-carbon-footprint.jpeg" width="1905" height="1009" alt="Cloud Carbon Footprint" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>Cloud Carbon Footprint is an open-source project, sponsored by Thoughtworks Inc <br />(Cloud Carbon Footprint, Apache License, Version 2.0)</p> </div> </article> <p>The open source platform <a href="https://app.electricitymap.org/map" target="_blank">electricityMap</a> calculates and predicts the carbon intensity of electric power consumption within electrical grids worldwide on an hourly basis. You or your business can take action by using this information to shift computation to times when there is a high share of renewable energy sources in the electricity grid, thereby reducing emissions.</p> <p>The open source community of <a href="https://openenergymonitor.org/" target="_blank">OpenEnergyMonitor</a> enables people to monitor and understand the electrification of their homes. Open hardware and open source tools created by OpenEnergyMonitor track and log usage data from multiple categories, including electric vehicles, heat pumps, and photovoltaics. Their learning platform offers a deep understanding of the possibilities for increasing the use of sustainable energy in your household and becoming energy independent. At the heart of it all is the <a href="https://github.com/openenergymonitor/emonpi" target="_blank">emonPi</a> energy monitor and base station, which can bring together information about your energy consumption from multiple sensor nodes.</p> <article class="align-center media media--type-image media--view-mode-default"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="https://opensource.com/sites/default/files/2022-05/my-solar-pv.jpeg" width="675" height="507" alt="A collage of photos shows a wall-mounted household monitor with a graph indicating total energy usage and solar usage, solar panels on a roof, and two additional examples of how usage could be visualized at different levels of total and solar power." loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>The OpenEnergyMonitor Solar PV monitor provides real-time and historical information on solar generation and on-site consumption.<br /> (OpenEnergyMonitor, CC BY-SA 4.0)</p> </div> </article> <h2>Understand the planet</h2> <p>The Earth is a highly complex system, which makes it vitally important to better understand the impact humans have on this system. Several open science and open source projects are working to improve transparency and cooperation in this area. Various tutorials offer beginners an introduction to the programming languages and tools used in this field. These tutorials allow you to improve your programming skills while simultaneously learning more about the environment.</p> <p><a href="https://earth-env-data-science.github.io/" target="_blank">An Introduction to Earth and Environmental Data Science</a> provides a beginner-friendly introduction to the use of open source Python tools, how these tools can be used, and data science in general. Instead of introducing the basics of Python with routine robotics projects, learners discover how to use Python and programming tools to interpret data about the planet.</p> <article class="align-center media media--type-image media--view-mode-default"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="https://opensource.com/sites/default/files/2022-05/sea_ice_map.png" width="497" height="414" alt="A color-coded map showing the concentration of sea ice around Antarctica, with yellow representing 100% and darker colors from green to indigo to violet representing smaller concentrations down to 0%" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>Understanding and representing earth observation data, such as this map of sea ice concentration, is a central part of the Introduction to Earth and Environmental Data Science course.<br /> (Tobias Auspurger, CC BY-SA 4.0)</p> </div> </article> <p><a href="https://brian-rose.github.io/ClimateLaboratoryBook/home.html" target="_blank">The Climate Laboratory</a> provides the perfect starting point for getting a deeper understanding of climate change and the physical science behind it. Like the previous example, this course includes tutorials to use Python, one of the main tools for climate scientists today. The textbook is a living document that has been created around <a href="https://github.com/brian-rose/climlab" target="_blank">climlab</a> to provide a powerful but entry-level friendly tool for climate modeling.</p> <article class="align-center media media--type-image media--view-mode-default"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="https://opensource.com/sites/default/files/2022-05/transient-cesm_41_0.png" width="675" height="335" alt="A map of the globe using a range of colors from violet to light green to illustrate anomalies in surface air temperatures. Toward the poles, the colors get lighter and greener to reflect a higher level of surface air temperature anomalies" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>You can learn to make maps illustrating surface air temperature anomalies due to CO2 doubling.<br /> (Tobias Auspurger, CC BY-SA 4.0)</p> </div> </article> <p><a href="https://www.earthdatascience.org/" target="_blank">Earth Lab</a> provides Earth data science lessons that will help you learn how to work with data in the R and Python programming languages. All course material is open source. Nonspecialists who enroll in the Earth data analytics online course help ensure that understanding how the planet works is not just an academic exercise but also a field of knowledge used in all parts of society.</p> <h2>Observe the planet</h2> <p>Satellites provide a unique tool to map the state of the planet. Even small changes in our ecosystems such as greenhouse gas emissions, land use change, biodiversity loss, soil drought, or water pollution can be measured with high temporal and spatial resolution.. The data collected here are calibrated to the highest scientific standards and therefore provide an objective view of Earth. Recent years have seen a massive democratization of data and software tools in this field. NASA and ESA have published many data sets and tools from various satellite missions under a free license.</p> <p>The condition of even the most remote forests can be assessed with the help of satellite images in different spectra. All kinds of forest health indicators can be derived from data, like <a href="https://github.com/ghislainv/forestatrisk" target="_blank">deforestation risk</a>, <a href="https://github.com/pyronear/pyro-vision" target="_blank">wildfire risk</a>, or <a href="https://github.com/weecology/DeepForest" target="_blank">tree detection</a>. By using and improving these tools, you can actively contribute to preserving this ecosystem. Only by measuring and disclosing such information can environmentalists demonstrate that habitats are being lost.</p> <p>You can also learn how to process satellite data using modern image processing algorithms such as neural networks. One of the most robust communities in this field is <a href="https://www.globalforestwatch.org/map/" target="_blank">Global Forest Watch</a>. Here, multiple datasets are combined to give an interactive overview of the health of forests worldwide.</p> <article class="align-center media media--type-image media--view-mode-default"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="https://opensource.com/sites/default/files/2022-05/notebooks_get_started_30_0.png" width="675" height="504" alt="A map of the Caribbean island of Guadeloupe colored to visualize the likelihood of deforestation, from green (least likely) in the middle of the island to dark red (most likely) toward the coastline" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>Spatial probability of deforestation on Guadeloupe<br /> (Tobias Auspurger, CC BY-SA 4.0)</p> </div> </article> <p>Projects like <a href="https://resourcewatch.org/" target="_blank">Resource Watch</a> and <a href="https://www.radiant.earth/" target="_blank">Radiant Earth</a> provide entry-level platforms for people anywhere to understand natural resources based on Earth-observation technology. NASA provides its own open source platform, <a href="https://nasaharvest.org/" target="_blank">NASA Harvest</a>, to map the state of crops, providing essential information about food security. Another way to get insights about possible hunger crises is the measurement of soil moisture, which is also possible from space with packages like <a href="https://github.com/ropensci/smapr" target="_blank">smapr</a>.</p> <p>The ever-increasing resolution of satellite data in recent years means that even the impact of individual companies on the environment can be measured. This new field of science is called <i>spatial finance</i>, and its purpose is to guide business development and investment in alignment with good sustainability practices. The first open datasets in this field track the locations and  companies involved in <a href="https://www.cgfi.ac.uk/spatial-finance-initiative/geoasset-project/geoasset-databases/" target="_blank">cement production</a>, <a href="https://www.cgfi.ac.uk/spatial-finance-initiative/geoasset-project/geoasset-databases/" target="_blank">iron and steel production</a>, and <a href="https://github.com/Lkruitwagen/global-fossil-fuel-supply-chain" target="_blank">global coal, oil, and gas supply chains</a>. The <a href="https://carbonmapperdata.org/map" target="_blank">Carbon Mapper</a> platform shows how to build pressure on companies by disclosing methane and carbon dioxide sources.</p> <article class="align-center media media--type-image media--view-mode-default"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="https://opensource.com/sites/default/files/2022-05/all_assets.jpeg" width="675" height="380" alt="A world map illustrating the global fossil fuel supply chain, with lines of several different colors showing fuel sources and transit routes" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>Global coal, oil, and gas asset-level data<br /> (Lucas Kruitwagen, MIT License)</p> </div> </article> <h2>Demand openness</h2> <p>Environmental catastrophes are often accompanied by a cover-up and manipulation of scientific findings and information. This applies to climate change as well as local environmental impacts. UN Secretary-General Antonio Guterres has given a clear warning following the release of the international climate change report, which shows no trend reversal in global warming and the loss of biodiversity in 2022.</p> <blockquote><p>We are on a pathway to global warming of more than double the 1.5°C limit agreed in Paris. Some government and business leaders are saying one thing, but doing another. Simply put, they are lying. And the results will be catastrophic. This is a climate emergency.</p> </blockquote> <article class="align-center media media--type-image media--view-mode-default"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="https://opensource.com/sites/default/files/2022-05/tutorials_pyam_first_steps_65_1.png" width="389" height="278" alt="World variable: Temperature" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>With the help of pyam you can process the data behind the latest UN report and thus better understand the different scenarios. <br />(pyam, Apache license)</p> </div> </article> <p>One of the easiest ways to change course is to consistently demand open science concerning environmental issues. Openness is a key indicator of sustainable development, because anyone pursuing truly sustainable intentions is interested in refining their conclusions through open scientific discourse. Openness will also help prevent <i>greenwashing,</i> or the practice of promoting a company's sustainability efforts through marketing while scientific findings and conclusions about environmental impacts are downplayed or held private.</p> <p>The next time you buy products that claim to be carbon neutral, ask for independent studies and data. If a politician demands questionable measures for environmental protection, ask for open model calculations and open access studies on this topic. Do you want to invest in a sustainable investment fund? Ask for open scientific studies, data, and models on why this investment is sustainable. Demanding openness in all these ways helps limit greenwashing and ensures that companies' environmental impacts are verifiable, accountable, and traceable.</p> </div> <div class="clearfix text-formatted field field--name-field-article-subhead field--type-text-long field--label-hidden field__item"><p>Why actions rooted in open source culture can make a big impact.</p> </div> <div class="field field--name-field-lead-image field--type-entity-reference field--label-hidden field__item"><article class="media media--type-image media--view-mode-caption"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="/sites/default/files/lead-images/dandelion_blue_water_hand.jpg" width="520" height="293" alt="Dandelion held out over water" title="Dandelion held out over water" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>Seth Kenlon, CC BY-SA 4.0</p> </div> </article> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/tags/science" hreflang="en">Science</a></div> <div class="field__item"><a href="/tags/data-science" hreflang="en">Data Science</a></div> </div> <div class="hidden field field--name-field-listicle-title field--type-string field--label-hidden field__item">What to read next</div> <div class="field field--name-field-default-license field--type-list-string field--label-hidden field__item"><a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"> <img alt="Creative Commons License" src="/themes/osdc/assets/img/cc-by-sa-4.png" title="This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License." /></a>This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.</div> <section id='comments' class="field field--name-field-comments field--type-comment field--label-hidden comment-wrapper"> <div class="comments__count"> <div class="login"><a href="/user/register?absolute=1">Register</a> or <a href="/user/login?current=/rss.xml&amp;absolute=1">Login</a> to post a comment.</div> </div> </section> Tue, 17 May 2022 07:00:00 +0000 Tobias Augspurger 70012 at https://opensource.com 5 benefits of switching from Google Analytics to Plausible https://opensource.com/article/22/5/plausible-analytics <span class="field field--name-title field--type-string field--label-hidden">5 benefits of switching from Google Analytics to Plausible</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/users/tpgreenwood" class="username">Tom Greenwood</a></span> <span class="field field--name-created field--type-created field--label-hidden">Mon, 05/16/2022 - 03:00</span> <div data-drupal-selector="rate-node-70017" class="rate-widget-thumbs-up" title="Register or Login to like."> <div class="rate-thumbs-up-btn-up vote-pending">5 readers like this</div> <div class="rate-score">5 readers like this</div> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Google Analytics (GA) has been the industry standard web analytics tool for about as long as there have been analytics tools. Nearly every brief that my WordPress agency receives specifies that GA must be installed. And there is rarely any debate around whether it's the best tool for the job.</p> <p>My team at Wholegrain Digital has had concerns about GA in terms of privacy, General Data Protection Regulation (GDPR) compliance, performance, user experience, not to mention Google as a global advertising, and search monopoly. However, we continued using GA for 99% of our projects because we didn't feel that there was a strong enough alternative.</p> <p>Well, that has changed. We've made a decision that GA will no longer be our default analytics tool. Instead, our default analytics tool will be <a href="https://plausible.io">Plausible</a>.</p> <p>In this article, I'll outline why we consider Plausible a better choice as a default analytics solution, the compromises to be aware of, and how it will impact our clients.</p> <h2 id="the-benefits-of-plausible-over-google-analytics">Why use Plausible instead of Google Analytics</h2> <p>We believe that using Plausible over GA is not a purely ideological choice. There are in fact a number of tangible benefits that make it an objectively better product in many cases. Let's take a look at some of these benefits.</p> <p></p><div class="embedded-resource-list callout-float-right"> <div class="field field--name-title field--type-string field--label-hidden field__item">More great content</div> <div class="field field--name-links field--type-link field--label-hidden field__items"> <div class="field__item"><a href="https://www.redhat.com/en/services/training/rh024-red-hat-linux-technical-overview?intcmp=7016000000127cYAAQ">Free online course: RHEL technical overview</a></div> <div class="field__item"><a href="https://developers.redhat.com/cheat-sheets/advanced-linux-commands/?intcmp=7016000000127cYAAQ">Learn advanced Linux commands</a></div> <div class="field__item"><a href="https://opensource.com/downloads/cheat-sheets?intcmp=7016000000127cYAAQ">Download cheat sheets</a></div> <div class="field__item"><a href="https://opensource.com/tags/linux?intcmp=7016000000127cYAAQ">Find an open source alternative</a></div> <div class="field__item"><a href="https://opensource.com/resources?intcmp=7016000000127cYAAQ">Explore open source resources</a></div> </div> </div> <h3 id="privacy">Privacy</h3> <p>One of Plausible's headline benefits is that it has been designed as a privacy-first analytics tool. This might sound like an ideological factor, but it has real practical implications too.</p> <p>Plausible only collects anonymous user data, and does not use cookies. This means that unlike most analytics solutions, it complies with both the GDPR and the European Cookie Law, so it's a tick in the box for legal compliance. It's also hosted in the EU and the data is owned by you so it doesn't get shared with any other organizations, which is another tick.</p> <p>This has a positive knock-on effect for user experience, because without privacy-invading cookies, you don't need to implement a cookie banner on the website (unless you use cookies for other things). Considering that the first few seconds of a website visit are the most critical to brand experience and conversion rates, cookie banners are arguably the single most damaging thing to the success of any online service. Avoiding these banners puts your brand and message first, helps you make a good first impression, and increases conversion rates.</p> <h3 id="simpler-user-interface">Simpler user interface</h3> <p>The GA dashboard was never a great case study in intuitive design, but as the functionality of GA has expanded, so too has the complexity of the interface. I'm increasingly hearing frustrations from even experienced web marketers that they sometimes struggle to find basic data inside GA.</p> <p>Plausible has taken the opposite approach and focused on ease of use over quantity of features. The dashboard is beautifully designed to showcase the data you want in a way that is easy to find and understand. It's what most people wish GA to be and it's a breath of fresh air.</p> <article class="align-center media media--type-image media--view-mode-default"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="https://opensource.com/sites/default/files/2022-05/Plausible-%C2%B7-websitecarbon-com.jpg" alt="Image of Plausible with a dark theme" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>(Tom Greenwood, CC BY-SA 4.0)</p> </div> </article> <p>This is not just a pleasantry. The reality is that if a tool is easy to use then you will use it, and if it is hard to use then you won't. The simplicity of the Plausible interface means that even though it has less features, many users are likely to get a lot more insights and value from their analytics.</p> <h3 id="better-web-performance">Better web performance</h3> <p>The Plausible tracking script is the smallest we are aware of for any analytics service, coming in at less than 1kb compared to 17kb for GA and even more if you're using Google Tag Manager.</p> <p>Better web performance improves user experience, helps your website to rank better in search engines and improves conversion rates. Web performance matters, and when it comes to web performance, every kilobyte matters.</p> <h3 id="reduced-environmental-impact">Reduced environmental impact</h3> <p>Plausible's tiny tracking script isn't just good for web performance, it's also good for the environment. At Wholegrain we are world leaders in sustainable web design and understand that every bit of wasted data is also wasted energy and carbon emissions.</p> <p>This adds up. As a minimum, switching to Plausible would save 16kb per visitor, so for a website with a modest 10K visitors per month this would be 160MB of data per month, or 2GB per year. A back of an envelope calculation using the latest methodology that we have developed for website carbon calculations put this at about the equivalent of 800 grams of CO2. Now multiply that up by the millions of websites running worldwide and you are talking about significant amounts of wasted energy and unnecessary carbon emissions.</p> <p><strong>[ Read also: <a href="https://opensource.com/article/22/4/zero-waste-web-design" target="_blank">5 open source tips to reduce waste in web design</a> ]</strong></p> <p>But it doesn't stop there. Analytics tools consume energy on the end user's device as they harvest data, in the transmission networks as they send that data back to the data center, and in the data center to store it all for eternity. By tracking less, Plausible is using less energy in its operation than bloated analytics tools such as GA that are tracking many more metrics that most people don't need.</p> <p>Plausible also hosts the data in data centers with a commitment to using renewable sources of electricity, which is great (though to be fair Google also does that), and they donate 5% of their revenue to good causes, so the money you are paying is also helping support environmental and social projects.</p> <h3 id="more-accurate-data">More accurate data</h3> <p>Finally, Plausible breaks one of the greatest myths about GA, which is that it is accurate. Plausible's own research and our own experiences with client websites show that GA can significantly under report data, sometimes by as much as 50-60%.</p> <p>When you look at GA and you think you are looking at all of your website data, you are most likely only looking at a portion of it. This is because GA is more likely to be blocked by ad blockers and privacy friendly web browsers, but perhaps more significantly because GA should not be tracking your visitors unless they have accepted cookies, which many visitors do not.</p> <p>Plausible therefore offers us a simple way to get a more complete and accurate view of website visitors. Needless to say, if you are a digital marketing manager and you want to make yourself look good, you want to use the analytics service that reports all of your visitors and not just some of them.</p> <h2 id="are-there-any-downsides">Are there any downsides?</h2> <p>There are very few downsides to using Plausible. If you are a GA power user and genuinely need a lot of its more advanced functionality then Plausible is not going to meet all of your needs. Plausible can track events, conversions, and campaigns but if you need more than that then you'll need another tool.</p> <p>The only other notable downside to Plausible is that it is not free. There is a monthly fee but it is very reasonable, starting at $6 per month. It's a small price to pay for such a good tool, to protect the privacy of your website visitors and to maintain ownership of your data.</p> <h2 id="how-will-it-impact-our-clients">What are the impacts?</h2> <p>Here at Wholegrain Digital we are implementing Plausible in a way that we hope will offer many of our clients the benefits listed above without the downsides. Nobody will be forced to stop using GA, but we will be talking about the benefits of Plausible proactively with our clients and including it in our proposals as the default option.</p> <p>In many cases, Plausible is not just capable of meeting a project's requirements, but is objectively a better solution than GA, so we'll be trying to help our clients to reap the benefits of this.</p> <p>In cases where advanced GA features are required, we will of course stick with GA for now. And in some cases, we may run GA and Plausible in parallel. This has a small overhead in terms of carbon footprint and performance, so it isn't our first choice. However, in some cases it may provide a necessary bridge to help our clients gain confidence in Plausible before making the leap, or help them gain a complete data set while ensuring compliance with privacy laws.</p> <p>As for the costs, Plausible is a very good value for what it offers, but we will be offering it free of charge to our clients for any websites cared for on our WordPress maintenance service. We hope that this will help lower the barrier to entry and help more of our clients and their website visitors gain the benefits of Plausible.</p> <h2 id="it-is-plausible">It is Plausible!</h2> <p>I hope I've convinced you that Plausible is not just a viable but a really great alternative to GA. If you need any advice on how to figure out the best analytics solution for your website or how to ensure that you are GDPR compliant without compromising user experience, get in touch with me.</p> <hr /> <p><em>This article originally appeared on the <a href="https://www.wholegraindigital.com/blog/plausible-vs-google-analytics/" target="_blank">Wholegrain Digital </a>blog and has been republished with permission.</em></p> </div> <div class="clearfix text-formatted field field--name-field-article-subhead field--type-text-long field--label-hidden field__item"><p>Plausible is an open source alternative to Google Analytics.</p> </div> <div class="field field--name-field-lead-image field--type-entity-reference field--label-hidden field__item"><article class="media media--type-image media--view-mode-caption"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="/sites/default/files/lead-images/LIFE_wavegraph.png" width="520" height="292" alt="wavegraph" title="The legacy of open source and the tide of progress" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>Opensource.com</p> </div> </article> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/tags/alternatives" hreflang="en">Alternatives</a></div> </div> <div class="field field--name-field-listicle-title field--type-string field--label-hidden field__item">What to read next</div> <div class="field field--name-field-listicles field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/article/21/2/plausible" hreflang="und">Why choose Plausible for an open source alternative to Google Analytics</a></div> </div> <div class="field field--name-field-default-license field--type-list-string field--label-hidden field__item"><a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"> <img alt="Creative Commons License" src="/themes/osdc/assets/img/cc-by-sa-4.png" title="This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License." /></a>This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.</div> <section id='comments' class="field field--name-field-comments field--type-comment field--label-hidden comment-wrapper"> <div class="comments__count"> <div class="login"><a href="/user/register?absolute=1">Register</a> or <a href="/user/login?current=/rss.xml&amp;absolute=1">Login</a> to post a comment.</div> </div> </section> Mon, 16 May 2022 07:00:00 +0000 Tom Greenwood 70017 at https://opensource.com https://opensource.com/article/22/5/plausible-analytics#comments Use Composer to require Git repositories within PHP projects https://opensource.com/article/22/5/composer-git-repositories <span class="field field--name-title field--type-string field--label-hidden">Use Composer to require Git repositories within PHP projects</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/users/daggerhart" class="username">Jonathan Daggerhart</a></span> <span class="field field--name-created field--type-created field--label-hidden">Mon, 05/16/2022 - 03:00</span> <div data-drupal-selector="rate-node-70007" class="rate-widget-thumbs-up" title="Register or Login to like."> <div class="rate-thumbs-up-btn-up vote-pending">3 readers like this</div> <div class="rate-score">3 readers like this</div> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>The dependency management tool <a href="https://getcomposer.org/" target="_blank">Composer</a> provides multiple ways to include Git repositories within a PHP: Hypertext Preprocessor (PHP) project.</p> <p>In many cases, repositories have been created on Packagist, so requiring them with Composer is very straightforward. But what do you do when a repository has not been created as a package on Packagist? You use Composer to require the package directly from the repository. This article explains how.</p> <p><b>Note:</b> Some of the terminology in this post is confusing because multiple words are used to describe different things. Here is a quick vocabulary list that will help:</p> <ul> <li><b>Project:</b> The custom software you are building. This can be a website, a command-line utility, an application, or anything else you dream up.<br />  </li> <li><b>Package:</b> Any third-party software you want to download and use within your project. It can be a library, Drupal theme, WordPress plugin, or any other number of things.<br />  </li> <li><b>Git repository:</b> Also called the Git repo, this is the version-control host for a package. Common hosts include GitHub, GitLab, or Bitbucket, but any URL-accessible Git repository will work for this tutorial.<br />  </li> <li><b>Composer repositories:</b> In a <code>composer.json</code> file, there is an optional property named "repositories." This property is where you can define new places for Composer to look when downloading packages.</li> </ul> <p>When adding a Git repo to your project with Composer, you can find yourself in two situations: Either the repo contains a <code>composer.json</code> file, which defines how the repo should be handled when required, or it does not. You can add the Git repository to your project in both cases, with different methods.</p> <h2>Git repo with composer.json</h2> <p>When a repository includes a <code>composer.json</code> file, it defines aspects of itself that are important to how Composer manages the package. Here is an example of a simple <code>composer.json</code> file a package may include:</p> <pre> <code class="language-json">{ "name": "mynamespace/my-custom-library", "type": "library" }</code></pre><p>This example shows two important properties that a <code>composer.json</code> file can define:</p> <ul> <li><b>Name:</b> The package's namespaced name. In this case, "mynamespace" is the namespace for the package "my-custom-library."</li> <li><b>Type:</b> The type of package the repo represents. Package types are used for installation logic. Out of the box, Composer allows for the following package types: library, project, metapackage, and composer-plugin.</li> </ul> <p>You can verify this by looking at the <code>composer.json</code> file of any popular GitHub project. They each define their package name and the package type near the top of the file. When a repository has this information defined in its <code>composer.json</code> file, requiring the repository within your project is quite simple.</p> <p></p><div class="embedded-resource-list callout-float-right"> <div class="field field--name-title field--type-string field--label-hidden field__item">More on Git</div> <div class="field field--name-links field--type-link field--label-hidden field__items"> <div class="field__item"><a href="https://opensource.com/resources/what-is-git?intcmp=7013a000002CxqLAAS">What is Git?</a></div> <div class="field__item"><a href="https://opensource.com/downloads/cheat-sheet-git?intcmp=7013a000002CxqLAAS">Git cheat sheet</a></div> <div class="field__item"><a href="https://opensource.com/downloads/cheat-sheet-markdown?intcmp=7013a000002CxqLAAS">Markdown cheat sheet</a></div> <div class="field__item"><a href="https://opensource.com/tags/git?intcmp=7013a000002CxqLAAS">New Git articles</a></div> </div> </div> <h2>Require a Git repository that has a composer.json file</h2> <p>After you've identified a Git repository with a <code>composer.json</code> file, you can require that repository as a package within your project.</p> <p>Within your project's <code>composer.json</code> file, you need to define a new property (assuming it doesn't exist already) named "repositories." The value of the repositories property is an array of objects, each containing information about the repository you want to include in your project. Consider this <code>composer.json</code> file for your custom project.</p> <pre> <code class="language-json">{ "name": "mynamespace/my-project-that-uses-composer", "repositories": [ { "type": "vcs", "url": "https://github.com/mynamespace/my-custom-library.git" } ], "require": { "mynamespace/my-custom-library": "dev-master" } } </code></pre><p>You are doing two important things here. First, you're defining a new repository that Composer can reference when requiring packages. And second, you're requiring the package from the newly defined repository.</p> <p><b>Note:</b> The package version is a part of the <i>require</i> statement and not a part of the <i>repository</i> property. You can require a specific branch of a repo by choosing a version named "dev-&lt;branch name&gt;".</p> <p>If you were to run <code>composer install</code> in the context of this file, Composer would look for a project at the defined URL. If that URL represents a Git repo that contains a <code>composer.json</code> file that defines its name and type, Composer will download that package to your project and place it in the appropriate location.</p> <h2>Custom package types</h2> <p>The example package shown above is of the type "library," but with WordPress and Drupal you're dealing with plugins, modules, and themes. When requiring special package types in your project, it's important to install them in specific locations within the project file structure. Wouldn't it be nice if you could convince Composer to treat these types of packages as special cases? Well, you're in luck. There is an official Composer plugin that will do that for you.</p> <p>The <a href="https://github.com/composer/installers" target="_blank">Installers</a> plugin for Composer contains the custom logic required for handling many different package types for a large variety of projects. It is extremely helpful when working with projects that have well-known and supported package installation steps.</p> <p>This project allows you to define package types like drupal-theme, drupal-module, wordpress-plugin, wordpress-theme, and many more, for a variety of projects. In the case of a drupal-theme package, the Installers plugin will place the required repo within the <code>/themes/contrib</code> folder of your Drupal installation.</p> <p>Here is an example of a <code>composer.json</code> file that might live within a Drupal theme project as its own Git repository:</p> <pre> <code class="language-json">{ "name": "mynamespace/whatever-i-call-my-theme", "type": "drupal-theme", "description": "Drupal 8 theme", "license": "GPL-2.0+" } </code></pre><p>Note that the only meaningful difference here is that the type is now drupal-theme. With the drupal-theme type defined, any project that uses the Installers plugin can easily require your repo in its Drupal project, and it will be treated as a contributed theme.</p> <h2>Require any Git repository with Composer</h2> <p>What happens when the repo you want to include in your project does not define anything about itself with a <code>composer.json</code> file? When a repo does not define its name or type, you have to define that information for the repo within your project's <code>composer.json</code> file. Take a look at this example:</p> <pre> <code class="language-json">{ "name": "mynamespace/my-project-that-uses-composer", "repositories": [ { "type": "package", "package": { "name": "mynamespace/my-custom-theme", "version": "1.2.3", "type": "drupal-theme", "source": { "url": "https://github.com/mynamespace/my-custom-theme.git", "type": "git", "reference": "master" } } } ], "require": { "mynamespace/my-custom-theme": "^1", "composer/installers": "^1" } } </code></pre><p>Notice that your repository type is now "package." That is where you will define everything about the package you want to require.</p> <p>Create a new object named "package" where you define all the essential information that Composer needs to know to be able to include this arbitrary git repo within your project, including:</p> <ul> <li><b>Name:</b> The namespaced package name. It should probably match the repository you're requiring but doesn't have to.</li> <li><b>Type:</b> The type of package. This reflects how you want Composer to treat this repository.</li> <li><b>Version:</b> A version number for the repo. You will need to make this up.</li> <li><b>Source:</b> An object that contains the following repository information: <ul> <li><b>URL:</b> The Git or other version-control system (VCS) URL where the package repo can be found</li> <li><b>Type:</b> The VCS type for the package, such as git, svn, cvs, and so on</li> <li><b>Reference:</b> The branch or tag you want to download</li> </ul> </li> </ul> <p>I recommend reviewing the <a href="https://getcomposer.org/doc/05-repositories.md#package-2" target="_blank">official documentation</a> on Composer package repositories. Note that it is possible to include zip files as Composer packages as well. Essentially, you are now responsible for all parts of how Composer treats this repository. Since the repository itself is not providing Composer with any information, you are responsible for determining almost everything, including the current version number for the package.</p> <p>This approach allows you to include almost anything as a Composer package in your project, but it has some notable drawbacks:</p> <ul> <li>Composer will not update the package unless you change the <code>version</code> field.<br />  </li> <li>Composer will not update the commit references. If you use <code>master</code> as a reference, you will have to delete the package to force an update, and you will have to deal with an unstable lock file.</li> </ul> <h2>Custom package versions</h2> <p>Maintaining the package version in your <code>composer.json</code> file isn't always necessary. Composer is smart enough to look for GitHub releases and use them as the package versions. But eventually you will likely want to include a simple project that has only a few branches and no official releases.</p> <p>When a repository does not have releases, you will be responsible for deciding what version the repository branch represents to your project. In other words, if you want composer to update the package, you will need to increment the "version” defined in your project's <code>composer.json</code> file before running <code>composer update</code>.</p> <h2>Overriding a Git repository's composer.json</h2> <p>When defining a new Composer repository of the type package, you can override a package's own <code>composer.json</code> definitions. Consider a Git repository that defines itself as a library in its <code>composer.json</code>, but you know that the code is actually a drupal-theme. You can use the above approach to include the Git repository within your project as a drupal-theme, allowing Composer to treat the code appropriately when required.</p> <p>Example: Require Guzzle as a drupal-theme just to prove that you can.</p> <pre> <code class="language-json">{ "name": "mynamespace/my-project-that-uses-composer", "repositories": [ { "type": "package", "package": { "name": "mynamespace/guzzle-theme", "version": "1.2.3", "type": "drupal-theme", "source": { "url": "https://github.com/guzzle/guzzle.git", "type": "git", "reference": "master" } } } ], "require": { "mynamespace/guzzle-theme": "^1", "composer/installers": "^1" } } </code></pre><p>This works! You've downloaded the Guzzle library and placed it within the <code>/themes</code> folder of your Drupal project. This is not a very practical example, but it highlights how much control the package type approach provides.</p> <h2>Summary</h2> <p>Composer offers plenty of options for including arbitrary packages within a project. Determining how those packages are included in the project primarily comes down to who defines the package information. If the Git repository includes a <code>composer.json</code> file that defines its name and type, you can have Composer rely on the repository itself for the definition.</p> <p>But if you want to include a repository that does not define its name and type, then it is up to your project to define and maintain that information for your own internal use. Alternatively, if a repository doesn't define a <code>composer.json</code> file, consider submitting a pull request that adds it.</p> <hr /> <p><em>This article originally appeared on the <a href="https://www.daggerhartlab.com/composer-how-to-use-git-repositories" target="_blank">Daggerhart Lab blog </a>and is republished with permission.</em></p> </div> <div class="clearfix text-formatted field field--name-field-article-subhead field--type-text-long field--label-hidden field__item"><p>This dependency management tool makes it easier to require a repository even when it hasn&#039;t been created as a package.</p> </div> <div class="field field--name-field-lead-image field--type-entity-reference field--label-hidden field__item"><article class="media media--type-image media--view-mode-caption"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="/sites/default/files/lead-images/lenovo-thinkpad-laptop-window-focus.png" width="1000" height="560" alt="woman on laptop sitting at the window" title="young woman working on a laptop" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>CC BY 3.0 US Mapbox Uncharted ERG</p> </div> </article> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/tags/git" hreflang="en">Git</a></div> </div> <div class="hidden field field--name-field-listicle-title field--type-string field--label-hidden field__item">What to read next</div> <div class="field field--name-field-default-license field--type-list-string field--label-hidden field__item"><a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"> <img alt="Creative Commons License" src="/themes/osdc/assets/img/cc-by-sa-4.png" title="This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License." /></a>This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.</div> <section id='comments' class="field field--name-field-comments field--type-comment field--label-hidden comment-wrapper"> <div class="comments__count"> <div class="login"><a href="/user/register?absolute=1">Register</a> or <a href="/user/login?current=/rss.xml&amp;absolute=1">Login</a> to post a comment.</div> </div> </section> Mon, 16 May 2022 07:00:00 +0000 Jonathan Daggerhart 70007 at https://opensource.com 5 reasons to apply for B Corp certification https://opensource.com/article/22/5/b-corp-open-source <span class="field field--name-title field--type-string field--label-hidden">5 reasons to apply for B Corp certification</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/users/tpgreenwood" class="username">Tom Greenwood</a></span> <span class="field field--name-created field--type-created field--label-hidden">Sat, 05/14/2022 - 03:00</span> <div data-drupal-selector="rate-node-70016" class="rate-widget-thumbs-up" title="Register or Login to like."> <div class="rate-thumbs-up-btn-up vote-pending">3 readers like this</div> <div class="rate-score">3 readers like this</div> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Wholegrain Digital just passed its fifth anniversary of being a certified B Corp. <a href="https://bcorporation.uk/">B Corp</a> is one of the most robust independent certifications assessing whether a business is run responsibly in terms of its environmental impact, its treatment of workers and suppliers, its impact on communities, and its governance.</p> <p>As one of the longest-standing B Corps in the UK, we're increasingly asked for advice by companies considering going through the B Corp assessment process, known as the <a href="https://bimpactassessment.net/">B Impact Assessment</a>. There is one question that seems to come up more than any other, and it is, <em>"Is there a business case for becoming a B Corp?" </em></p> <p>In this article, I'll share my own perspective on that question, based upon what I've experienced in our business and what I've observed from other B corps that I know.</p> <h2 id="do-it-for-the-right-reasons">Do it for the right reasons</h2> <p>First of all, I need to highlight what B Corp is not. It's not a marketing gimmick. There are loads of certifications and badges that companies can get to make themselves look good, but which don't really mean anything.</p> <p>B Corp is different in that it's both independent and really hard to obtain. The difficulty of the assessment is exactly what makes it meaningful. Therefore, if you're thinking that the business benefit is that it's a cheap marketing gimmick, then you're headed in the wrong direction. B Corp certification can have significant benefits to any business, but only if it's pursued for the right reasons and with a genuine commitment to become a more responsible business.</p> <p>So, let's look at the real benefits.</p> <p></p><div class="embedded-resource-list callout-float-right"> <div class="field field--name-title field--type-string field--label-hidden field__item">More great content</div> <div class="field field--name-links field--type-link field--label-hidden field__items"> <div class="field__item"><a href="https://www.redhat.com/en/services/training/rh024-red-hat-linux-technical-overview?intcmp=7016000000127cYAAQ">Free online course: RHEL technical overview</a></div> <div class="field__item"><a href="https://developers.redhat.com/cheat-sheets/advanced-linux-commands/?intcmp=7016000000127cYAAQ">Learn advanced Linux commands</a></div> <div class="field__item"><a href="https://opensource.com/downloads/cheat-sheets?intcmp=7016000000127cYAAQ">Download cheat sheets</a></div> <div class="field__item"><a href="https://opensource.com/tags/linux?intcmp=7016000000127cYAAQ">Find an open source alternative</a></div> <div class="field__item"><a href="https://opensource.com/resources?intcmp=7016000000127cYAAQ">Explore open source resources</a></div> </div> </div> <h2 id="it-helps-small-businesses-grow-up">B Corp helps small businesses grow up</h2> <p>From day one, we always tried to run Wholegrain Digital as a responsible business but it was hard to ever know how well we were doing. When we first started the B Impact Assessment after being in business for about 9 years, we quickly realized that we needed to get more organized about how we manage things across the business.</p> <p>We needed to put some structures and policies in place and properly document evidence of what we're doing. As a small creative business, this was something that we were not very good at and so the process of going through the B Impact Assessment helped us to grow up as a business. It not only gave us better visibility of our performance, but it also encouraged us to put in place the structures that the business needed in order to grow and progress.</p> <p>This benefit is probably mostly applicable to small businesses, but it's one that can help take a business over that hurdle from a small scrappy startup to a serious, mature business.</p> <h2 id="it-guides-you-to-better-performance">B Corp guides you to better performance</h2> <p>The B Impact Assessment is largely multiple choice, with evidence being needed to prove that you have delivered the options that you select. The beauty of this multiple choice format is that for every issue, you can see a variety of options and you can see which ones are considered more responsible than others.</p> <p>This is a great learning tool because in most cases, you probably won't be able to select the "best" option, but will then know what the best option is considered to be. With this knowledge, you can take action to improve in the future. The assessment process therefore helps accelerate progress and give you some targets to aim for.</p> <h2 id="it-helps-create-a-culture-of-positive-change">B Corp helps create a culture of positive change</h2> <p>As mentioned, the impact assessment process can help you see where you could create more positive impact, but the positive change that can come from certifying as a B Corp can go well beyond the things actually included in the assessment. The process gets you thinking more deeply about where you have impact. It also sends a signal to everyone in the organization that there is a deep commitment to creating positive impact.</p> <p>The result is a stronger culture of positive change from which new ideas and initiatives emerge. For example, we've implemented schemes such as <a href="https://www.wholegraindigital.com/blog/climate-perks-green-travel/">Climate Perks</a>, extra holiday for <a href="https://www.wholegraindigital.com/blog/we-now-use-100-renewable-energy-at-the-office-and-at-home/">using renewable energy at home</a> and a <a href="https://www.wholegraindigital.com/blog/vegetarian-food-policy/">vegetarian food policy</a>, even though they don't gain us any points in the B Impact Assessment. More significantly, the thought process that was sparked by our first attempt at the B Impact Assessment led us to research the environmental impact of digital technology and go on to become world leaders in the emerging field of <a href="https://www.wholegraindigital.com/digital-sustainability/">sustainable web design</a>.</p> <p>The innovation inspired by this pursuit has led us to learn new skills and constantly improve the quality of <a href="https://www.wholegraindigital.com/work/">the work that we're delivering</a>, not just environmentally, but across the board. It's inspired, motivated and educated us to perform at the highest level, making us truly proud of the work that we're doing and in turn, helping us to be more commercially successful too.</p> <p><strong>[ Download the eBook: <a href="https://opensource.com/open-organization/resources/culture-change" target="_blank">The Open Organization Guide to IT Culture Change</a> ]</strong></p> <h2 id="it-shows-that-you-are-serious">B Corp shows that you are serious</h2> <p>Two of the benefits that I often hear mentioned are that B Corp certification can help attract talented staff and new clients. In my experience running a digital agency, I would say that this is partially true. I don't think it's a magic bullet in delivering either of these things, but it certainly can help.</p> <p>Awareness of B Corp certification among the general public is still relatively low in the UK so many people won't think much of it. However, for anyone who cares about creating a positive impact, it's a great way of demonstrating that you are serious about it. It helps you to earn their trust and respect and this can definitely help in attracting employees and clients with similar values.</p> <h2 id="it's-a-real-community">B Corp is a real community</h2> <p>There are many things out there today that claim to be communities, but almost none of them are. However, when we first achieved B Corp certification, we were amazed to find ourselves welcomed into a community of business leaders who genuinely cared about creating positive impact and wanted to support other businesses to do the same.</p> <p>The openness and enthusiasm to share and collaborate was refreshing. We've made some great friends, had some amazing shared experiences, and learnt a huge amount from others. This has helped us to stay engaged and motivated in the journey of evolving our own business, as well as providing practical support where we needed it. We are a more successful business as a result.</p> <p>When we joined the B Corp community, it was very small in the UK, so it was a very tight-knit group. The pandemic paused most in-person activities and some of this community energy was lost temporarily. I hope it will soon return to full force.</p> <p>As the UK B Corp movement is now reaching momentum, with 700 companies certified to date and a huge waiting list, there is of course a risk that the true sense of community gets diluted. I therefore hope that the sense of community will be able to be maintained over the long term.</p> <p><strong>[ Read also: <a href="https://opensource.com/article/22/5/inclusive-community-recognition" target="_blank">How to make community recognition more inclusive</a> ]</strong></p> <h2 id="so-is-being-a-b-corp-good-for-business">So is being a B Corp good for open source business?</h2> <p>As Managing Director, I have found that becoming a B Corp has been hugely beneficial to us as at Wholegrain Digital and has contributed to our success in recent years.</p> <p>I believe that it should only be pursued if you truly want to run a more responsible business. It's a lot of work that won't immediately pay for itself but if you're in it for the long term, it can pay dividends for people, the planet, and be financially profitable too.</p> <hr /> <p><em>This article originally appeared on the <a href="https://www.wholegraindigital.com/blog/b-corp-business-case/" target="_blank">Wholegrain Digital</a> blog and has been republished with permission.</em></p> </div> <div class="clearfix text-formatted field field--name-field-article-subhead field--type-text-long field--label-hidden field__item"><p>B Corp certification shows that your open source business runs responsibly in terms of its environmental impact, its treatment of workers and suppliers, its impact on communities, and its governance.</p> </div> <div class="field field--name-field-lead-image field--type-entity-reference field--label-hidden field__item"><article class="media media--type-image media--view-mode-caption"> <div class="field field--name-field-media-image field--type-image field--label-hidden field__item"> <img src="/sites/default/files/lead-images/BIZ_WorkInPublic_4618517_1110_CS_A.png" width="520" height="292" alt="open data center Facebook" title="Two open data centers at Facebook" loading="lazy" /> </div> <div class="field field--name-field-caption field--type-text-long field--label-hidden caption field__item"><span class="caption__byline">Image by: </span><p>Opensource.com</p> </div> </article> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/tags/business" hreflang="en">Business</a></div> </div> <div class="hidden field field--name-field-listicle-title field--type-string field--label-hidden field__item">What to read next</div> <div class="field field--name-field-default-license field--type-list-string field--label-hidden field__item"><a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"> <img alt="Creative Commons License" src="/themes/osdc/assets/img/cc-by-sa-4.png" title="This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License." /></a>This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.</div> <section id='comments' class="field field--name-field-comments field--type-comment field--label-hidden comment-wrapper"> <div class="comments__count"> <div class="login"><a href="/user/register?absolute=1">Register</a> or <a href="/user/login?current=/rss.xml&amp;absolute=1">Login</a> to post a comment.</div> </div> </section> Sat, 14 May 2022 07:00:00 +0000 Tom Greenwood 70016 at https://opensource.com https://opensource.com/article/22/5/b-corp-open-source#comments