<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: arinak1017</title>
    <description>The latest articles on DEV Community by arinak1017 (@arilloid).</description>
    <link>https://dev.to/arilloid</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2023033%2F2cf0070a-1224-4c2f-8817-6fed698a05c3.jpeg</url>
      <title>DEV Community: arinak1017</title>
      <link>https://dev.to/arilloid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arilloid"/>
    <language>en</language>
    <item>
      <title>GCC: Automatic Function Multi-Versioning Wrap Up</title>
      <dc:creator>arinak1017</dc:creator>
      <pubDate>Thu, 12 Dec 2024 09:35:22 +0000</pubDate>
      <link>https://dev.to/arilloid/gcc-automatic-function-multi-versioning-wrap-up-264m</link>
      <guid>https://dev.to/arilloid/gcc-automatic-function-multi-versioning-wrap-up-264m</guid>
      <description>&lt;h2&gt;
  
  
  Before we start...
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have just stumbled upon my SPO600 series of blog posts, it has been created to document and share my learnings as I progress through my Software Portability and Optimization course at Seneca Polytechnic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As this term comes to an end and we officially wrap up our course project,  &lt;code&gt;implementing a new experimental feature (Automatic Function Multi-Versioning) in the GNU Compiler Collection&lt;/code&gt;, I want to reflect on the progress I’ve made and summarize my work. Throughout this project, I delved into GCC compiler passes, tackled the complexities of the GIMPLE intermediate representation, and developed initial logic for identifying and pruning redundant function clones.&lt;/p&gt;

&lt;p&gt;If you are curious to learn more about the project, feel free to check out my previous blog posts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/arilloid/gcc-automatic-function-multi-versioning-pt2-mfa"&gt;GCC: Automatic Function Multi-Versioning Pt.2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/arilloid/gcc-automatic-function-multi-versioning-pt1-59c5"&gt;GCC: Automatic Function Multi-Versioning Pt.1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/arilloid/building-gcc-from-source-on-aarch64-34d2"&gt;Building GCC from Source on AArch64&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How did I approach the experiments?
&lt;/h2&gt;

&lt;p&gt;Over the course of the last few weeks, I spent a significant amount of time navigating the GCC documentation, and experimenting with the dummy passes provided to us by our Professor, Chris Tyler.&lt;/p&gt;

&lt;p&gt;While working on my test pass, I approached the problem by isolating it from the complexity of the GCC compiler. Imagine designing a simple function that scans a piece of text or a file and flags redundant paragraphs. This analogy reflects what we’re trying to achieve but makes the concept easier to grasp. Instead of analyzing text, however, we’re examining the binaries of function clones and flagging them for pruning if they are redundant.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let’s take a look at the draft logic
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;compare_gimple_functions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gimple_seq&lt;/span&gt; &lt;span class="n"&gt;g1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gimple_seq&lt;/span&gt; &lt;span class="n"&gt;g2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;gimple_stmt_iterator&lt;/span&gt; &lt;span class="n"&gt;gsi1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gsi_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;gimple_stmt_iterator&lt;/span&gt; &lt;span class="n"&gt;gsi2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gsi_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;gsi_end_p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;gsi_end_p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;gimple&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;stmt1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gsi_stmt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;gimple&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;stmt2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gsi_stmt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Check if the statements are equivalent&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;stmt1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;stmt2&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;simple_cst_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stmt1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stmt2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;gsi_next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gsi1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;gsi_next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gsi2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;gsi_end_p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gsi_end_p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="n"&gt;pass_testprune&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;cgraph_node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;FOR_EACH_FUNCTION&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;analyzed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;function_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IDENTIFIER_POINTER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DECL_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"_1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;npos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_last_of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"_"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;base_func_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;cgraph_node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;base_node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;get_base_function&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_node&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;base_node&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;compare_gimple_functions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;get_body&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;get_body&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"PRUNE: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_func_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c_str&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"NOPRUNE: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_func_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c_str&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// anon namespace&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Understanding the proposed logic:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;compare_gimple_functions&lt;/code&gt;&lt;br&gt;
The function &lt;code&gt;compare_gimple_functions&lt;/code&gt; attempts to compare two GIMPLE statement sequences using a simple while loop. It iterates through the sequences with iterators and checks if the statements are equivalent using the &lt;code&gt;simple_cst_equal&lt;/code&gt; function. This logic is designed to mimic comparing lines in two files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;execute function&lt;/code&gt;&lt;br&gt;
The execute function is the core of this pass. It aims to process function clones within the binaries. Clones are typically identified by a suffix like &lt;code&gt;_1&lt;/code&gt; or &lt;code&gt;_2&lt;/code&gt; in their names. The pass compares each clone to its base function, flagging it for pruning if it matches.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Step-by-step execution&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Initial Safeguard:&lt;/code&gt; the &lt;code&gt;if (!node-&amp;gt;analyzed)&lt;/code&gt; block is intended to ensure that the compiler has analyzed the function before processing it. If not, the function is skipped. This check is meant to act as a safeguard.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Iterating Through Functions:&lt;/code&gt; inside the &lt;code&gt;FOR_EACH_FUNCTION&lt;/code&gt; loop, the pass attempts to identify clones by checking for function names ending with &lt;code&gt;_1&lt;/code&gt; or similar suffixes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Comparing Clones:&lt;/code&gt; the base function and its clone are compared using the &lt;code&gt;compare_gimple_functions&lt;/code&gt; method. If they appear identical, the pass prints &lt;code&gt;PRUNE: &amp;lt;function_name&amp;gt;&lt;/code&gt;. Otherwise, it prints &lt;code&gt;NOPRUNE: &amp;lt;function_name&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;You can find the source code with my newly added pass (&lt;a href="https://github.com/arilloid/gcc/blob/afmv-function-clone-comparison/gcc/tree-testprune.cc" rel="noopener noreferrer"&gt;tree-testprune.cc&lt;/a&gt;) in &lt;a href="https://github.com/arilloid/gcc/tree/afmv-function-clone-comparison" rel="noopener noreferrer"&gt;my personal fork of gcc-mirror&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To try running it:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clone the repo&lt;/li&gt;
&lt;/ul&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/arilloid/gcc.git
&lt;/code&gt;&lt;/pre&gt;


&lt;ul&gt;
&lt;li&gt;Switch to the &lt;code&gt;afmv-function-clone-comparison&lt;/code&gt; branch&lt;/li&gt;
&lt;/ul&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout afmv-function-clone-comparison
&lt;/code&gt;&lt;/pre&gt;


&lt;ul&gt;
&lt;li&gt;Follow the standard &lt;a href="[build%20process](https://dev.to/arilloid/building-gcc-from-source-on-aarch64-34d2)"&gt;build process&lt;/a&gt; to configure, build, and install the GCC compiler with the added pass.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Code refrences:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To see which files were modified to add a pass, refer to this commit: &lt;a href="https://github.com/arilloid/gcc/commit/5ece49951a1307dcd98af8953dff1bb371cb74da" rel="noopener noreferrer"&gt;5ece499&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The proposed logic for the pass is added in this commit:  &lt;a href="https://github.com/arilloid/gcc/commit/61428c7e1be7a9e3531c08b5ee1d04b8c7d680f0" rel="noopener noreferrer"&gt;61428c7&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The issues with the proposed solution
&lt;/h3&gt;

&lt;p&gt;The primary issue stems from the incorrect use of GIMPLE functions and macros. To address this, I spent a substantial amount of time studying the &lt;a href="https://gcc.gnu.org/onlinedocs/gccint/GIMPLE.html" rel="noopener noreferrer"&gt;GCC GIMPLE documentation&lt;/a&gt;. Through this effort, I gained a better understanding of how GIMPLE passes work. However, due to time constraints, I couldn’t get the pass to run successfully.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advice for future students
&lt;/h2&gt;

&lt;p&gt;My main advice to future students taking this course is to become very comfortable with configuring, building, and installing the GCC compiler. These foundational skills will save you a lot of time and frustration as you progress through the project.&lt;/p&gt;

&lt;p&gt;Additionally, dedicate time to thoroughly reading the documentation, particularly on GIMPLE, as the project revolves around designing a GIMPLE pass. The more familiar you are with the documentation, the more confident you’ll feel working with the GCC compiler. If we had a clear understanding of the necessary macros and operands from the start, completing the pass would have been much easier. However, since the documentation is mostly incomplete or hard to navigate, patience and persistence are key.&lt;/p&gt;

&lt;p&gt;Finally, get comfortable navigating the codebase and always use Git for version control. Even for small changes, commit your work regularly. Mistakes are inevitable, and being able to revert changes will save you countless hours. Trust me, this is an underrated yet crucial tip when working with a project as complex as GCC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Afterthoughts
&lt;/h2&gt;

&lt;p&gt;All in all, this journey has been a great experience. Although I wasn’t able to achieve a functional solution, I’m proud of the effort I put in, actively making changes, experimenting, and continuously rebuilding the GCC compiler. This process has given me confidence in my ability to work with large and complex codebases.&lt;/p&gt;

&lt;p&gt;In the professional world, the reality is that most of the time we’ll be working on someone else’s code, relying on company-specific libraries, and navigating official documentation to understand and extend functionality. This project closely mirrored that experience, and I’m grateful for the valuable skills and knowledge I gained along the way.&lt;/p&gt;

</description>
      <category>gcc</category>
      <category>compiling</category>
      <category>afmv</category>
    </item>
    <item>
      <title>6502 Length Converter</title>
      <dc:creator>arinak1017</dc:creator>
      <pubDate>Thu, 12 Dec 2024 07:21:20 +0000</pubDate>
      <link>https://dev.to/arilloid/6502-length-converter-541l</link>
      <guid>https://dev.to/arilloid/6502-length-converter-541l</guid>
      <description>&lt;h2&gt;
  
  
  Hello, Blog!
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have just stumbled upon my SPO600 series of blog posts, it has been created to document and share my learnings as I progress through my Software Portability and Optimization college course.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The end of the term is around the corner,  and I’m continuing to tackle my backlog of blog posts. Today, I’m sharing my experience completing Lab 3 for the Software Portability and Optimization course.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Check out my 1-st post about 6502 Assembly: &lt;a href="https://dev.to/arilloid/6502-assembly-intro-52ed"&gt;6502 Assembly Intro&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find the 6502 emulator I used here: &lt;a href="http://6502.cdot.systems/" rel="noopener noreferrer"&gt;6502 Emulator&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nice and colourful 6502 reference: &lt;a href="https://www.pagetable.com/c64ref/6502/?tab=2" rel="noopener noreferrer"&gt;Ultimate 6502 Reference&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sample code provided by our professor, Chris Tyler: &lt;a href="https://github.com/ctyler/6502js-code" rel="noopener noreferrer"&gt;6502js-code&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  An inches-and-feet to centimeter converter
&lt;/h2&gt;

&lt;p&gt;In Lab 3, we were tasked to write a 6502 assembly program involving math operations and string manipulation. To be brutally honest, I chose to write a length converter due to time constraints, creating a full game in assembly felt too ambitious given the complexity.&lt;/p&gt;

&lt;p&gt;That said, even writing a "simple" inches-and-feet-to-centimeters converter turned out to be incredibly challenging (just like writing anything in assembly).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To write this code I had to deal with:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Handling user input and strings:&lt;/strong&gt; learning to work with ROM routines for basic I/O.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Branching and jumps:&lt;/strong&gt; refreshing the fundamentals of conditional branching and program flow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Challenging arithmetic operations:&lt;/strong&gt; implementing multi-step calculations using decimal and binary-coded decimal (&lt;code&gt;BCD&lt;/code&gt;) math.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A LOT of trial and error:&lt;/strong&gt; iterating through countless debugging cycles to get everything working.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;I borrowed the printing logic from our professor, Chris Tyler. &lt;br&gt;
You can find the original implementation &lt;a href="https://github.com/ctyler/6502js-code/blob/master/colour-selector-live.6502" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Final Solution
&lt;/h2&gt;

&lt;p&gt;This program is a basic unit converter for lengths. Users can choose to convert from inches or feet to centimeters. After selecting a unit (1 for inches or 2 for feet), they enter a one-digit number (0-9). The program then calculates the result using approximated conversion factors (3 cm per inch or 30 cm per foot) and displays it in centimeters. It uses binary-coded decimal (&lt;code&gt;BCD&lt;/code&gt;) arithmetic for calculating conversions. Once the result is shown, the program starts over, letting users make another conversion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The main loop illustrates the overall structure of the program:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAINLOOP:
    JSR RESET             ; Reset variables
    JSR PRINT_WELCOME     ; Show welcome message
    JSR PROMPT_UNIT_INPUT ; Get unit selection
    JSR GET_NUMBER        ; Get number input
    JSR CONVERT           ; Convert to centimeters
    JSR SHOW_RESULT       ; Display the result
    JMP MAINLOOP          ; Restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Here is the key code logic:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; Get unit selection
GET_UNIT_INPUT:
    JSR CHRIN          ; Get input    
    CMP #$31           ; Check if 1 pressed
    BEQ UNIT_INCHES
    CMP #$32           ; Check if 2 pressed
    BEQ UNIT_FEET

    JMP GET_UNIT_INPUT ; If neither, keep waiting

; Handle inch selection
UNIT_INCHES:
    JSR PRINT
    DCB "I","n","c","h","e","s",32,"s","e","l","e","c","t","e","d","!",$0d,00
    LDA #$01
    STA UNIT_TYPE
    JMP PROMPT_NUMBER

; Handle feet selection
UNIT_FEET:
    JSR PRINT
    DCB "F","e","e","t",32,"s","e","l","e","c","t","e","d","!",$0d,00
    LDA #$02
    STA UNIT_TYPE
    JMP PROMPT_NUMBER

PROMPT_NUMBER:
    JSR PRINT
    DCB $0d,"E","N","T","E","R",32,"N","U","M","B","E","R",32
    DCB "(","0","-","9",")",":"
    DCB 32,00
    RTS

; Get number from user
GET_NUMBER:
    LDA #$00
    STA INPUT_NUM      ; Clear input storage

READ_DIGIT:
    JSR CHRIN          ; Get character from keyboard
    CMP #$0d           ; Check for ENTER key
    BEQ PROCESS_NUMBER

    CMP #$30           ; Check if less than 0
    BCC READ_DIGIT
    CMP #$3a           ; Check if greater than 9
    BCS READ_DIGIT

    CPX #$01           ; Already have a digit?
    BCS READ_DIGIT     ; If yes, ignore

    PHA                ; Save digit temporarily
    JSR CHROUT         ; Display it
    PLA                ; Retrieve digit

    AND #$0f           ; Convert from ASCII to binary
    STA INPUT_NUM      ; Store directly
    INX
    JMP READ_DIGIT

; Process completed number input
PROCESS_NUMBER:
    LDA #$0d           ; Print newline
    JSR CHROUT
    LDA INPUT_NUM      ; Load final number
    CPX #$00           ; Check if no digits entered
    BEQ READ_DIGIT     ; If none, keep waiting
    RTS

; Convert number based on selected unit
CONVERT:
    SED                ; Set decimal mode for BCD math
    LDA INPUT_NUM
    STA RESULT_L       ; Store initial value
    LDA #$00
    STA RESULT_H

    LDA UNIT_TYPE      ; Check which conversion to do
    CMP #$01
    BEQ CONVERT_INCHES
    JMP CONVERT_FEET

; Convert inches to centimeters (×3)
CONVERT_INCHES:
    LDA INPUT_NUM
    CLC
    ADC INPUT_NUM      ; ×2
    CLC
    ADC INPUT_NUM      ; ×3
    STA RESULT_L
    LDA #$00           ; Clear high byte
    STA RESULT_H
    CLD
    RTS

; Convert feet to centimeters (×30)
CONVERT_FEET:
    SED                ; Set decimal mode (for BCD math)

    ; Multiply by 10
    LDA INPUT_NUM
    STA RESULT_L       ; Store in RESULT_L
    LDA #$00
    STA RESULT_H       ; Clear high byte (start at zero)

    LDX #$09           ; Loop 9 times to add the number to itself (×10)
multiply_by_10:
    CLC
    LDA RESULT_L
    ADC INPUT_NUM
    STA RESULT_L
    LDA RESULT_H
    ADC #$00
    STA RESULT_H
    DEX
    BNE multiply_by_10

    ; Store the result of ×10 in a temporary variable
    LDA RESULT_L
    STA TEMP_L         ; Store low byte
    LDA RESULT_H
    STA TEMP_H         ; Store high byte

    ; Multiply by 3 (add twice more)
    LDY #$02           ; Loop 2 times to add the current result to itself
multiply_by_3:
    CLC
    LDA RESULT_L
    ADC TEMP_L
    STA RESULT_L
    LDA RESULT_H
    ADC TEMP_H
    STA RESULT_H
    DEY
    BNE multiply_by_3

    CLD                ; Clear decimal mode
    RTS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you’d like to see the complete implementation, feel free to check it out on &lt;a href="https://github.com/arilloid/assembly/blob/main/program.6502" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Execution of my converter
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Conversion from feet to cm (9 feet -&amp;gt; ~270 cm)
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhs0ae9zb546od94ljpfy.png" alt="Image description" width="517" height="401"&gt;
&lt;/li&gt;
&lt;li&gt;Conversion from inch to cm (8 inch -&amp;gt; ~24 cm)
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73rv0ilu5oq1ftkdxft0.png" alt="Image description" width="512" height="401"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Single-digit input&lt;/li&gt;
&lt;li&gt;No floating-point support&lt;/li&gt;
&lt;li&gt;Approximated conversion factors (&lt;code&gt;1 inch = 3 cm&lt;/code&gt; vs. &lt;code&gt;1 inch = 2.54 cm&lt;/code&gt;; &lt;code&gt;1 foot = 30 cm&lt;/code&gt; vs. &lt;code&gt;1 foot = 30.48 cm&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Lack of thorough error handling&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Afterthoughts
&lt;/h2&gt;

&lt;p&gt;This is the most complex assembly program I have written as of yet. Completing it required refreshing my understanding of how the 6502 processor handles data, performs arithmetic, and manages program flow. Along the way, I encountered some of the limitations of the 6502, such as its lack of native support for multiplication or floating-point arithmetic. Getting the multiplications right and implementing I/O operations were definitely the most challenging parts of this project. This lab really pushed me making the results more rewarding.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>6502 Math</title>
      <dc:creator>arinak1017</dc:creator>
      <pubDate>Wed, 11 Dec 2024 23:05:14 +0000</pubDate>
      <link>https://dev.to/arilloid/6502-math-5ggh</link>
      <guid>https://dev.to/arilloid/6502-math-5ggh</guid>
      <description>&lt;h2&gt;
  
  
  Hello, Blog!
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have just stumbled upon my SPO600 series of blog posts, it has been created to document and share my learnings as I progress through my Software Portability and Optimization college course.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The semester is wrapping up, and I'm working to catch up on my backlog of blog posts - bringing you a sudden throwback to 6502 assembly.&lt;/p&gt;

&lt;p&gt;In this post, I'll cover the second lab of the course. The main goal of this lab was getting familiar with performing math operations in 6502 assembly, specifically to animate the graphics on the screen.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Check out my 1-st post about 6502 Assembly: &lt;a href="https://dev.to/arilloid/6502-assembly-intro-52ed"&gt;6502 Assembly Intro&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find the 6502 emulator I used here: &lt;a href="http://6502.cdot.systems/" rel="noopener noreferrer"&gt;6502 Emulator&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nice and colourful 6502 reference: &lt;a href="https://www.pagetable.com/c64ref/6502/?tab=2" rel="noopener noreferrer"&gt;Ultimate 6502 Reference&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let's take a look at the starter code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;;
; draw-image-subroutine.6502
;
; This is a routine that can place an arbitrary 
; rectangular image on to the screen at given
; coordinates.
;
; Chris Tyler 2024-09-17
; Licensed under GPLv2+
;

;
; The subroutine is below starting at the 
; label "DRAW:"
;

; Test code for our subroutine
; Moves an image diagonally across the screen

; Zero-page variables
define XPOS $20
define YPOS $21

; Set up the data structure
; The syntax #&amp;lt;LABEL returns the low byte of LABEL
; The syntax #&amp;gt;LABEL returns the high byte of LABEL
LDA #&amp;lt;G_X     ; POINTER TO GRAPHIC
STA $10
LDA #&amp;gt;G_X
STA $11
LDA #$05
STA $12       ; IMAGE WIDTH
STA $13       ; IMAGE HEIGHT

; Set initial position X=Y=0
LDA #$00
STA XPOS
STA YPOS

; Main loop for diagonal animation
MAINLOOP:

  ; Set pointer to the image
  ; Use G_O or G_X as desired
  LDA #&amp;lt;G_O
  STA $10
  LDA #&amp;gt;G_O
  STA $11

  ; Place the image on the screen
  LDA #$10  ; Address in zeropage of the data structure
  LDX XPOS  ; X position
  LDY YPOS  ; Y position
  JSR DRAW  ; Call the subroutine

  ; Delay to show the image
  LDY #$00
  LDX #$50
DELAY:
  DEY
  BNE DELAY
  DEX
  BNE DELAY

  ; Set pointer to the blank graphic
  LDA #&amp;lt;G_BLANK
  STA $10
  LDA #&amp;gt;G_BLANK
  STA $11

  ; Draw the blank graphic to clear the old image
  LDA #$10 ; LOCATION OF DATA STRUCTURE
  LDX XPOS
  LDY YPOS
  JSR DRAW

  ; Increment the position
  INC XPOS
  INC YPOS

  ; Continue for 29 frames of animation
  LDA #28
  CMP XPOS
  BNE MAINLOOP

  ; Repeat infinitely
  JMP $0600

; ==========================================
;
; DRAW :: Subroutine to draw an image on 
;         the bitmapped display
;
; Entry conditions:
;    A - location in zero page of: 
;        a pointer to the image (2 bytes)
;        followed by the image width (1 byte)
;        followed by the image height (1 byte)
;    X - horizontal location to put the image
;    Y - vertical location to put the image
;
; Exit conditions:
;    All registers are undefined
;
; Zero-page memory locations
define IMGPTR    $A0
define IMGPTRH   $A1
define IMGWIDTH  $A2
define IMGHEIGHT $A3
define SCRPTR    $A4
define SCRPTRH   $A5
define SCRX      $A6
define SCRY      $A7

DRAW:
  ; SAVE THE X AND Y REG VALUES
  STY SCRY
  STX SCRX

  ; GET THE DATA STRUCTURE
  TAY
  LDA $0000,Y
  STA IMGPTR
  LDA $0001,Y
  STA IMGPTRH
  LDA $0002,Y
  STA IMGWIDTH
  LDA $0003,Y
  STA IMGHEIGHT

  ; CALCULATE THE START OF THE IMAGE ON
  ; SCREEN AND PLACE IN SCRPTRH
  ;
  ; THIS IS $0200 (START OF SCREEN) +
  ; SCRX + SCRY * 32
  ; 
  ; WE'LL DO THE MULTIPLICATION FIRST
  ; START BY PLACING SCRY INTO SCRPTR
  LDA #$00
  STA SCRPTRH
  LDA SCRY
  STA SCRPTR
  ; NOW DO 5 LEFT SHIFTS TO MULTIPLY BY 32
  LDY #$05     ; NUMBER OF SHIFTS
MULT:
  ASL SCRPTR   ; PERFORM 16-BIT LEFT SHIFT
  ROL SCRPTRH
  DEY
  BNE MULT

  ; NOW ADD THE X VALUE
  LDA SCRX
  CLC
  ADC SCRPTR
  STA SCRPTR
  LDA #$00
  ADC SCRPTRH
  STA SCRPTRH

  ; NOW ADD THE SCREEN BASE ADDRESS OF $0200
  ; SINCE THE LOW BYTE IS $00 WE CAN IGNORE IT
  LDA #$02
  CLC
  ADC SCRPTRH
  STA SCRPTRH
  ; NOTE WE COULD HAVE DONE TWO: INC SCRPTRH

  ; NOW WE HAVE A POINTER TO THE IMAGE IN MEM
  ; COPY A ROW OF IMAGE DATA
COPYROW:
  LDY #$00
ROWLOOP:
  LDA (IMGPTR),Y
  STA (SCRPTR),Y
  INY
  CPY IMGWIDTH
  BNE ROWLOOP

  ; NOW WE NEED TO ADVANCE TO THE NEXT ROW
  ; ADD IMGWIDTH TO THE IMGPTR
  LDA IMGWIDTH
  CLC
  ADC IMGPTR
  STA IMGPTR
  LDA #$00
  ADC IMGPTRH
  STA IMGPTRH

  ; ADD 32 TO THE SCRPTR
  LDA #32
  CLC
  ADC SCRPTR
  STA SCRPTR
  LDA #$00
  ADC SCRPTRH
  STA SCRPTRH

  ; DECREMENT THE LINE COUNT AND SEE IF WE'RE
  ; DONE
  DEC IMGHEIGHT
  BNE COPYROW

  RTS

; ==========================================

; 5x5 pixel images

; Image of a blue "O" on black background
G_O:
DCB $00,$0e,$0e,$0e,$00
DCB $0e,$00,$00,$00,$0e
DCB $0e,$00,$00,$00,$0e
DCB $0e,$00,$00,$00,$0e
DCB $00,$0e,$0e,$0e,$00

; Image of a yellow "X" on a black background
G_X:
DCB $07,$00,$00,$00,$07
DCB $00,$07,$00,$07,$00
DCB $00,$00,$07,$00,$00
DCB $00,$07,$00,$07,$00
DCB $07,$00,$00,$00,$07

; Image of a black square
G_BLANK:
DCB $00,$00,$00,$00,$00
DCB $00,$00,$00,$00,$00
DCB $00,$00,$00,$00,$00
DCB $00,$00,$00,$00,$00
DCB $00,$00,$00,$00,$00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This initial code creates a simple animation that moves the graphic diagonally from the top-left corner to the bottom-right. It uses a subroutine (&lt;code&gt;DRAW&lt;/code&gt;) to place the image at the correct screen address each frame, then erases the old position and updates &lt;code&gt;XPOS&lt;/code&gt; and &lt;code&gt;YPOS&lt;/code&gt; until it has moved 29 times. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzde587khfrlrullc2fn7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzde587khfrlrullc2fn7.gif" alt="Circle animation" width="524" height="481"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Let's make it bounce
&lt;/h2&gt;

&lt;p&gt;Our goal in this lab is to make the graphic the bitmapped display using 6502 math, instead of resetting after a set number of frames. &lt;/p&gt;

&lt;h4&gt;
  
  
  Steps taken:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. Set the initial position for the graphic:&lt;/strong&gt; I chose a non-corner starting point, so the graphic can properly bounce around the screen once I am finished with the logic&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; Set initial position X=Y=0
LDA #$00
STA XPOS
LDA #$05
STA YPOS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuyllvttojqf1xeqb91py.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuyllvttojqf1xeqb91py.gif" alt="Image description" width="525" height="481"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;2. Select an X increment that is -1 or +1, and a Y increment that is -1 or +1:&lt;/strong&gt; I created two new zero-page variables, &lt;code&gt;XINCREMENT&lt;/code&gt; and &lt;code&gt;YINCREMENT&lt;/code&gt;, and set them to 1. This means the image initially moves down-right. Using &lt;code&gt;#$01&lt;/code&gt; and &lt;code&gt;#$FF&lt;/code&gt; will allow us to move in different directions (&lt;code&gt;#$01&lt;/code&gt; - right/down; &lt;code&gt;#$FF&lt;/code&gt; - left/up)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; Zero-page variables
define XINCREMENT $22
define YINCREMENT $23

; Select the increments
LDA #$01
STA XINCREMENT  ; start moving right (+1)
LDA #$01
STA YINCREMENT  ; start moving down (+1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Successively move the graphic and make it bounce around the screen&lt;/strong&gt;: &lt;/p&gt;

&lt;p&gt;Figuring out the logic took quite some time, but the final code essentially works as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Increment the X coordinate:&lt;/strong&gt; on each iteration, the X position is adjusted by adding either +1 or -1, depending on the current horizontal increment value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check horizontal boundaries:&lt;/strong&gt; if the updated X position hits the right or left edge of the screen, the increment is reversed, causing the graphic to change direction horizontally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increment the Y coordinate:&lt;/strong&gt; next, the Y position is similarly updated based on its current vertical increment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check vertical boundaries:&lt;/strong&gt; if the Y position reaches the top or bottom edge, the vertical increment is also flipped, making the graphic bounce vertically as well.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ; setup code
  ; start of the main loop

  ; Increment the X position
  ; ---------------------------
  ; If XINCREMENT is #$01, we move right by adding 1
  ; If XINCREMENT is #$FF, we move left by adding -1

  LDA XPOS
  CLC             ; Clear carry before addition
  ADC XINCREMENT  ; Add XINCREMENT to XPOS
  STA XPOS

  ; Check horizontal boundaries
  ; ---------------------------

  ; Check if XPOS == XBOUNDARY (right edge)
  LDA XPOS
  CMP #XBOUNDARY
  BNE CHECK_X_LEFT ; If not equal, jump to check left boundary

  ; If we hit the right boundary, reverse direction
  LDA #$FF
  STA XINCREMENT

CHECK_X_LEFT:
  ; Check if XPOS == 0 (left edge)
  LDA XPOS
  CMP #0
  BNE UPDATE_Y ; If not equal, jump to update Y coordinate

  ; If we hit the left boundary and direction == left, reverse direction
  LDA #$01
  STA XINCREMENT

UPDATE_Y:
  ; Update YPOS using YINCREMENT
  ; ----------------------------
  ; If YINCREMENT is #$01, we move down by adding 1
  ; If YINCREMENT is #$FF, we move up by adding -1

  LDA YPOS
  CLC             ; Clear carry before addition
  ADC YINCREMENT  ; Add YINCREMENT to YPOS
  STA YPOS

  ; Check vertical boundaries
  ; ---------------------------

  ; Check if YPOS == YBOUNDARY (bottom edge)
  LDA YPOS
  CMP #YBOUNDARY
  BNE CHECK_Y_TOP  ; If not equal, jump to check the top edge

  ; If we hit bottom edge, reverse direction
  LDA #$FF
  STA YINCREMENT

CHECK_Y_TOP:
  ; Check if YPOS == 0 (top edge)
  LDA YPOS
  CMP #0  ; If no boundary hit, continue moving
  BNE MAINLOOP

  ; If we hit top edge, reverse direction
  LDA #$01
  STA YINCREMENT

  JMP MAINLOOP  ; Return to the main loop

; DRAW subroutine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1bmb2ubw43yn190qbptu.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1bmb2ubw43yn190qbptu.gif" alt="Image description" width="525" height="481"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Full Solution
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you’d like to see the complete implementation, feel free to check it out on &lt;a href="https://github.com/arilloid/assembly/blob/main/bouncing_graphic.6502" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Afterthoughts
&lt;/h2&gt;

&lt;p&gt;Assembly programming is certainly very tedious, especially after stepping away from it for a while (the process of readjusting is very real!). However, the complete lack of abstraction also has its benefits: it forces you to gain an intimate understanding of every tiny detail of the code's logic.&lt;/p&gt;

</description>
      <category>6502</category>
      <category>assembly</category>
    </item>
    <item>
      <title>The Open Source Finale: Pt. 3</title>
      <dc:creator>arinak1017</dc:creator>
      <pubDate>Wed, 11 Dec 2024 13:47:59 +0000</pubDate>
      <link>https://dev.to/arilloid/the-open-source-finale-pt-3-5b1l</link>
      <guid>https://dev.to/arilloid/the-open-source-finale-pt-3-5b1l</guid>
      <description>&lt;h2&gt;
  
  
  Hello, Blog!
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have just stumbled upon my OSD600 series of blog posts, it has been created to document and share my learnings as I progress through my Open Source Development college course.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This post wraps up the final stretch of my Open Source course, Release 0.4. In it, I’ll share updates on my latest contributions and give an overview of what I’ve achieved in this assignment.&lt;/p&gt;

&lt;h2&gt;
  
  
  A bit about Release 0.4
&lt;/h2&gt;

&lt;p&gt;For our final assignment, we were tasked to leverage the skills and experience we’ve built over the term to work on something meaningful to us in one way or another.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you missed how I started working on 0.4, check out my previous posts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/arilloid/the-open-source-finale-pt1-4kkf"&gt;The Open Source Finale: Pt.1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/arilloid/the-open-source-finale-pt-2-39m3"&gt;The Open Source Finale: Pt. 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Last Issue follow up
&lt;/h2&gt;

&lt;p&gt;In my last post, I shared how I created a draft Pull Request for the following issue:&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/move-fast-and-break-things/aibyss/issues/43" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        feat: add ability to view the current game without having to log in
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#43&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/yurijmikhalevich" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F4187729%3Fv%3D4" alt="yurijmikhalevich avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/yurijmikhalevich" rel="noopener noreferrer"&gt;yurijmikhalevich&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/move-fast-and-break-things/aibyss/issues/43" rel="noopener noreferrer"&gt;&lt;time&gt;Sep 29, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Display the current game at the login screen.&lt;/p&gt;
&lt;p&gt;E.g. we should update the login screen to look exactly like the screen after login, but instead of the code editor, we should display the login form.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/move-fast-and-break-things/aibyss/issues/43" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I had implemented the base requirements and left a comment asking for feedback from the maintainer to clarify some doubts:&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/move-fast-and-break-things/aibyss/pull/92#issuecomment-2526382413" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Comment for
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#92&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F105298302%3Fu%3D773354456431193f4bc8af01e227e5f584e3d61f%26v%3D4" alt="arilloid avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;arilloid&lt;/a&gt;
        &lt;/strong&gt; commented on &lt;a href="https://github.com/move-fast-and-break-things/aibyss/pull/92#issuecomment-2526382413" rel="noopener noreferrer"&gt;&lt;time&gt;Dec 08, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Hello &lt;a class="mentioned-user" href="https://dev.to/yurijmikhalevich"&gt;@yurijmikhalevich&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;I have refactored the login page!&lt;/p&gt;
&lt;p&gt;I have a doubt about the login form.
Would it be better to move into a sperate component, or is it okay just to leave it as is?
(I tried to move the form into a separate component, but this seems to have disrupted how the E2E tests interact with the page elements)&lt;/p&gt;
&lt;p&gt;Also, would you suggest displaying any kind of placeholder/animation while the game screen is loading?&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/move-fast-and-break-things/aibyss/pull/92#issuecomment-2526382413" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h4&gt;
  
  
  What happened next?
&lt;/h4&gt;

&lt;p&gt;I quickly received feedback from the maintainer. First, they pointed out that copying the resizing logic from another page wasn’t ideal and questioned whether it was necessary on the login page. They also addressed my question about the login form. Initially, I had moved it into a separate component, but since this caused the e2e tests to fail, I kept it inside the login page for the time being.&lt;/p&gt;

&lt;p&gt;The maintainer suggested that it would be better to move the login form into a separate component and encouraged me to adjust the e2e tests if necessary.&lt;/p&gt;

&lt;h4&gt;
  
  
  Addressing feedback
&lt;/h4&gt;

&lt;p&gt;Most of the changes were straightforward. I simplified the &lt;code&gt;/login&lt;/code&gt; page by removing the resizing logic, moved the login form into a separate component, and investigated the e2e tests.&lt;/p&gt;

&lt;p&gt;Initially, I couldn’t run the e2e tests locally due to an issue where one of the testing commands failed because my absolute file path contained a space. Once I fixed that, I was able to run the tests successfully. However, the login tests were still failing due to the default 30-second timeout being insufficient for the tests to complete. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jcepqe3jglyb2y2w0nd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jcepqe3jglyb2y2w0nd.png" alt="Image description" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the project uses &lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt; for testing, I consulted their &lt;a href="https://playwright.dev/docs/test-timeouts#:~:text=Playwright%20Test%20enforces%20a%20timeout,included%20in%20the%20test%20timeout" rel="noopener noreferrer"&gt;documentation on timeouts&lt;/a&gt; to find a solution. I increased the timeout for both tests to 60 seconds to resolve the issue. With this adjustment, the tests ran smoothly. After confirming everything was working as expected, I pushed my changes and reached out to the maintainer for another review.&lt;/p&gt;

&lt;h4&gt;
  
  
  Final Touches
&lt;/h4&gt;

&lt;p&gt;The maintainer left two minor comments, which I quickly addressed. Now, I’m waiting for my PR to be merged.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F09kn5qv41p2154js4gai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F09kn5qv41p2154js4gai.png" alt="Comment" width="800" height="127"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4w06qzurv99n32xtg152.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4w06qzurv99n32xtg152.png" alt="Discussion thread 1" width="800" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgciu6krb342peqpv9bv3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgciu6krb342peqpv9bv3.png" alt="Discussion thread 2" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;This assignment concludes my Open Source Development course. While I couldn’t get both of my Pull Requests merged by the deadline due to some life circumstances, I still learned a lot and accomplished most of my goals. Here’s what I achieved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Contributed to high-priority issues:&lt;/strong&gt; I addressed two &lt;code&gt;high priority&lt;/code&gt; issues, making key features of the app publicly accessible for unauthenticated users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gained hands-on experience with new tools and frameworks:&lt;/strong&gt; now I know how to build full-stack &lt;code&gt;Vue.js&lt;/code&gt; apps using &lt;code&gt;Nuxt&lt;/code&gt;, write &lt;code&gt;Playwright&lt;/code&gt; tests. /+ I learned a bit more about &lt;code&gt;Prisma ORM&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved communication with project maintainers:&lt;/strong&gt; Unlike my previous contributions, where feedback was limited, I had a more engaging back-and-forth with the maintainer. So, I finally had the chance to polish features based on feedback and make necessary adjustments to meet project expectations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Afterthoughts
&lt;/h2&gt;

&lt;p&gt;The Open Source course at Seneca pushed me out of my comfort zone. I’m no longer as intimidated by collaboration or sharing my code with others. I’ve become much more proficient with &lt;code&gt;Git&lt;/code&gt; and, overall, feel more confident in my programming skills despite the hiccups I faced throughout the course.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Update! My changes got merged 😄 - &lt;a href="https://github.com/move-fast-and-break-things/aibyss/commit/1e0f17d93031b570d60880fb56275957d83dc2d3" rel="noopener noreferrer"&gt;commit&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>The Open Source Finale: Pt. 2</title>
      <dc:creator>arinak1017</dc:creator>
      <pubDate>Tue, 10 Dec 2024 06:03:49 +0000</pubDate>
      <link>https://dev.to/arilloid/the-open-source-finale-pt-2-39m3</link>
      <guid>https://dev.to/arilloid/the-open-source-finale-pt-2-39m3</guid>
      <description>&lt;h2&gt;
  
  
  Hello, Blog
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have just stumbled upon my OSD600 series of blog posts, it has been created to document and share my learnings as I progress through my Open Source Development college course.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this blog post, I’ll share my progress on the course's final assignment, Release 0.4.&lt;/p&gt;

&lt;h2&gt;
  
  
  A bit about Release 0.4
&lt;/h2&gt;

&lt;p&gt;For our final assignment, we were tasked to leverage the skills and experience we’ve built over the term to work on something meaningful to us in one way or another. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you missed how I started working on 0.4, check out my &lt;a href="https://dev.to/arilloid/the-open-source-finale-pt1-4kkf"&gt;previous post&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Where am I at right now?
&lt;/h2&gt;

&lt;p&gt;At this stage,  I’ve already made significant progress. I’ve gotten a hang of the stack, picked up two issues, closed one, and created a draft Pull Request for the second.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/move-fast-and-break-things" rel="noopener noreferrer"&gt;
        move-fast-and-break-things
      &lt;/a&gt; / &lt;a href="https://github.com/move-fast-and-break-things/aibyss" rel="noopener noreferrer"&gt;
        aibyss
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🚧 UNDER DEVELOPMENT 🚧 Aibyss: code your AI to compete in a survival game
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🚧 UNDER DEVELOPMENT 🚧 Aibyss: code your AI to compete in a survival game&lt;/h1&gt;

&lt;/div&gt;
&lt;div&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/move-fast-and-break-things/aibyss/refs/heads/main/public/og-image.png"&gt;&lt;img alt="Aibyss social image" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmove-fast-and-break-things%2Faibyss%2Frefs%2Fheads%2Fmain%2Fpublic%2Fog-image.png" width="600px"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Setup&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;install &lt;a href="https://nodejs.org/en" rel="nofollow noopener noreferrer"&gt;node.js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;(on macOS only)&lt;/strong&gt; install &lt;code&gt;node-gyp&lt;/code&gt;: &lt;code&gt;npm install -g node-gyp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;install the dependencies: &lt;code&gt;npm ci&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Development server&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Start the development server on &lt;code&gt;http://localhost:3000&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run dev&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Create new user&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run create-user &lt;span class="pl-k"&gt;&amp;lt;&lt;/span&gt;username&lt;span class="pl-k"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Running the tests&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;unit tests&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run &lt;span class="pl-c1"&gt;test&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;e2e tests&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;First, setup e2e tests by running &lt;code&gt;npm run test:e2e:install&lt;/code&gt;, then run the tests with:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run test:e2e&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Contributors guide&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;We follow &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="nofollow noopener noreferrer"&gt;conventional commits&lt;/a&gt;, name your PRs accordingly&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Production&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Build the application for production:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run build&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Locally preview production build:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run preview&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Check out the &lt;a href="https://nuxt.com/docs/getting-started/deployment" rel="nofollow noopener noreferrer"&gt;deployment documentation&lt;/a&gt; for more information.&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/move-fast-and-break-things/aibyss" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;The project I’m contributing to, AIbyss, uses various tools and technologies, many of which were entirely new to me. Familiarizing myself with the stack was one of the goals I set for Release 0.4, so I took the time to explore the project structure and dive into the documentation for each tool and framework. &lt;/p&gt;

&lt;p&gt;Now, I have a basic understanding of building &lt;code&gt;Vue.js&lt;/code&gt; apps!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The key components of the stack:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nuxt.com/" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt;- a powerful open-source framework built on top of &lt;code&gt;Vue.js&lt;/code&gt;, designed for creating dynamic full-stack web applications. It provides a great way to build full-stack &lt;code&gt;Vue&lt;/code&gt; apps.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Just take a look at &lt;code&gt;Nuxt DevTools&lt;/code&gt;!&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwwu2pvqoy1epz1t4rbla.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwwu2pvqoy1epz1t4rbla.png" alt="Image description" width="800" height="310"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue.js&lt;/a&gt; - a "progressive JavaScript framework" focused on building user interfaces. &lt;code&gt;Vue.js&lt;/code&gt; piqued my interest for a while, and after finally using it in this project, I can see why it’s so popular in the developer community - it's both intuitive and flexible.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.prisma.io/" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt; - a modern Object-Relational Mapping (ORM) tool for simplifying database interactions. Having heard much about it, I am excited to incorporate it into future projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My contributions (as of now)
&lt;/h2&gt;

&lt;p&gt;If you’ve read my first post, you’ll know that my ultimate goal was to contribute to the project in a meaningful way. To achieve this, I focused on taking and resolving issues labelled as &lt;code&gt;high priority.&lt;/code&gt; So far, I’ve successfully closed one issue and created a draft Pull Request for the second, marking steady progress toward my goal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue 1 - Making the Rating Page publicly accessible
&lt;/h3&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/move-fast-and-break-things/aibyss/issues/42" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        feat: let the users view the rating page without having to log in
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#42&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/yurijmikhalevich" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F4187729%3Fv%3D4" alt="yurijmikhalevich avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/yurijmikhalevich" rel="noopener noreferrer"&gt;yurijmikhalevich&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/move-fast-and-break-things/aibyss/issues/42" rel="noopener noreferrer"&gt;&lt;time&gt;Sep 29, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;This is a follow-up idea to the #37 and should be done after it is merged.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/move-fast-and-break-things/aibyss/issues/42" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;When I first picked up this issue, I thought it would be straightforward since the repo maintainer provided clear guidance on where to start. However, it turned out to be more challenging than expected. The task involved a lot of debugging and required a deeper understanding of how routing and middleware were set up in the project.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/move-fast-and-break-things/aibyss/issues/42#issuecomment-2510945849" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Comment for
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#42&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/yurijmikhalevich" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F4187729%3Fv%3D4" alt="yurijmikhalevich avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/yurijmikhalevich" rel="noopener noreferrer"&gt;yurijmikhalevich&lt;/a&gt;
        &lt;/strong&gt; commented on &lt;a href="https://github.com/move-fast-and-break-things/aibyss/issues/42#issuecomment-2510945849" rel="noopener noreferrer"&gt;&lt;time&gt;Dec 02, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Hi &lt;a class="mentioned-user" href="https://dev.to/arilloid"&gt;@arilloid&lt;/a&gt;! 👋&lt;/p&gt;
&lt;p&gt;Thank you for reaching out! Yes, of course, you can take this issue! It's a good one to start with. It should take a smaller change to the &lt;code&gt;PUBLIC_PATHS&lt;/code&gt; in &lt;code&gt;server/middleware/auth.ts&lt;/code&gt;, and let's move the "rating" link to the header so it's accessible from any page. Let me know if you have any questions!&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/move-fast-and-break-things/aibyss/issues/42#issuecomment-2510945849" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I began by moving the rating link from &lt;code&gt;GameScreen.vue&lt;/code&gt; to &lt;code&gt;GlobalHeader.vue&lt;/code&gt;. This required locating the necessary components, removing the link from the game screen, and placing it in the global header to ensure it was displayed for both authenticated and unauthenticated users. &lt;/p&gt;

&lt;p&gt;After confirming the link was accessible from the header, I modified the public paths array inside the authentication middleware to include the &lt;code&gt;/rating&lt;/code&gt; path. The middleware checks if a requested path is public and redirects unauthenticated users to the login page if it isn’t.&lt;/p&gt;

&lt;p&gt;I assumed this would resolve the issue, but I was met with a rendering error when I clicked the rating link while not logged in. The error indicated that &lt;code&gt;.toFixed(2)&lt;/code&gt; was being called on &lt;code&gt;null&lt;/code&gt; values in &lt;code&gt;RatingTable.vue&lt;/code&gt;. I suspected this was because the &lt;code&gt;api/rating&lt;/code&gt; fetch wasn’t returning any data in the development environment. To test this, I updated the component to conditionally render the values with &lt;code&gt;.toFixed(2)&lt;/code&gt; only if rating data was available.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wpysdq5uhs5jz5qiqn6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wpysdq5uhs5jz5qiqn6.png" alt="Image description" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This allowed me to access the rating page without logging in, but something was still wrong, as the table displayed blank entries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpawspyc2x9vwixvxbczw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpawspyc2x9vwixvxbczw.png" alt="Image description" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To investigate the issue, I checked &lt;code&gt;rating.get.ts&lt;/code&gt; to confirm that fetching rating data didn’t rely on user-specific information. Then, I added &lt;code&gt;console.log()&lt;/code&gt; statements to the middleware logic in &lt;code&gt;/server/middleware/auth.ts&lt;/code&gt; to understand how redirects were handled. I also logged the status of the &lt;code&gt;api/rating&lt;/code&gt; fetch on the rating page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fei49lesqs9gdzp6e6xq1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fei49lesqs9gdzp6e6xq1.png" alt="Image description" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I noticed that, for some reason, there was a redirect to &lt;code&gt;/API/auth/users.&lt;/code&gt; Then, I thought: "It must be it! Somewhere in the code, there is an attempt to fetch user details while not being authenticated, resulting in the redirect to the &lt;code&gt;/login&lt;/code&gt; being sent back to the rating page instead of the rating info". My assumption was partially confirmed by displaying the result of the &lt;code&gt;/api/rating fetch&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The logs revealed a redirect to &lt;code&gt;/api/auth/user&lt;/code&gt;. I thought that it was IT, that I found the underlying issue, as this suggested that an fetching user details was causing a redirect to the login page, which was being returned to the rating page instead of the actual ratings data. I confirmed an attempted redirect to &lt;code&gt;/login&lt;/code&gt; by inspecting the result of the &lt;code&gt;/api/rating&lt;/code&gt; fetch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6q9s3a4rflzayrcn62y5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6q9s3a4rflzayrcn62y5.png" alt="Image description" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I discovered that the global header was making a fetch request to &lt;code&gt;/api/auth/user&lt;/code&gt;, and I suspected this was causing the issue. To test this, I temporarily removed the logic that fetched user data from the header. However, the problem persisted, and the rating page was still rendered incorrectly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgkgaraqwt3ulaitxi7a8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgkgaraqwt3ulaitxi7a8.png" alt="Image description" width="800" height="689"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, I decided to revisit my changes and carefully re-examine the logs. It became clear that I also needed to include &lt;code&gt;/api/rating&lt;/code&gt; in the public paths array to allow it to be accessed without authentication.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6dd8a0wzfedd5grj2qrx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6dd8a0wzfedd5grj2qrx.png" alt="Image description" width="800" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After adding &lt;code&gt;/api/rating&lt;/code&gt; to the public paths, everything worked as expected! It surprised me that such a small oversight caused so much debugging, but I was glad to have resolved the issue and was ready to submit my PR.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/move-fast-and-break-things/aibyss/pull/90" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        feat(rating): make rating page publicly accessible
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#90&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F105298302%3Fv%3D4" alt="arilloid avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;arilloid&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/move-fast-and-break-things/aibyss/pull/90" rel="noopener noreferrer"&gt;&lt;time&gt;Dec 06, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How does this PR impact the user?&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/user-attachments/assets/41f5cb0d-b87a-4852-bbc3-a905fdebe2bb" rel="noopener noreferrer"&gt;https://github.com/user-attachments/assets/41f5cb0d-b87a-4852-bbc3-a905fdebe2bb&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Description&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Made the rating page accessible to unauthenticated users by moving the link from game screen to the global header, and adding &lt;code&gt;/rating&lt;/code&gt; and &lt;code&gt;/api/rating&lt;/code&gt; to the list of public paths.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Checklist&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[x] my PR is focused and contains one wholistic change&lt;/li&gt;
&lt;li&gt;[x] I have added screenshots or screen recordings to show the changes&lt;/li&gt;
&lt;/ul&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/move-fast-and-break-things/aibyss/pull/90" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I opened a draft PR and asked the maintainer for feedback on the link’s placement in the global header. I also suggested conditionally rendering the link so it wouldn’t appear on the rating page itself. However, the maintainer was satisfied with the changes and merged my PR.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpdtb69m2tlwgyn3lt0m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpdtb69m2tlwgyn3lt0m.png" alt="Image description" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue 2 - Make the Current Game publicly available
&lt;/h3&gt;

&lt;p&gt;After my &lt;a href="https://github.com/move-fast-and-break-things/aibyss/pull/90" rel="noopener noreferrer"&gt;1-st Pull Request&lt;/a&gt;, I quickly picked up a &lt;code&gt;high priority&lt;/code&gt; issue.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/move-fast-and-break-things/aibyss/issues/43" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        feat: add ability to view the current game without having to log in
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#43&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/yurijmikhalevich" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F4187729%3Fv%3D4" alt="yurijmikhalevich avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/yurijmikhalevich" rel="noopener noreferrer"&gt;yurijmikhalevich&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/move-fast-and-break-things/aibyss/issues/43" rel="noopener noreferrer"&gt;&lt;time&gt;Sep 29, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Display the current game at the login screen.&lt;/p&gt;
&lt;p&gt;E.g. we should update the login screen to look exactly like the screen after login, but instead of the code editor, we should display the login form.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/move-fast-and-break-things/aibyss/issues/43" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Implementing the base requirements for this issue was relatively straightforward, as I was already familiar with the project and its routing setup. The maintainer requested that the login screen be updated to be exactly like the main game screen, with the only difference being that the left panel should instead display the login form.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frb2cihaj0rmmon08czkz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frb2cihaj0rmmon08czkz.png" alt="Image description" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To achieve this, I added &lt;code&gt;/api/state&lt;/code&gt; route used to fetch game state information for the game screen to the public paths in the middleware. I then reused the layout template and separator logic from the &lt;code&gt;index.vue&lt;/code&gt; (main game page) to build the login screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code Reference:&lt;/strong&gt; &lt;code&gt;index.vue&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex flex-col h-screen w-screen&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GlobalHeader&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex flex-grow p-1 h-[90%]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;
        &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resizeEditorElement&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex min-w-[300px] h-full w-1/2 mr-2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CodeEditor&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;
        &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;separator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;w-1 bg-gray-300 cursor-ew-resize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;
        &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resizeGameElement&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex min-w-[300px] w-1/2 overflow-auto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GameScreen&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onUnmounted&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isResizing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialWidthEditor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialWidthGame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resizeEditorElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLDivElement&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resizeGameElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLDivElement&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;separator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLDivElement&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;startResize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;resizeEditorElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unexpected: no resizeEditorElement&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;resizeGameElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unexpected: no resizeGameElement&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;isResizing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;initialX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;initialWidthEditor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resizeEditorElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;initialWidthGame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resizeGameElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleResize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;resizeEditorElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unexpected: no resizeEditorElement&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;resizeGameElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unexpected: no resizeGameElement&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isResizing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientX&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;initialX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newWidthEditor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialWidthEditor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newWidthGame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialWidthGame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;resizeEditorElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;newWidthEditor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;resizeGameElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;newWidthGame&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stopResize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;isResizing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;separator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unexpected: no separator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;separator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mousedown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;startResize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mousemove&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleResize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mouseup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stopResize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;onUnmounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;separator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unexpected: no separator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;separator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mousedown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;startResize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mousemove&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleResize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mouseup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stopResize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;resizeEditorElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;resizeGameElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;separator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;My only issue with the code was that I initially moved the login form into a separate component, &lt;code&gt;LoginForm.vue&lt;/code&gt;, for better modularity. However, I discovered that this change caused issues with existing e2e (end-to-end) tests. The tests appeared to break because the final DOM structure rendered differently when the login form was imported as a separate component. (But I noticed a cool thing: because of &lt;code&gt;Nuxt&lt;/code&gt;, there was no need for explicit component export/import!).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrl1ob6ov71ji6yr3sp1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrl1ob6ov71ji6yr3sp1.png" alt="Image description" width="800" height="111"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I moved the login form back to the login page to resolve the issue, ensuring the DOM structure remained consistent. Once I confirmed that the login form worked as expected and the game screen displayed correctly on the login page, I submitted a draft pull request.&lt;/p&gt;

&lt;p&gt;I also asked the maintainer for feedback on whether the login form should remain part of the page or be modularized into a separate component. Additionally, I mentioned how trying to move the form to a separate component tempered with the existing e2e tests.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/move-fast-and-break-things/aibyss/pull/92" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        feat(login): view current game without login
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#92&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F105298302%3Fv%3D4" alt="arilloid avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;arilloid&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/move-fast-and-break-things/aibyss/pull/92" rel="noopener noreferrer"&gt;&lt;time&gt;Dec 08, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How does this PR impact the user?&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/user-attachments/assets/7f2fea98-3c8b-4cc6-a313-8e19c729f4ab" rel="noopener noreferrer"&gt;https://github.com/user-attachments/assets/7f2fea98-3c8b-4cc6-a313-8e19c729f4ab&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Description&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Added &lt;code&gt;/api/state&lt;/code&gt; to public paths to make current game publicly accessible.&lt;/li&gt;
&lt;li&gt;Updated the login screen to display the login form on the left and the current game on the right (reused the code from &lt;code&gt;index.vue&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Limitations&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;The game screen takes a couple of seconds to load.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Checklist&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[x] my PR is focused and contains one wholistic change&lt;/li&gt;
&lt;li&gt;[x] I have added screenshots or screen recordings to show the changes&lt;/li&gt;
&lt;/ul&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/move-fast-and-break-things/aibyss/pull/92" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;




&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/move-fast-and-break-things/aibyss/pull/92#issuecomment-2526382413" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Comment for
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#92&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F105298302%3Fu%3D773354456431193f4bc8af01e227e5f584e3d61f%26v%3D4" alt="arilloid avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;arilloid&lt;/a&gt;
        &lt;/strong&gt; commented on &lt;a href="https://github.com/move-fast-and-break-things/aibyss/pull/92#issuecomment-2526382413" rel="noopener noreferrer"&gt;&lt;time&gt;Dec 08, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Hello &lt;a class="mentioned-user" href="https://dev.to/yurijmikhalevich"&gt;@yurijmikhalevich&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;I have refactored the login page!&lt;/p&gt;
&lt;p&gt;I have a doubt about the login form.
Would it be better to move into a sperate component, or is it okay just to leave it as is?
(I tried to move the form into a separate component, but this seems to have disrupted how the E2E tests interact with the page elements)&lt;/p&gt;
&lt;p&gt;Also, would you suggest displaying any kind of placeholder/animation while the game screen is loading?&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/move-fast-and-break-things/aibyss/pull/92#issuecomment-2526382413" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;At the time of writing this post, I am awaiting feedback from the maintainer. As soon as I receive their suggestions, I plan to go ahead and implement any necessary changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Afterthoughts...
&lt;/h2&gt;

&lt;p&gt;I’ve already learned quite a lot about &lt;code&gt;Vue.js&lt;/code&gt; and &lt;code&gt;Nuxt&lt;/code&gt; and feel satisfied with my progress. + One thing I’ve noticed is how much easier it has become, especially toward the end of the term, to navigate the structure of unfamiliar projects, even those built with frameworks I’ve never worked with before!&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>The Open Source Finale: Pt.1</title>
      <dc:creator>arinak1017</dc:creator>
      <pubDate>Fri, 06 Dec 2024 15:55:33 +0000</pubDate>
      <link>https://dev.to/arilloid/the-open-source-finale-pt1-4kkf</link>
      <guid>https://dev.to/arilloid/the-open-source-finale-pt1-4kkf</guid>
      <description>&lt;h2&gt;
  
  
  Hello, Blog!
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have just stumbled upon my OSD600 series of blog posts, it has been created to document and share my learnings as I progress through my Open Source Development college course.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lately, I have been falling behind on blogging. This post, for instance, should have gone up last week, right after I wrapped up the planning phase for our final Open Source assignment. But as they say, better late than never! Today, I’ll take you back to where I was a week ago to share how I approached the planning process, the project I chose to work on, and the personal goals I set for myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  A bit about Release 0.4
&lt;/h2&gt;

&lt;p&gt;For our final assignment, we were tasked to leverage the skills and experience we’ve built over the term to work on something meaningful to us in one way or another. &lt;/p&gt;

&lt;h2&gt;
  
  
  Looking for the right project
&lt;/h2&gt;

&lt;p&gt;Finding the right project to work on was the toughest part of the planning stage. I spent hours browsing popular open-source repositories and reading countless articles on "best open-source projects for beginners" (half of which list projects like Linux Kernel as a great starting point for beginners). As that approach wasn’t working, I decided to focus on something fun. Something that I wanted to try for a long time but didn't have a chance (or at least so I thought) to do.&lt;/p&gt;

&lt;p&gt;The first idea that came to mind was exploring fun VSCode extensions. I’ve always loved quirky extensions made to bring a smile to a coder's face right in their IDE. However, after doing some research, I discovered that most of these extensions are more like personal side projects than active open-source initiatives. Many of the repositories hadn’t been updated in over a year.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For example, I tried contributing to the repo of a VSCode extension featuring one of my favourite memes, (&lt;a href="https://marketplace.visualstudio.com/items?itemName=VirejDasani.incredibly-in-your-face" rel="noopener noreferrer"&gt;Incredibly In Your Face&lt;/a&gt;). It’s a simple but genuinely funny project with over 100k downloads on the VSCode Marketplace. I picked an issue, submitted a comment, and waited for a response. Unfortunately, I haven't heard back since the project is no longer maintained.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/virejdasani/Incredibly-InYourFace/issues/6#issuecomment-2480621366" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Comment for
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#6&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F105298302%3Fu%3D773354456431193f4bc8af01e227e5f584e3d61f%26v%3D4" alt="arilloid avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;arilloid&lt;/a&gt;
        &lt;/strong&gt; commented on &lt;a href="https://github.com/virejdasani/Incredibly-InYourFace/issues/6#issuecomment-2480621366" rel="noopener noreferrer"&gt;&lt;time&gt;Nov 16, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Hello &lt;a class="mentioned-user" href="https://dev.to/virejdasani"&gt;@virejdasani&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;I know it's been a while since you have released the extension, but I was wondering if you are still open to accepting Pull Requests.&lt;/p&gt;
&lt;p&gt;I’m a student just starting my Open Source journey and looking to play around with some VSCode extensions &amp;amp; I would love to contribute to yours as I find it genuinely funny!&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/virejdasani/Incredibly-InYourFace/issues/6#issuecomment-2480621366" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/blockquote&gt;

&lt;p&gt;With time running out, I decided to pivot again and look into the repositories my classmates worked on during Release 0.3.&lt;/p&gt;

&lt;p&gt;And then, finally, I found the perfect project!&lt;/p&gt;

&lt;h2&gt;
  
  
  The project I picked
&lt;/h2&gt;

&lt;p&gt;The project I chose is a game in active development created by a group with ties to KubSu, one of my country's most renowned tech universities. It’s maintained by a close-knit community of former students, many of whom are now immigrants (essentially, people in the same boat as me). The atmosphere felt welcoming, and the project maintainer stood out as very supportive and helpful, thoroughly responding to my classmate's comments. It feels like a community I could genuinely see myself joining if I continue to contribute.&lt;/p&gt;

&lt;p&gt;Even the name of the community is compelling:&lt;br&gt;
&lt;a href="https://mfbt.community/#join" rel="noopener noreferrer"&gt;Move Fast and Break Things&lt;/a&gt; - an ultimate developer's motto!&lt;/p&gt;

&lt;p&gt;+ An online game, what can be more fun than that?&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/move-fast-and-break-things" rel="noopener noreferrer"&gt;
        move-fast-and-break-things
      &lt;/a&gt; / &lt;a href="https://github.com/move-fast-and-break-things/aibyss" rel="noopener noreferrer"&gt;
        aibyss
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🚧 UNDER DEVELOPMENT 🚧 Aibyss: code your AI to compete in a survival game
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🚧 UNDER DEVELOPMENT 🚧 Aibyss: code your AI to compete in a survival game&lt;/h1&gt;

&lt;/div&gt;
&lt;div&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/move-fast-and-break-things/aibyss/refs/heads/main/public/og-image.png"&gt;&lt;img alt="Aibyss social image" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmove-fast-and-break-things%2Faibyss%2Frefs%2Fheads%2Fmain%2Fpublic%2Fog-image.png" width="600px"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Setup&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;install &lt;a href="https://nodejs.org/en" rel="nofollow noopener noreferrer"&gt;node.js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;(on macOS only)&lt;/strong&gt; install &lt;code&gt;node-gyp&lt;/code&gt;: &lt;code&gt;npm install -g node-gyp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;install the dependencies: &lt;code&gt;npm ci&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Development server&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Start the development server on &lt;code&gt;http://localhost:3000&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run dev&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Create new user&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run create-user &lt;span class="pl-k"&gt;&amp;lt;&lt;/span&gt;username&lt;span class="pl-k"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Running the tests&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;unit tests&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run &lt;span class="pl-c1"&gt;test&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;e2e tests&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;First, setup e2e tests by running &lt;code&gt;npm run test:e2e:install&lt;/code&gt;, then run the tests with:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run test:e2e&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Contributors guide&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;We follow &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="nofollow noopener noreferrer"&gt;conventional commits&lt;/a&gt;, name your PRs accordingly&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Production&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Build the application for production:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run build&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Locally preview production build:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run preview&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Check out the &lt;a href="https://nuxt.com/docs/getting-started/deployment" rel="nofollow noopener noreferrer"&gt;deployment documentation&lt;/a&gt; for more information.&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/move-fast-and-break-things/aibyss" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;So, that’s how I decided to work on AIbyss, an online competition game where players program AI bots to compete against one another.&lt;/p&gt;

&lt;p&gt;While the project is relatively small, it offers many learning opportunities. I’m unfamiliar with most of the stack (&lt;a href="https://nuxt.com/docs/getting-started/deployment" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt;, &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue.js&lt;/a&gt;), have never worked on online games, and also haven’t tackled any frontend-related issues in my open-source journey. All this combined makes the project a great fit for my Release 0.4.&lt;/p&gt;

&lt;h2&gt;
  
  
  The goals I set for Release 0.4
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Contributing to the project in a meaningful way&lt;/strong&gt; - to achieve this, I decided to start by picking up an issue with a &lt;code&gt;high priority&lt;/code&gt; label&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/move-fast-and-break-things/aibyss/issues/42" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        feat: let the users view the rating page without having to log in
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#42&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/yurijmikhalevich" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F4187729%3Fv%3D4" alt="yurijmikhalevich avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/yurijmikhalevich" rel="noopener noreferrer"&gt;yurijmikhalevich&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/move-fast-and-break-things/aibyss/issues/42" rel="noopener noreferrer"&gt;&lt;time&gt;Sep 29, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;This is a follow-up idea to the #37 and should be done after it is merged.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/move-fast-and-break-things/aibyss/issues/42" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Getting comfortable with the tools&lt;/strong&gt; - as mentioned, the project utilizes a lot of tools that are new to me, so I was excited to see them in action.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Communicating with the maintainers more actively&lt;/strong&gt; - in this release, I wanted to engage more actively with the maintainers. Instead of waiting until my work was complete, I planned to create a draft PR early on to gather feedback and collaborate more effectively throughout the process.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stay tuned
&lt;/h2&gt;

&lt;p&gt;I’ve already picked up an issue and started working on it, so stay tuned — I’ll share my progress in an upcoming post!&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>GCC: Automatic Function Multi-Versioning Pt.2</title>
      <dc:creator>arinak1017</dc:creator>
      <pubDate>Fri, 06 Dec 2024 06:56:16 +0000</pubDate>
      <link>https://dev.to/arilloid/gcc-automatic-function-multi-versioning-pt2-mfa</link>
      <guid>https://dev.to/arilloid/gcc-automatic-function-multi-versioning-pt2-mfa</guid>
      <description>&lt;h2&gt;
  
  
  Before we start...
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have just stumbled upon my SPO600 series of blog posts, it has been created to document and share my learnings as I progress through my Software Portability and Optimization course at Seneca Polytechnic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this blog post, I will talk about the code experiments I conducted as part of Stage 2 of our course Project: implementing a new experimental feature in the GNU Compiler Collection (GCC) — Automatic Function Multi-Versioning.&lt;/p&gt;

&lt;p&gt;If you are curious to learn more about the project, feel free to check out my previous blog posts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/arilloid/gcc-automatic-function-multi-versioning-pt1-59c5"&gt;GCC: Automatic Function Multi-Versioning Pt.1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/arilloid/building-gcc-from-source-on-aarch64-34d2"&gt;Building GCC from Source on AArch64&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Analyzing the Demo Pass
&lt;/h2&gt;

&lt;p&gt;In my previous post, I shared how I integrated the demo pass provided to us by our professor.&lt;/p&gt;

&lt;p&gt;After I made sure that I could get the new passes running, I decided to take a closer look at the functionality of the demo pass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Omitted the License and the include statements&lt;/span&gt;
&lt;span class="c1"&gt;// ============================================================= vvv&lt;/span&gt;
&lt;span class="c1"&gt;// Test pass&lt;/span&gt;
&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;pass_data&lt;/span&gt; &lt;span class="n"&gt;pass_data_ctyler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;GIMPLE_PASS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* type */&lt;/span&gt;
  &lt;span class="s"&gt;"ctyler"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* name */&lt;/span&gt;
  &lt;span class="n"&gt;OPTGROUP_NONE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* optinfo_flags */&lt;/span&gt;
  &lt;span class="n"&gt;TV_NONE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* tv_id */&lt;/span&gt;
  &lt;span class="n"&gt;PROP_cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* properties_required */&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* properties_provided */&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* properties_destroyed */&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* todo_flags_start */&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* todo_flags_finish */&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;pass_ctyler&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;gimple_opt_pass&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; 
&lt;span class="nl"&gt;public:&lt;/span&gt;
  &lt;span class="n"&gt;pass_ctyler&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gcc&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;gimple_opt_pass&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pass_data_ctyler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="cm"&gt;/* opt_pass methods: */&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;gate&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// always execute pass&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// class pass_ctyler&lt;/span&gt;

&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="n"&gt;pass_ctyler&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;basic_block&lt;/span&gt; &lt;span class="n"&gt;bb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;bb_cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stmt_cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;FOR_EACH_BB_FN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;bb_cnt&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fprintf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"===== Basic block count: %d =====&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bb_cnt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gimple_stmt_iterator&lt;/span&gt; &lt;span class="n"&gt;gsi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gsi_start_bb&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;gsi_end_p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;gsi_next&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gsi&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;gimple&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gsi_stmt&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;stmt_cnt&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;fprintf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"----- Statement count: %d -----&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stmt_cnt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;print_gimple_stmt&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TDF_VOPS&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;TDF_MEMSYMS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fprintf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;##### End ctyler diagnostics, start regular dump of current gimple #####&lt;/span&gt;&lt;span class="se"&gt;\n\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// anon namespace&lt;/span&gt;

&lt;span class="n"&gt;gimple_opt_pass&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="nf"&gt;make_pass_ctyler&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gcc&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;pass_ctyler&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ============================================================= ^^^&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I first noticed that the &lt;code&gt;if&lt;/code&gt; loop was placed below a &lt;code&gt;return&lt;/code&gt; statement, making it ineffective. I fixed this by moving the &lt;code&gt;if&lt;/code&gt; loop above the &lt;code&gt;return&lt;/code&gt; statement.&lt;/p&gt;

&lt;p&gt;Then, I decided to break the code down into sections to understand the logic of the demo pass better:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Metadata Declaration:&lt;/code&gt; in the first section, the metadata of the pass is defined (type, name, options, and properties)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Pass Object:&lt;/code&gt; a pass object of type &lt;code&gt;Gimple Opt Pass&lt;/code&gt; is declared&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Gate Method:&lt;/code&gt; this method determined whether the pass should run.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Execution Logic:&lt;/code&gt; the actual logic of the pass is implemented in the &lt;code&gt;execute&lt;/code&gt; function. It uses the &lt;code&gt;FOR_EACH_BB_FN&lt;/code&gt; macro to loop through basic blocks. Inside this loop, a nested loop iterates through statements, printing the statement number and content&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;if&lt;/code&gt; loop to print the final message was initially placed below the return statement, making it unreachable&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Pass Object Declaration:&lt;/code&gt; finally, the pass object of type &lt;code&gt;pass_tyler&lt;/code&gt; is declared&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shortly after, the updated version of the pass was released:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* Test pass
   Chris Tyler, Seneca Polytechnic College, 2024-11 
   Modelled on tree-nrv.cc

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
&amp;lt;http://www.gnu.org/licenses/&amp;gt;.  */&lt;/span&gt;

&lt;span class="cp"&gt;#define INCLUDE_MEMORY
#include&lt;/span&gt; &lt;span class="cpf"&gt;"config.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"system.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"coretypes.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"backend.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"tree.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"gimple.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"tree-pass.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"ssa.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"gimple-iterator.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"gimple-walk.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"internal-fn.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"gimple-pretty-print.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// Added headers:&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"gimple-ssa.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"cgraph.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"attribs.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"pretty-print.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"tree-inline.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"intl.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// Included for dump_printf:&lt;/span&gt;
&lt;span class="c1"&gt;//#include "tree-pretty-print.h"&lt;/span&gt;
&lt;span class="c1"&gt;//#include "diagnostic.h"&lt;/span&gt;
&lt;span class="c1"&gt;//#include "dumpfile.h"&lt;/span&gt;
&lt;span class="c1"&gt;//#include "builtins.h"&lt;/span&gt;
&lt;span class="c1"&gt;//#include &amp;lt;stdlib.h&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// =================================================== vvv&lt;/span&gt;
&lt;span class="c1"&gt;// Test pass&lt;/span&gt;



&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;pass_data&lt;/span&gt; &lt;span class="n"&gt;pass_data_ctyler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;GIMPLE_PASS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* type */&lt;/span&gt;
  &lt;span class="s"&gt;"ctyler"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* name */&lt;/span&gt;
  &lt;span class="n"&gt;OPTGROUP_NONE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* optinfo_flags */&lt;/span&gt;
  &lt;span class="n"&gt;TV_NONE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* tv_id */&lt;/span&gt;
  &lt;span class="n"&gt;PROP_cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* properties_required */&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* properties_provided */&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* properties_destroyed */&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* todo_flags_start */&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* todo_flags_finish */&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;pass_ctyler&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;gimple_opt_pass&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; 
&lt;span class="nl"&gt;public:&lt;/span&gt;
  &lt;span class="n"&gt;pass_ctyler&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gcc&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;gimple_opt_pass&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pass_data_ctyler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="cm"&gt;/* opt_pass methods: */&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;gate&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// always execute pass&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// class pass_ctyler&lt;/span&gt;

&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="n"&gt;pass_ctyler&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;cgraph_node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;func_cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;FOR_EACH_FUNCTION&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fprintf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"=== Function %d Name '%s' ===&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;func_cnt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fprintf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;#### End ctyler diagnostics, start regular dump of current gimple ####&lt;/span&gt;&lt;span class="se"&gt;\n\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// anon namespace&lt;/span&gt;

&lt;span class="n"&gt;gimple_opt_pass&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="nf"&gt;make_pass_ctyler&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gcc&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;pass_ctyler&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// =================================================== ^^^&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The contents of the dump file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello World Program, pass output

;; Function main (main, funcdef_no=0, decl_uid=3267, cgraph_uid=1, symbol_order=0)

=== Function 1 Name 'printf' ===
=== Function 2 Name 'main' ===


#### End ctyler diagnostics, start regular dump of current gimple ####


int main ()
{
  int D.3270;
  int _3;

  &amp;lt;bb 2&amp;gt; :
  printf ("Hello");
  _3 = 0;

  &amp;lt;bb 3&amp;gt; :
&amp;lt;L0&amp;gt;:
  return _3;

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pass uses a different accessor macro called &lt;code&gt;FOR_EACH_FUNCTION&lt;/code&gt;, which cycles through the code and prints the function name; this version of the pass seems to have a considerably simpler logic.&lt;/p&gt;

&lt;p&gt;To test the pass, I extracted the test case files provided by our professor in the &lt;code&gt;/public/spo600-test-clone.tgz&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuf9v7hh31dq1z3ic0i5i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuf9v7hh31dq1z3ic0i5i.png" alt="Image description" width="800" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;Makefile&lt;/code&gt;, I set &lt;code&gt;DUMP_ALL&lt;/code&gt; to 1 to make sure that all files would be dumped into the current directory during the build process. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The test files contain two implementations of the &lt;code&gt;scale_samples function&lt;/code&gt;, which were effectively identical, and two implementations of the &lt;code&gt;scale_sample&lt;/code&gt; function, which were significantly different. The goal of our pass = pruning the identical functions while leaving the significantly different ones untouched.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After building the files, our pass generated two dump files:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6m6klufwcxy8b8dtklgn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6m6klufwcxy8b8dtklgn.png" alt="Image description" width="584" height="88"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each dump file listed the function names at the top, followed by the full content of the dump. Since the files are quite lengthy, I can’t display them in full here, but they looked something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;;; Function main (main, funcdef_no=24, decl_uid=3961, cgraph_uid=25, symbol_order=24) (executed once)

=== Function 1 Name '__builtin_cpu_supports' ===
=== Function 2 Name '__builtin_cpu_init' ===
=== Function 3 Name 'scale_samples.resolver' ===
=== Function 4 Name 'scale_samples' ===
=== Function 5 Name 'scale_samples.arch_x86_64_v3' ===
=== Function 6 Name 'printf' ===
=== Function 7 Name 'vol_createsample' ===
=== Function 8 Name 'calloc' ===
=== Function 9 Name 'main' ===
=== Function 10 Name 'scale_samples' ===
=== Function 11 Name 'sum_sample' ===


#### End ctyler diagnostics, start regular dump of current gimple ####


int main ()
{
  unsigned long ivtmp.123;
  vector(4) int vect_t_16.116;
  vector(4) int vect_t_22.115;
  vector(4) int vect__14.114;
  vector(8) short int vect__13.113;
  int t;
  int16_t * out;
  int16_t * in;
  void * _10;
  unsigned long _12;
  int _33;
  int _34;

  &amp;lt;bb 2&amp;gt; [local count: 10737416]:
  # DEBUG BEGIN_STMT
  # DEBUG BEGIN_STMT
  # DEBUG ttl =&amp;gt; 0
  # DEBUG BEGIN_STMT
  # DEBUG BEGIN_STMT
  # DEBUG BEGIN_STMT
  in_3 = calloc (50000000, 2);
  # DEBUG in =&amp;gt; in_3
  # DEBUG BEGIN_STMT
  out_5 = calloc (50000000, 2);
  # DEBUG out =&amp;gt; out_5
  # DEBUG BEGIN_STMT
  vol_createsample (in_3, 50000000);
  # DEBUG BEGIN_STMT
  scale_samples (in_3, out_5, 50000000, 50);
  # DEBUG BEGIN_STMT
  # DEBUG buff =&amp;gt; out_5
  # DEBUG samples =&amp;gt; 50000000
  # DEBUG INLINE_ENTRY sum_sample
  # DEBUG BEGIN_STMT
  # DEBUG BEGIN_STMT
  # DEBUG BEGIN_STMT
  # DEBUG x =&amp;gt; 0
  # DEBUG t =&amp;gt; t_18(D)
  # DEBUG BEGIN_STMT
  ivtmp.123_21 = (unsigned long) out_5;
  _12 = ivtmp.123_21 + 100000000;

  &amp;lt;bb 3&amp;gt; [local count: 1063004408]:
  # vect_t_22.115_20 = PHI &amp;lt;vect_t_16.116_15(5), { 0, 0, 0, 0 }(2)&amp;gt;
  # ivtmp.123_31 = PHI &amp;lt;ivtmp.123_22(5), ivtmp.123_21(2)&amp;gt;
  # DEBUG x =&amp;gt; NULL
  # DEBUG t =&amp;gt; NULL
  # DEBUG BEGIN_STMT
  # DEBUG D#26 =&amp;gt; D#27 * 2
  # DEBUG D#25 =&amp;gt; out_5 + D#26
  _10 = (void *) ivtmp.123_31;
  vect__13.113_25 = MEM &amp;lt;vector(8) short int&amp;gt; [(int16_t *)_10];
  vect__14.114_24 = [vec_unpack_lo_expr] vect__13.113_25;
  vect__14.114_23 = [vec_unpack_hi_expr] vect__13.113_25;
  vect_t_16.116_19 = vect_t_22.115_20 + vect__14.114_24;
  vect_t_16.116_15 = vect_t_16.116_19 + vect__14.114_23;
  # DEBUG D#24 =&amp;gt; *D#25
  # DEBUG D#23 =&amp;gt; (int) D#24
  # DEBUG t =&amp;gt; D#22
  # DEBUG BEGIN_STMT
  # DEBUG x =&amp;gt; NULL
  # DEBUG t =&amp;gt; D#22
  # DEBUG BEGIN_STMT
  ivtmp.123_22 = ivtmp.123_31 + 16;
  if (_12 != ivtmp.123_22)
    goto &amp;lt;bb 5&amp;gt;; [98.99%]
  else
    goto &amp;lt;bb 4&amp;gt;; [1.01%]

  &amp;lt;bb 5&amp;gt; [local count: 1052266995]:
  goto &amp;lt;bb 3&amp;gt;; [100.00%]

  &amp;lt;bb 4&amp;gt; [local count: 10737416]:
  _33 = .REDUC_PLUS (vect_t_16.116_15);
  _34 = t_18(D) + _33;
  # DEBUG BEGIN_STMT
  # DEBUG buff =&amp;gt; NULL
  # DEBUG samples =&amp;gt; NULL
  # DEBUG x =&amp;gt; NULL
  # DEBUG t =&amp;gt; NULL
  # DEBUG ttl =&amp;gt; _34
  # DEBUG BEGIN_STMT
  printf ("Result: %d\n", _34);
  # DEBUG BEGIN_STMT
  return 0;

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is just one of the blocks from the dump file, specifically from the &lt;code&gt;main&lt;/code&gt; function. My goal is to compare the binaries of the two cloned functions within the dump file to check if they are identical. However, as discussed in class (and as John pointed out), the binaries of the two cloned functions in the dump file are not identical, even when the functions themselves are effectively the same.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For a deeper dive into this issue, you can check out my classmate &lt;a href="https://jonpier.blogspot.com/2024/12/identifying-essence-of-function-clone.html" rel="noopener noreferrer"&gt;John’s blog&lt;/a&gt;, where he explores this problem in detail, providing really good examples.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  My Approach
&lt;/h3&gt;

&lt;p&gt;Looking at the problem from a bird’s eye view, I think we should first develop a working logic that compares the binaries of both of the cloned functions, even if it classifies them as &lt;code&gt;no-prune&lt;/code&gt; due to some minor differences, it’s essential to establish a basic comparison mechanism. Once this is achieved, we can fine-tune the comparing logic to ignore some specific parts of the binaries. For example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpw25qypeeez2lkgm4he1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpw25qypeeez2lkgm4he1.png" alt="Image description" width="800" height="88"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Credit:&lt;/strong&gt; Borrowed from John’s blog&lt;br&gt;
&lt;a href="https://jonpier.blogspot.com/2024/12/identifying-essence-of-function-clone.html" rel="noopener noreferrer"&gt;Identifying the Essence of a Function Clone&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this specific example, we could focus on checking the type instead of performing a word-by-word comparison. The advantage of this approach is that it at least provides some working foundation to build upon.&lt;/p&gt;

&lt;p&gt;However, developing this logic presents challenges since it goes far beyond simple loops and logic operations typically used in day-to-day coding. I spent a significant amount of time exploring the &lt;a href="https://gcc.gnu.org/onlinedocs/gccint/GIMPLE.html" rel="noopener noreferrer"&gt;GCC Gimple Documentation&lt;/a&gt;to better understand the required macros and functions. But, to be honest, navigating the documentation felt like diving into a rabbit hole... There is no efficient way to search for a specific macro or loop, so finding clues/helpful pointers usually requires looking through the whole docs. On top of that, some of the documentation sections are incomplete, unclear, or perhaps just too complex for me to understand.&lt;/p&gt;

&lt;p&gt;While doing the experiments, I was able to come up with draft logic for the &lt;code&gt;execute&lt;/code&gt; and &lt;code&gt;compare_gimple_functions&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;compare_gimple_functions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gimple_seq&lt;/span&gt; &lt;span class="n"&gt;g1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gimple_seq&lt;/span&gt; &lt;span class="n"&gt;g2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;gimple_stmt_iterator&lt;/span&gt; &lt;span class="n"&gt;gsi1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gsi_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;gimple_stmt_iterator&lt;/span&gt; &lt;span class="n"&gt;gsi2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gsi_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;gsi_end_p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;gsi_end_p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;gimple&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;stmt1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gsi_stmt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;gimple&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;stmt2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gsi_stmt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Check if the statements are equivalent&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;stmt1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;stmt2&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;simple_cst_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stmt1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stmt2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;gsi_next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gsi1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;gsi_next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gsi2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;gsi_end_p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;gsi_end_p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;pass_ctyler&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;cgraph_node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;FOR_EACH_FUNCTION&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;analyzed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;function_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IDENTIFIER_POINTER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DECL_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;decl&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"_1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;npos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_last_of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"_"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;base_func_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;cgraph_node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;base_node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;get_base_function&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_node&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;base_node&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;compare_gimple_functions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;get_body&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;get_body&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"PRUNE: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_func_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c_str&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"NOPRUNE: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_func_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c_str&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The logic I developed currently has three errors, mainly due to incorrect usage of GIMPLE functions and macros. I tried digging into &lt;code&gt;cgraph.cc&lt;/code&gt; to better understand the issue, but this only added to my confusion. Unfortunately, I ended up corrupting the project and had to rebuild it from scratch. For now, my logic attempts to get the binaries for the cloned functions and compare them using the &lt;code&gt;compare_gimple_functions&lt;/code&gt;; if they are the same, it is supposed to print &lt;code&gt;PRUNE&lt;/code&gt;, and if they differ, it will print &lt;code&gt;NOPRUNE&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Afterthoughts
&lt;/h2&gt;

&lt;p&gt;This code is the result of a lot of trial and error, and although I don’t have any feasible results to show, I will continue learning more about the code base and try to fix my logic. &lt;/p&gt;

&lt;p&gt;All in all, this journey has been rewarding despite constant setbacks due to the extreme complexity of the GCC codebase.&lt;/p&gt;

</description>
      <category>gcc</category>
      <category>compiling</category>
      <category>afmv</category>
    </item>
    <item>
      <title>GCC: Automatic Function Multi-Versioning Pt.1</title>
      <dc:creator>arinak1017</dc:creator>
      <pubDate>Fri, 06 Dec 2024 03:22:53 +0000</pubDate>
      <link>https://dev.to/arilloid/gcc-automatic-function-multi-versioning-pt1-59c5</link>
      <guid>https://dev.to/arilloid/gcc-automatic-function-multi-versioning-pt1-59c5</guid>
      <description>&lt;h2&gt;
  
  
  Before we start...
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have just stumbled upon my SPO600 series of blog posts, it has been created to document and share my learnings as I progress through my Software Portability and Optimization college course.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this blog post, I’ll start sharing the progress I made after transitioning to Stage 2 of our class project: implementing a new experimental feature in the GNU Compiler Collection (GCC) — Automatic Function Multi-Versioning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Automatic Function Multi-Versioning?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As promised in my &lt;a href="https://dev.to/arilloid/building-gcc-from-source-on-aarch64-34d2/edit"&gt;1st project-related blog post&lt;/a&gt;, before diving into the details of Project Stage 2, I’d like to give you a better idea of the project's specifics. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automatic Function Multi-Versioning&lt;/strong&gt; should enable the compiler to automatically identify functions that could benefit from being cloned and optimized for specific architectural variants without requiring developers to modify the source code. By using a compiler option to specify the target architectures, AFMV will clone, optimize, and prune redundant function versions, enhancing software performance without requiring any manual efforts from the devs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;However, this 2024 Fall term, our focus is determining how to detect when two function versions are "fundamentally the same," which is essential for implementing function pruning.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Stage 2 Objective
&lt;/h2&gt;

&lt;p&gt;In Stage 2 of the Project, we are aiming to add a compilation pass to the GCC compiler that determines whether functions should be pruned. This pass should iterate through the program's code, identify cloned functions, and analyze their gimple representations to determine if their implementations are identical. If duplicates are detected, the pass will output a decision indicating that the redundant clones can be pruned (by returning true or false).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;To limit the scope, we will be making the following assumptions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;There is only one cloned function in a program&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There are only two versions of that function.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Initial Setup
&lt;/h2&gt;

&lt;p&gt;For the initial setup, I created a folder called &lt;code&gt;Stage-2&lt;/code&gt; in my home directory, along with the following sub-folders:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgp6kjznp9dkbxgjq0ziv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgp6kjznp9dkbxgjq0ziv.png" alt="Initial-setup" width="720" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/src&lt;/code&gt; - contains the source code of the GCC compiler&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/build&lt;/code&gt; - used to configure and build the compiler&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/install&lt;/code&gt; - serves as the destination directory for installing the GCC binaries&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;The server where I initially built the compiler was put down, so I rebuilt it on our class x86_64 server. The clean build took about 22 minutes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9j5u2vwsluvprn714e2z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9j5u2vwsluvprn714e2z.png" alt="gcc --version" width="800" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can read about building GCC from source in my previous blog post: &lt;a href="https://dev.toBuilding%20GCC%20from%20Source%20on%20AArch64"&gt;Building GCC from Source&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Adding a New Pass
&lt;/h2&gt;

&lt;p&gt;Before conducting any code experiments, I made sure that I could successfully integrate new passes into GCC. &lt;/p&gt;

&lt;p&gt;Our professor, Chris Tyler, gave us his demo pass as a starter code for Project Stage 2. The pass was located in the public folder (&lt;code&gt;/public/spo600-gcc-pass-demo.tgz&lt;/code&gt;). I moved it to my home directory and extracted it using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xvzf&lt;/span&gt; spo600-gcc-pass-demo.tgz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9wsywg60ukl45te80cp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9wsywg60ukl45te80cp.png" alt="Folder structure" width="759" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The extracted files included three modified files from the &lt;code&gt;/gcc&lt;/code&gt; subdirectory of the source tree (&lt;code&gt;Makefile.in&lt;/code&gt;, &lt;code&gt;passes.def&lt;/code&gt;, &lt;code&gt;tree-pass.h&lt;/code&gt;) and one new file, &lt;code&gt;tree-ctyler.cc&lt;/code&gt;, containing the pass logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's Take a Look at the Files, What Changes Were Made to Add a Pass?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Makefile.in&lt;/code&gt;: on line 1712, &lt;code&gt;tree-ctyler.o&lt;/code&gt; was added. &lt;code&gt;tree-ctyler.o&lt;/code&gt; is a language-independent object file generated from the corresponding source file &lt;code&gt;tree-ctyler.cc&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ctyler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; \
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;passes.def&lt;/code&gt;: this file defines the sequence of passes that transform and optimize code during compilation. The demo pass, &lt;code&gt;pass_ctyler&lt;/code&gt;, is added on line 444, ensuring it is executed late in the compilation process, after all significant optimizations have been completed.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;NEXT_PASS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pass_ctyler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;tree-pass.h&lt;/code&gt;: this file contains the structures for defining optimization passes in GCC. It includes a new line that declares the entry point for our custom pass. The declaration introduces the external function &lt;code&gt;make_pass_ctyler&lt;/code&gt;, which initializes the pass in the GCC compiler framework. This function takes a pointer to a &lt;code&gt;gcc::context&lt;/code&gt; object as its argument and returns a pointer to a &lt;code&gt;gimple_opt_pass&lt;/code&gt; object, representing the configuration of our custom pass.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;//Line: 491&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;gimple_opt_pass&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;make_pass_ctyler&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gcc&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;tree-ctyler.cc&lt;/code&gt;: this file contains the logic of the demo pass. The pass iterates over each basic block and statement within a function, printing diagnostic information about the number of basic blocks and statements and detailed GIMPLE statements if a dump file is enabled.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Omitted the License and the include statements&lt;/span&gt;
&lt;span class="c1"&gt;// ============================================================= vvv&lt;/span&gt;
&lt;span class="c1"&gt;// Test pass&lt;/span&gt;
&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;pass_data&lt;/span&gt; &lt;span class="n"&gt;pass_data_ctyler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;GIMPLE_PASS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* type */&lt;/span&gt;
  &lt;span class="s"&gt;"ctyler"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* name */&lt;/span&gt;
  &lt;span class="n"&gt;OPTGROUP_NONE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* optinfo_flags */&lt;/span&gt;
  &lt;span class="n"&gt;TV_NONE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* tv_id */&lt;/span&gt;
  &lt;span class="n"&gt;PROP_cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* properties_required */&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* properties_provided */&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* properties_destroyed */&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* todo_flags_start */&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* todo_flags_finish */&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;pass_ctyler&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;gimple_opt_pass&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; 
&lt;span class="nl"&gt;public:&lt;/span&gt;
  &lt;span class="n"&gt;pass_ctyler&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gcc&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;gimple_opt_pass&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pass_data_ctyler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="cm"&gt;/* opt_pass methods: */&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;gate&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// always execute pass&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// class pass_ctyler&lt;/span&gt;

&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="n"&gt;pass_ctyler&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;basic_block&lt;/span&gt; &lt;span class="n"&gt;bb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;bb_cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stmt_cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;FOR_EACH_BB_FN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;bb_cnt&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fprintf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"===== Basic block count: %d =====&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bb_cnt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gimple_stmt_iterator&lt;/span&gt; &lt;span class="n"&gt;gsi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gsi_start_bb&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;gsi_end_p&lt;/span&gt; 
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;gsi_next&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gsi&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;gimple&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gsi_stmt&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gsi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;stmt_cnt&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;fprintf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"----- Statement count: %d -----&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stmt_cnt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;print_gimple_stmt&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;span class="n"&gt;TDF_VOPS&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;TDF_MEMSYMS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fprintf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;##### End ctyler diagnostics, start regular dump of current gimple #####&lt;/span&gt;&lt;span class="se"&gt;\n\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// anon namespace&lt;/span&gt;

&lt;span class="n"&gt;gimple_opt_pass&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="nf"&gt;make_pass_ctyler&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gcc&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;pass_ctyler&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ============================================================= ^^^&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

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

&lt;blockquote&gt;
&lt;p&gt;While the GCC documentation is rather sparse, you can find some helpful info on adding a pass here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gcc.gnu.org/onlinedocs/gccint/Pass-manager.html" rel="noopener noreferrer"&gt;Pass manager (GCC Internals)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gcc.gnu.org/wiki/WritingANewPass" rel="noopener noreferrer"&gt;Writing a new pass (GCC Wiki)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Rebuilding GCC with a New Pass&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After wrapping my head around the changes required to add the sample pass, I integrated it into the source code and rebuilt the project. &lt;/p&gt;

&lt;p&gt;I started by copying the necessary source code files using the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;akolodeznikova@x86-001 gcc]&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
/home/akolodeznikova/Stage-2/src/gcc
&lt;span class="nb"&gt;cp&lt;/span&gt; ../../../test/gcc/Makefile.in &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; ../../../test/gcc/passes.def &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; ../../../test/gcc/tree-pass.h &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; ../../../test/gcc/tree-ctyler.cc &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, I went into the build folder and ran the &lt;code&gt;make&lt;/code&gt; command to rebuild the project with applied changes. &lt;/p&gt;

&lt;p&gt;The build process took approximately five minutes. Once completed, I ran the &lt;code&gt;make install&lt;/code&gt; command to install the newly built GCC compiler into the &lt;code&gt;/install&lt;/code&gt; folder.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; the &lt;code&gt;make&lt;/code&gt; utility efficiently rebuilds a codebase by comparing the timestamps of dependencies (inputs) and targets (outputs). It determines which source files have been modified and rebuilds only the affected targets (&lt;em&gt;Chris Tyler’s Wiki&lt;/em&gt;).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With the build and installation complete, I tested the setup to verify that the sample pass was working. &lt;/p&gt;

&lt;p&gt;To do this, I quickly created a sample file in the test folder:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;hello.c&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then compiled it, triggering the newly added pass using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~/Stage-2/install/bin/gcc hello.c &lt;span class="nt"&gt;-fdump-tree-ctyler&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running the command, a file named &lt;code&gt;a-hello.c.263t.ctyler&lt;/code&gt; was generated. The file contained the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//a-hello.c.263t.ctyler
;; Function main (main, funcdef_no=0, decl_uid=3267, cgraph_uid=1, symbol_order=0)

===== Basic block count: 1 =====
----- Statement count: 1 -----
# .MEM_2 = VDEF &amp;lt;.MEM_1(D)&amp;gt;
printf ("Hello");
----- Statement count: 2 -----
_3 = 0;
===== Basic block count: 2 =====
----- Statement count: 3 -----
&amp;lt;L0&amp;gt;:
----- Statement count: 4 -----
# VUSE &amp;lt;.MEM_2&amp;gt;
return _3;
int main ()
{
  int D.3270;
  int _3;

  &amp;lt;bb 2&amp;gt; :
  printf ("Hello");
  _3 = 0;

  &amp;lt;bb 3&amp;gt; :
&amp;lt;L0&amp;gt;:
  return _3;

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output confirmed the added pass was working as expected. It successfully iterated through the code, producing diagnostic information about basic blocks and statements.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎉 🎉 🎉
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Stay tuned...
&lt;/h2&gt;

&lt;p&gt;In my next post, I’ll share the code experiments I conducted to implement the proposed functionality. So, stay tuned for more updates on my progress!&lt;/p&gt;

</description>
      <category>gcc</category>
      <category>compiling</category>
      <category>afmv</category>
    </item>
    <item>
      <title>Publishing ADDCOM!</title>
      <dc:creator>arinak1017</dc:creator>
      <pubDate>Sat, 23 Nov 2024 00:46:53 +0000</pubDate>
      <link>https://dev.to/arilloid/publishing-addcom-26fn</link>
      <guid>https://dev.to/arilloid/publishing-addcom-26fn</guid>
      <description>&lt;h2&gt;
  
  
  Hello, Blog!
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have just stumbled upon my OSD600 series of blog posts, it has been created to document and share my learnings as I progress through my Open Source Development college course.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this blog post, I want to go over the steps I took to publish my CLI tool - &lt;a href="https://pypi.org/project/addcom/" rel="noopener noreferrer"&gt;addcom&lt;/a&gt; to PyPi.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;
        arilloid
      &lt;/a&gt; / &lt;a href="https://github.com/arilloid/addcom" rel="noopener noreferrer"&gt;
        addcom
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      a CLI tool for adding comments to your source code files
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;ADDCOM&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;addcom&lt;/code&gt; is a CLI source code documenter tool which provides coders with an easy way to add comments to their source code files
Give it a relative/absolute path to your file and it will analyze its contents and add comments using a Large Language Model's chat completion.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://private-user-images.githubusercontent.com/105298302/366692445-e01f1c1b-faf4-4c2d-b62b-a2492de1475b.gif?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzIzMjMzOTgsIm5iZiI6MTczMjMyMzA5OCwicGF0aCI6Ii8xMDUyOTgzMDIvMzY2NjkyNDQ1LWUwMWYxYzFiLWZhZjQtNGMyZC1iNjJiLWEyNDkyZGUxNDc1Yi5naWY_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQxMTIzJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MTEyM1QwMDUxMzhaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0yZWM0NzRkNzUyYTc2YzkyMmZiNTRlZjdjYjk0ZjhjYjA2NDU0MjBjZjI1NzYwZmNmYWY0YTU5OTRlZTRlNjA4JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.0CL3eSQmxWdvvq52o56z_sacNbwdJxjHWMWp8eDKkvI"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fprivate-user-images.githubusercontent.com%2F105298302%2F366692445-e01f1c1b-faf4-4c2d-b62b-a2492de1475b.gif%3Fjwt%3DeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzIzMjMzOTgsIm5iZiI6MTczMjMyMzA5OCwicGF0aCI6Ii8xMDUyOTgzMDIvMzY2NjkyNDQ1LWUwMWYxYzFiLWZhZjQtNGMyZC1iNjJiLWEyNDkyZGUxNDc1Yi5naWY_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQxMTIzJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MTEyM1QwMDUxMzhaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0yZWM0NzRkNzUyYTc2YzkyMmZiNTRlZjdjYjk0ZjhjYjA2NDU0MjBjZjI1NzYwZmNmYWY0YTU5OTRlZTRlNjA4JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.0CL3eSQmxWdvvq52o56z_sacNbwdJxjHWMWp8eDKkvI" alt="addcom"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See a demo of the functionality on YouTube: &lt;a href="https://youtu.be/3jKifG2BLzc?si=M2MNCW2BASBnDQ7z" rel="nofollow noopener noreferrer"&gt;addcom-demo&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Setup Instructions&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Prerequisites&lt;/h3&gt;

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Make sure Python is installed on your system (you can download it here: &lt;a href="https://www.python.org/downloads/" rel="nofollow noopener noreferrer"&gt;https://www.python.org/downloads/&lt;/a&gt;).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;1. Install the tool using &lt;code&gt;pip&lt;/code&gt;
&lt;/h4&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;pip install addcom&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;2. Default: Create an account and generate the API key here: &lt;a href="https://console.groq.com/" rel="nofollow noopener noreferrer"&gt;https://console.groq.com/&lt;/a&gt;
&lt;/h4&gt;

&lt;/div&gt;
&lt;p&gt;By default, addcom uses the Groq API endpoint for chat completion. However, you can specify a custom endpoint using the &lt;code&gt;--base-url&lt;/code&gt; or &lt;code&gt;-u&lt;/code&gt; flag option. (If you do this, make sure to obtain an appropriate API key and specify the model supported by the chosen provider using the &lt;code&gt;--model&lt;/code&gt;/ &lt;code&gt;-m&lt;/code&gt; option).&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;3. Set&lt;/h4&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/arilloid/addcom" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I welcome feedback/&lt;a href="https://github.com/arilloid/addcom/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;contributions&lt;/a&gt;, so don’t hesitate to take a look and get involved 😊&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing for Release
&lt;/h2&gt;

&lt;p&gt;Before releasing my tool, I integrated &lt;a href="https://python-poetry.org/docs/" rel="noopener noreferrer"&gt;Poetry&lt;/a&gt; for dependency management and packaging into my project, replacing the good old &lt;code&gt;setuptools&lt;/code&gt;. This decision was inspired by recommendations from peers and various blog posts highlighting Poetry’s simplicity and modern features.&lt;/p&gt;

&lt;p&gt;I removed the &lt;code&gt;setup.py&lt;/code&gt; file, which handled the tools' packaging. Then, moved the metadata from &lt;code&gt;__init__.py&lt;/code&gt; into a &lt;code&gt;pyproject.toml&lt;/code&gt; file, which I created a couple of labs back to add configs for the source code formatter and linter.&lt;/p&gt;

&lt;p&gt;Additionally, I did a bit of refactoring to make the project's structure a bit cleaner. To do so I moved all source code files into a single &lt;code&gt;app&lt;/code&gt; package and updated the imports across the project.&lt;/p&gt;

&lt;p&gt;For guidance, I referred to &lt;a href="https://python-poetry.org/docs/pyproject/" rel="noopener noreferrer"&gt;Poetry's official documentation&lt;/a&gt; and studied similar Python projects on GitHub.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Below are the final configurations I used for Poetry:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# Poetry - project metadata&lt;/span&gt;
&lt;span class="nn"&gt;[tool.poetry]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"addcom"&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1.0.2"&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"a CLI tool for adding comments to your source code files"&lt;/span&gt;
&lt;span class="py"&gt;authors&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Arina Kolodeznikova &amp;lt;arinak1017@gmail.com&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;license&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"MIT"&lt;/span&gt;
&lt;span class="py"&gt;readme&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"README.md"&lt;/span&gt;
&lt;span class="py"&gt;repository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://github.com/arilloid/addcom"&lt;/span&gt;
&lt;span class="py"&gt;packages&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;[{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="err"&gt;}]&lt;/span&gt;

&lt;span class="c"&gt;# Dependencies required for running the project&lt;/span&gt;
&lt;span class="nn"&gt;[tool.poetry.dependencies]&lt;/span&gt;
&lt;span class="py"&gt;python&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^3.12"&lt;/span&gt;
&lt;span class="py"&gt;typer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^0.12"&lt;/span&gt;
&lt;span class="py"&gt;openai&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^1.46"&lt;/span&gt;
&lt;span class="py"&gt;rich&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^13.8"&lt;/span&gt;
&lt;span class="py"&gt;typing_extensions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^4.12"&lt;/span&gt;

&lt;span class="c"&gt;# Dev dependencies (not required for run-time)&lt;/span&gt;
&lt;span class="nn"&gt;[tool.poetry.group.dev.dependencies]&lt;/span&gt;
&lt;span class="py"&gt;black&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^24.10"&lt;/span&gt;
&lt;span class="py"&gt;ruff&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^0.7"&lt;/span&gt;
&lt;span class="py"&gt;pytest&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^8.3"&lt;/span&gt;
&lt;span class="py"&gt;pytest-mock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^3.14"&lt;/span&gt;

&lt;span class="c"&gt;# Project's CLI commands&lt;/span&gt;
&lt;span class="nn"&gt;[tool.poetry.scripts]&lt;/span&gt;
&lt;span class="py"&gt;addcom&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'app.main:app'&lt;/span&gt;

&lt;span class="c"&gt;# Build configurations&lt;/span&gt;
&lt;span class="nn"&gt;[build-system]&lt;/span&gt;
&lt;span class="py"&gt;requires&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"poetry-core"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;build-backend&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"poetry.core.masonry.api"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Publishing addcom to PyPi
&lt;/h2&gt;

&lt;p&gt;After setting up Poetry and verifying that everything was working as expected, I tweaked &lt;a href="https://github.com/arilloid/addcom/blob/main/.github/workflows/addcom_ci.yml" rel="noopener noreferrer"&gt;my CI workflow file&lt;/a&gt;, updated the tool’s documentation, and went on to publishing my tool to &lt;a href="https://pypi.org/" rel="noopener noreferrer"&gt;PyPi&lt;/a&gt; (The Python Package Index). &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can find the guide that I followed here: &lt;a href="https://www.geeksforgeeks.org/publishing-packages-with-poetry/?ref=oin_asr1" rel="noopener noreferrer"&gt;Publishing packages with Poetry&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Steps to publish
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Tagging the Release&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I started by tagging the release using an annotated Git tag to mark the version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git tag &lt;span class="nt"&gt;-a&lt;/span&gt; v1.0.0 &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"my version 1.0.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Configuring PyPI Credentials&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, I configured Poetry to use my PyPI credentials (this step required obtaining a PyPI API token):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry config pypi-token.pypi &amp;lt;your-pypi-token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;To generate a PyPI token, I created an account on PyPI, navigated to Account Settings, and selected Add API Tokens.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6k3vpjh5zia89cabj7o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6k3vpjh5zia89cabj7o.png" alt="API token" width="800" height="284"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;3. Building and Publishing the Package&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Finally, I built and published the package using Poetry (which I specified as the build backend in the &lt;code&gt;pyproject.toml&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry publish &lt;span class="nt"&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbznjrdtmb0qzxxcd6e6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbznjrdtmb0qzxxcd6e6.png" alt="published the release" width="800" height="283"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can find my release here: &lt;a href="https://pypi.org/project/addcom/" rel="noopener noreferrer"&gt;addcom&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Testing the Release
&lt;/h2&gt;

&lt;p&gt;After testing the release myself, I invited my friend, roommate, and fellow developer, Tatiana, for a dedicated testing session. Although I was nervous to show her my tool, the testing process went pretty smoothly, thanks to the effort I put into creating detailed instructions in the projects &lt;code&gt;README.md&lt;/code&gt;. However, there were still a few issues during the review. The instructions for setting up the API key were poorly structured, causing confusion. Tatiana also noted that the &lt;code&gt;.toml&lt;/code&gt; configuration section assumed users were working from a cloned repository, which wouldn't be the case for most users installing the tool using &lt;code&gt;pip&lt;/code&gt;. The most significant feedback, which echoed a remark made by my professor David, was about the tool’s handling of multiple files. When generating comments for several files, the tool saved everything to a single file, with no option to split the output. Additionally, at times the generated comments were inconsistent, even with the given "context" code used for reference.&lt;/p&gt;

&lt;p&gt;To address these issues, I edited the API key setup instructions in the &lt;code&gt;README&lt;/code&gt; and updated the &lt;code&gt;.toml&lt;/code&gt; configuration section. As for the file output logic and comment consistency, I plan to look into updating them after the term comes to an end.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to install ADDCOM
&lt;/h2&gt;

&lt;p&gt;You can now install &lt;code&gt;addcom&lt;/code&gt; using &lt;code&gt;pip&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;addcom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, &lt;code&gt;addcom&lt;/code&gt; uses the Groq API for chat completion. To get started quickly, create an account on the &lt;a href="https://console.groq.com/" rel="noopener noreferrer"&gt;Groq Console&lt;/a&gt;, generate an API key, and run the tool with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;addcom FILE_PATH&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"your_api_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For detailed information on the tool's functionality, usage, and instructions, visit the &lt;a href="https://pypi.org/project/addcom/" rel="noopener noreferrer"&gt;release page on PyPI&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>opensource</category>
      <category>python</category>
      <category>cli</category>
    </item>
    <item>
      <title>Contributing to ByteChef</title>
      <dc:creator>arinak1017</dc:creator>
      <pubDate>Thu, 21 Nov 2024 08:06:10 +0000</pubDate>
      <link>https://dev.to/arilloid/contributing-to-bytechef-23gb</link>
      <guid>https://dev.to/arilloid/contributing-to-bytechef-23gb</guid>
      <description>&lt;h2&gt;
  
  
  Before we start...
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have just stumbled upon my OSD600 series of blog posts, it has been created to document and share my learnings as I progress through my Open Source Development college course.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After completing Hacktoberfest, my classmates and I were challenged to make more substantial Open Source contributions. It was time to move beyond typo fixes and minor code changes and focus on implementing full-fledged features.&lt;/p&gt;

&lt;p&gt;If you read my &lt;a href="https://dev.to/arilloid/hacktoberfest-2024-last-contribution-recap-337h"&gt;Hacktoberfest Recap&lt;/a&gt; post, you might remember that my largest contribution was &lt;a href="https://github.com/ohcnetwork/care/pull/2547" rel="noopener noreferrer"&gt;adding a settings variable to one project's backend&lt;/a&gt;. This was mainly because, in the final week of Hacktoberfest, I decided to unassign myself from a more difficult issue that involved implementing a feature in the Java Spring Boot backend of a project called &lt;a href="https://github.com/bytechefhq/bytechef" rel="noopener noreferrer"&gt;ByteChef&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As a result, when the new course task was announced, I knew I wanted to revisit ByteChef and face my fear of Java!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;In this blog post, I'll share how I learned from the mistakes of my previous contribution attempt and successfully contributed two new features to ByteChef.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  A bit about ByteChef
&lt;/h2&gt;

&lt;p&gt;ByteChef is an open-source, low-code platform for API integration and workflow automation (currently under active development). It aims to help users easily create and manage workflows across different applications and systems by adding components (each responsible for interacting with a specific service) and defining their relations.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Cool fact:&lt;/em&gt;&lt;/strong&gt; the company is based in Croatia! 🌍&lt;/p&gt;
&lt;/blockquote&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/bytechefhq" rel="noopener noreferrer"&gt;
        bytechefhq
      &lt;/a&gt; / &lt;a href="https://github.com/bytechefhq/bytechef" rel="noopener noreferrer"&gt;
        bytechef
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Open-source, low-code, extendable API integration &amp;amp; workflow automation platform. Integrate your organizations or your SaaS product with any third party API
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
    &lt;a href="https://www.bytechef.io?utm_source=github&amp;amp;utm_medium=organic&amp;amp;utm_campaign=readme" rel="nofollow noopener noreferrer"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fbytechefhq%2Fbytechefstatic%2Fbytechef_logo.png" alt="API integration and workflow automation platform" width="350"&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;API integration and workflow automation platform&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;
    &lt;a href="https://www.bytechef.io?utm_source=github&amp;amp;utm_medium=organic&amp;amp;utm_campaign=readme" rel="nofollow noopener noreferrer"&gt;Website&lt;/a&gt; - &lt;a href="https://docs.bytechef.io?utm_source=github&amp;amp;utm_medium=organic&amp;amp;utm_campaign=readme" rel="nofollow noopener noreferrer"&gt;Documentation&lt;/a&gt; - &lt;a href="https://discord.gg/VKvNxHjpYx" rel="nofollow noopener noreferrer"&gt;Discord&lt;/a&gt; - &lt;a href="https://twitter.com/bytechefhq" rel="nofollow noopener noreferrer"&gt;Twitter&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
    &lt;a href="https://github.com/bytechefhq/bytechef/actions/workflows/build_push.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/bytechefhq/bytechef/actions/workflows/build_push.yml/badge.svg"&gt;&lt;/a&gt; &lt;a href="https://github.com/bytechefhq/bytechef/blob/master/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/7dee08365ea2137977e6f4182225aed1e2153a6b13af3f6056ad80f75d249b70/68747470733a2f2f696d672e736869656c64732e696f2f7374617469632f76313f6c6162656c3d6c6963656e7365266d6573736167653d41706163686525323076322e3026636f6c6f723d627269676874677265656e"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;UPDATE: ByteChef is under active development. We are in the alpha stage, and some features might be missing or disabled.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/bytechefhq/bytechefstatic/screenshot.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fbytechefhq%2Fbytechefstatic%2Fscreenshot.png" alt="ByteChef Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What is ByteChef?&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;ByteChef is an open-source, low-code, extendable API integration and workflow automation platform. ByteChef can help you as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An automation solution that allows you to integrate and build automation workflows across your SaaS apps, internal APIs, and databases.&lt;/li&gt;
&lt;li&gt;An embedded solution targeted explicitly for SaaS products, allowing your customers to integrate applications they use with your product.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Key Features&lt;/h3&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Intuitive UI Workflow Editor: build and visualize workflows via the UI editor by dragging and dropping components and defining their relations.&lt;/li&gt;
&lt;li&gt;Event-Driven &amp;amp; Scheduled Workflows: automate scheduled and real-time event-driven workflows via a simple trigger definition.&lt;/li&gt;
&lt;li&gt;Multiple flow controls: use the range of various flow controls such as condition, switch, loop, each, parallel, etc.&lt;/li&gt;
&lt;li&gt;Built-In Code…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/bytechefhq/bytechef" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  The 1-st Issue I worked on
&lt;/h2&gt;

&lt;p&gt;I decided to give myself a head start by picking up an issue similar to the one I had previously dropped (&lt;a href="https://github.com/bytechefhq/bytechef/issues/1643" rel="noopener noreferrer"&gt;Baserow - Get Row action #1643&lt;/a&gt;). So, I found an issue related to the same workflow component and reached out to the issue creator, asking for a second chance to contribute.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/bytechefhq/bytechef/issues/1642#issuecomment-2457654666" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Comment for
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1642&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F105298302%3Fu%3D773354456431193f4bc8af01e227e5f584e3d61f%26v%3D4" alt="arilloid avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;arilloid&lt;/a&gt;
        &lt;/strong&gt; commented on &lt;a href="https://github.com/bytechefhq/bytechef/issues/1642#issuecomment-2457654666" rel="noopener noreferrer"&gt;&lt;time&gt;Nov 05, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Hello @monikakuster ,&lt;/p&gt;
&lt;p&gt;I previously had to unassign myself from the related issue due to some personal circumstances, but I now have more time and resources to tackle adding new actions to the Baserow component. Could you please assign me to this issue? I’m ready to get started and see it through this time.&lt;/p&gt;
&lt;p&gt;Thank you!&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/bytechefhq/bytechef/issues/1642#issuecomment-2457654666" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;To be honest, I felt a bit nervous returning to the project, as I was still ashamed for unassigning myself from the previous issue. However, the project maintainer was kind enough to give me another shot.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The Issue I ended up working on:&lt;/strong&gt; The task was to implement the Delete Row action for the &lt;a href="https://baserow.io/" rel="noopener noreferrer"&gt;Baserow&lt;/a&gt; (Open Source database platform) component, enabling users to remove specific rows from a table in their Baserow database.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/bytechefhq/bytechef/issues/1642" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Baserow - Delete Row action
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1642&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/monikakuster" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F120166289%3Fv%3D4" alt="monikakuster avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/monikakuster" rel="noopener noreferrer"&gt;monikakuster&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/bytechefhq/bytechef/issues/1642" rel="noopener noreferrer"&gt;&lt;time&gt;Oct 22, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Implement the Delete Row action for the Baserow component to enable users to remove specific rows from a table within their Baserow database.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Action properties:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;table id - id of the table from which the row should be deleted&lt;/li&gt;
&lt;li&gt;row id - id of the row that needs to be deleted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ouput:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Documentation Reference: &lt;a href="https://baserow.io/api-docs" rel="nofollow noopener noreferrer"&gt;https://baserow.io/api-docs&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;/div&amp;gt;
&amp;lt;div class="gh-btn-container"&amp;gt;&amp;lt;a class="gh-btn" href="https://github.com/bytechefhq/bytechef/issues/1642"&amp;gt;View on GitHub&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;





&lt;h2&gt;
  
  
  Contribution Process
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Dev Environment Setup
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;During my first attempt, I struggled to get the project running, even though I closely followed the instructions in the &lt;a href="https://github.com/bytechefhq/bytechef/blob/master/CONTRIBUTING.md" rel="noopener noreferrer"&gt;CONTRIBUTING.md&lt;/a&gt; (or at least I thought I did), which left me unable to test my draft code. This time, I decided to focus on correctly setting up my development environment from the very beginning.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Here is an overview of the entire setup process, combining the problems I faced during both my initial and current attempts:&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The first issue I encountered was an error when cloning the repository: "File name too long" / "Clone succeeded but checkout failed." I resolved this by configuring Git to accept long paths.&lt;/p&gt;

&lt;p&gt;Next, I downloaded the compatible version of the Java SDK (21+) and the Java support extension for VS Code. I then started the necessary Docker containers for the dependent infrastructure (Redis, PostgreSQL, and Mailhog). After compiling the codebase, I attempted to start the server but encountered an error with a terrifyingly long stack trace. I thought the issue was related to unresolved dependencies, as, at first glance, the error message seemed to point in that direction. So, I checked the prerequisites and tried rebuilding the project, but the problem persisted. Upon further investigation (of the stack trace that was too long for the LLM to process), I discovered that the issue was related to the server's inability to connect to PostgreSQL. I checked the PostgreSQL Docker container's logs, but everything appeared to be running as expected. Confused, I decided to seek help on the project's Discord. One of the maintainers asked if I was trying to access an external database, and that’s when the realization struck me: something else was likely occupying the port where the PostgreSQL container was supposed to run. Sure enough, I found that my local PostgreSQL server server was already using that port. After terminating the process and restarting the Docker containers, the server started up as expected.&lt;/p&gt;

&lt;p&gt;With the development environment finally set up, I was ready to move forward with implementing a feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  Feature Implementation
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;As a Java noob, I was intimidated by the project, especially since I had no experience with Gradle or Java Spring Boot.&lt;/p&gt;

&lt;p&gt;On my first attempt, I started by locating where the component actions needed to be implemented. Although I found the relevant functions, I quickly realized that this approach wasn't ideal. Without a clear understanding of the project setup, I struggled to make sense of imported custom classes, methods, and constants, and, inevitably, got overwhelmed. &lt;/p&gt;

&lt;p&gt;On my second attempt, I took a step back to study the project structure and familiarize myself with the tools used. I also revisited the project's history to see how similar features had been implemented, which helped me understand the workflow. (By this point, more component actions had been implemented, so I had a chance to learn by looking at previous PRs + the docs on adding new components/component actions were updated, making the implementation process clear).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lesson learned:&lt;/em&gt;&lt;/strong&gt; It's much easier to tune into a project that is further along in its development, as there's more work to reference and learn from.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After studying the project, I began coding by following the instructions in the &lt;a href="https://docs.bytechef.io/developer_guide/component_specification/action/" rel="noopener noreferrer"&gt;ByteChef Developer Guide&lt;/a&gt; and referencing existing actions for guidance. &lt;/p&gt;

&lt;p&gt;I discovered that creating an action starts with the &lt;code&gt;action()&lt;/code&gt; method from the &lt;code&gt;ComponentDsl&lt;/code&gt; package. It initializes an instance of &lt;code&gt;ModifiableActionDefinition&lt;/code&gt; which provides various methods, such as &lt;code&gt;title()&lt;/code&gt;, &lt;code&gt;description()&lt;/code&gt;, &lt;code&gt;properties()&lt;/code&gt;, and &lt;code&gt;perform()&lt;/code&gt;, to define the action’s properties and logic. Once all the properties are defined, the action is registered in the component handler, making it available for use.&lt;/p&gt;

&lt;p&gt;For the action I was implementing, no output was required. Its sole purpose was to send an HTTP &lt;code&gt;DELETE&lt;/code&gt; request to a specific API endpoint, using a table ID and a row ID as inputs. I constructed the URL for this request by referring to the &lt;a href="https://baserow.io/api-docs" rel="noopener noreferrer"&gt;Baserow documentation&lt;/a&gt; (you need to create an account to see the docs!). To execute the request, I utilized the &lt;code&gt;http()&lt;/code&gt; method provided by the &lt;code&gt;ActionContext&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;Overall, the project already provided all the necessary building blocks. My main task was to understand how these components worked together and supply the required parameters to define the action correctly. Once I understood the structure and flow, implementing the action became a straightforward and logical process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BaserowDeleteRowAction.java:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.bytechef.component.baserow.action&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bytechef&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;baserow&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BaserowConstants&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ROW_ID&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bytechef&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;baserow&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;constant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BaserowConstants&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;TABLE_ID&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bytechef&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;definition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ComponentDsl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bytechef&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;definition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ComponentDsl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.bytechef.component.definition.ActionContext&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.bytechef.component.definition.ComponentDsl.ModifiableActionDefinition&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.bytechef.component.definition.Parameters&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * @author Arina Kolodeznikova
 */&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaserowDeleteRowAction&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ModifiableActionDefinition&lt;/span&gt; &lt;span class="no"&gt;ACTION_DEFINITION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"deleteRow"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Delete Row"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Deletes the specified row."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TABLE_ID&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Table ID"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ID of the table containing the row to be deleted."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;integer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ROW_ID&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Row ID"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ID of the row to be deleted."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;perform&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;BaserowDeleteRowAction:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;perform&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;BaserowDeleteRowAction&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;Parameters&lt;/span&gt; &lt;span class="n"&gt;inputParameters&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Parameters&lt;/span&gt; &lt;span class="n"&gt;connectionParameters&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ActionContext&lt;/span&gt; &lt;span class="n"&gt;actionContext&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="n"&gt;actionContext&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"/database/rows/table/"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;inputParameters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRequiredString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TABLE_ID&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"/"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                    &lt;span class="n"&gt;inputParameters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRequiredString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ROW_ID&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;After implementing the action, I tested the row deletion by rebuilding the project, starting the server and client, creating a test table in my Baserow account, setting up the test workflow in the frontend, adding the delete row action for the Baserow component, connecting the component to the service using my Baserow credentials, inputting the table and row IDs, and executing the workflow — and it worked as expected! (For details on creating and testing components, refer to &lt;a href="https://docs.bytechef.io/automation/getting-started/quick-start/" rel="noopener noreferrer"&gt;ByteChef's Quick Start Guide&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating the Delete Row action:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafbwx5o1rkgf5bcwh89m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafbwx5o1rkgf5bcwh89m.png" alt="Delete Row Action - UI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow successfully running:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyzxxq8b9vvvequ46umh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyzxxq8b9vvvequ46umh.png" alt="Testing the workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The row I specified (row #1) is no longer in the DB:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj9961utngxy3dmqyos8k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj9961utngxy3dmqyos8k.png" alt="Row deleted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After confirming that my action worked as expected, I began working on the unit test. I reviewed tests for other Baserow actions and found that they were fairly simple, involving the use of &lt;code&gt;JUnit&lt;/code&gt; and &lt;code&gt;Mockito&lt;/code&gt; for mocking API interactions and input parameters to ensure the correct API calls were made and expected results returned.&lt;/p&gt;

&lt;p&gt;Following this approach, I mocked the &lt;code&gt;ActionContext&lt;/code&gt;, &lt;code&gt;Http.Executor&lt;/code&gt;, and &lt;code&gt;Http.Response&lt;/code&gt; to simulate the API. Using &lt;code&gt;MockParametersFactory&lt;/code&gt;, I created mock parameters for the table and row IDs. I then configured the &lt;code&gt;Http.Executor&lt;/code&gt; to return the mocked response and tested the &lt;code&gt;perform()&lt;/code&gt; method, confirming it returned &lt;code&gt;null&lt;/code&gt; as expected for a successful row deletion. (See my unit test &lt;a href="https://github.com/bytechefhq/bytechef/pull/1743/files#diff-ee169093fa508343b5e5bca8a717b134cf9aa6e9b4e2e07034924b5ad6cd1c0f" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;After several iterations of formatting the code, running tests, and fixing minor issues, all tests passed, and my changes were ready for a PR. I went ahead and submitted a Pull Request, and it was merged the following day!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgwm08w17dl42n0bppscy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgwm08w17dl42n0bppscy.png" alt="Test success!"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/bytechefhq/bytechef/pull/1743" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        1642 - baserow delete row action
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1743&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F105298302%3Fv%3D4" alt="arilloid avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;arilloid&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/bytechefhq/bytechef/pull/1743" rel="noopener noreferrer"&gt;&lt;time&gt;Nov 15, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Description&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Implemented the Delete Row action for the Baserow component to enable users to remove specific rows from a table within their Baserow database.&lt;/p&gt;
&lt;p&gt;Fixes #1642&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Type of change&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;New feature (non-breaking change which adds functionality)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How Has This Been Tested?&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Added a new unit test and executed it alongside the existing test in the module to ensure all tests pass successfully.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/1db96e957e5fd26d804737749c056dfa294ebe667d0b57536b8a1464a04b28d7/68747470733a2f2f6465762d746f2d75706c6f6164732e73332e616d617a6f6e6177732e636f6d2f75706c6f6164732f61727469636c65732f67776d3038773137646c34326e306270707363792e706e67"&gt;&lt;img src="https://camo.githubusercontent.com/1db96e957e5fd26d804737749c056dfa294ebe667d0b57536b8a1464a04b28d7/68747470733a2f2f6465762d746f2d75706c6f6164732e73332e616d617a6f6e6177732e636f6d2f75706c6f6164732f61727469636c65732f67776d3038773137646c34326e306270707363792e706e67" alt="Test success!"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Manually tested the action by creating and executing a test workflow on the client side.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Created a test workflow that included a Baserow delete row action. Configured the workflow by adding the authentication token to connections and specifying the table ID and row ID for the testing Baserow table:
&lt;a rel="noopener noreferrer" href="https://github.com/user-attachments/assets/b3a54b95-1f4a-4461-9b23-df3027935a09"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2Fb3a54b95-1f4a-4461-9b23-df3027935a09" alt="Baserow Delete Row Action"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Executed the workflow:
&lt;a rel="noopener noreferrer" href="https://github.com/user-attachments/assets/07de9873-4742-4214-88a4-c96b133c68c4"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2F07de9873-4742-4214-88a4-c96b133c68c4" alt="Workflow executed successfully"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Checked the specified Baserow database table to confirm that the specified row was successfully deleted.:
&lt;a rel="noopener noreferrer" href="https://github.com/user-attachments/assets/90be1f78-abfa-4dd4-974c-07aea5da1548"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2F90be1f78-abfa-4dd4-974c-07aea5da1548" alt="Row deleted"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Checklist:&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[x] My code follows the style guidelines of this project&lt;/li&gt;
&lt;li&gt;[x] I have performed a self-review of my own code&lt;/li&gt;
&lt;li&gt;[ ] I have commented my code, particularly in hard-to-understand areas
&lt;ul&gt;
&lt;li&gt;Referenced the code for other Baserow component actions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;[ ] I have made corresponding changes to the documentation
&lt;ul&gt;
&lt;li&gt;Running &lt;code&gt;gradlew generateDocumentation&lt;/code&gt; for the module did not produce any documentation updates&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;[x] My changes generate no new warnings&lt;/li&gt;
&lt;li&gt;[x] I have added tests that prove my fix is effective or that my feature works&lt;/li&gt;
&lt;li&gt;[x] New and existing unit tests pass locally with my changes&lt;/li&gt;
&lt;/ul&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/bytechefhq/bytechef/pull/1743" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;






&lt;h2&gt;
  
  
  The 2-nd issue I worked on
&lt;/h2&gt;

&lt;p&gt;After my first PR was merged, I was curious to implement an action for another component to explore how the backend integrates interactions with other services. I checked the open issues and found one related to adding an action for the Google Drive component.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/bytechefhq/bytechef/issues/1647" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Google Drive - Get File action
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1647&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/monikakuster" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F120166289%3Fv%3D4" alt="monikakuster avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/monikakuster" rel="noopener noreferrer"&gt;monikakuster&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/bytechefhq/bytechef/issues/1647" rel="noopener noreferrer"&gt;&lt;time&gt;Oct 24, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;The Get File action for the Google Drive component is designed to retrieve a specified file from the user's Google Drive. This action allows users to access file metadata and content.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Action properties:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;file ID - the ID of the file you wish to retrieve&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Ouput:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;file - a file object containing detailed information about the retrieved file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Documentation Reference: &lt;a href="https://developers.google.com/drive/api/reference/rest/v3/files/get" rel="nofollow noopener noreferrer"&gt;https://developers.google.com/drive/api/reference/rest/v3/files/get&lt;/a&gt;&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/bytechefhq/bytechef/issues/1647" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I left a comment asking to be assigned the issue and also requesting feedback on possible areas for improvement in my previous PR. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbtyzq2ls3ik69snwt9zd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbtyzq2ls3ik69snwt9zd.png" alt="Interaction with the Issue creator"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although I didn't receive any feedback, the issue was assigned to me a couple of days later. At first, I was a bit surprised by the delay in responses (mainly because the maintainers had been super quick to reply and assign issues before), but after a quick Google search, I learned that there was a long weekend in Croatia, where most of the project maintainers are based.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note:&lt;/em&gt;&lt;/strong&gt; The ability to put yourself in someone else's shoes is especially important when working with people from all around the world. As for me, I certainly wouldn't want to be bothered during the holidays.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Contribution Process
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Implementing the feature
&lt;/h3&gt;

&lt;p&gt;I was already familiar with the project, so writing the second feature was much easier. The main difference between writing the action for Baserow and Google Drive was that it used different custom classes. So, this time, I essentially needed to familiarize myself with a few new "building blocks", the key one being the Google API SDK library for Java.&lt;/p&gt;

&lt;p&gt;I read the &lt;a href="https://developers.google.com/drive/api/reference/rest/v3/files/get" rel="noopener noreferrer"&gt;documentation reference&lt;/a&gt; linked by the maintainer and realized that I saw the same method in the Google Drive Copy File action. By extracting the necessary components from the existing logic, I was able to write an action that returns the metadata for the selected file in the linked Google Drive (See the code on &lt;a href="https://github.com/bytechefhq/bytechef/pull/1753/files#diff-627c74b2cb89d465d91cc75a4b747dd2c72762e647a9b4fd2281599b5c7b91c0" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing the feature
&lt;/h3&gt;

&lt;p&gt;Manually testing the feature was fun, as I got to set up a Google Cloud account and &lt;a href="https://support.google.com/googleapi/answer/6158849?hl=en" rel="noopener noreferrer"&gt;OAuth2&lt;/a&gt; credentials to access my Google Drive from the frontend application. (I followed the instructions for the Google Drive component in the &lt;a href="https://docs.bytechef.io/reference/components/google-drive/#connection" rel="noopener noreferrer"&gt;docs&lt;/a&gt; to generate the necessary credentials).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retrieving the metadata for one of my Google Drive documents:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw4ufy18k3fumr1hoctem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw4ufy18k3fumr1hoctem.png" alt="UI workflow executed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After manually testing the feature in the frontend, I created a unit test in the same way as before, using JUnit and Mockito (&lt;a href="https://github.com/bytechefhq/bytechef/pull/1753/files#diff-22c2ef4eda2b580813a63479b95141a06fa4860355370adaafe4c769824be560" rel="noopener noreferrer"&gt;GoogleDriveGetFileActionTest.java&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Then, I ran the code formatter, ensured that my code passed all the checks, and submitted a Pull Request, asking a few questions about the expected output in the comments. (However, as of writing this blog post, the maintainers haven’t yet responded).&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/bytechefhq/bytechef/pull/1753" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        1647 - Added Google Drive Get File Action
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1753&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F105298302%3Fv%3D4" alt="arilloid avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;arilloid&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/bytechefhq/bytechef/pull/1753" rel="noopener noreferrer"&gt;&lt;time&gt;Nov 19, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Description&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Added Get File action to the Google Drive component.&lt;/p&gt;
&lt;p&gt;Fixes #1647&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Type of change&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;New feature (non-breaking change which adds functionality)&lt;/li&gt;
&lt;li&gt;This change requires a documentation update&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How Has This Been Tested?&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Added a new unit test and executed it alongside the existing test in the module to ensure all tests pass successfully.&lt;/li&gt;
&lt;li&gt;Manually tested the action by creating and executing a test workflow on the client side.
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/667097bf7405975475440674a312d1e42ce4620873d48c53fc4f59c04b4a513e/68747470733a2f2f6465762d746f2d75706c6f6164732e73332e616d617a6f6e6177732e636f6d2f75706c6f6164732f61727469636c65732f773475667931386b3366756d7231686f6374656d2e706e67"&gt;&lt;img src="https://camo.githubusercontent.com/667097bf7405975475440674a312d1e42ce4620873d48c53fc4f59c04b4a513e/68747470733a2f2f6465762d746f2d75706c6f6164732e73332e616d617a6f6e6177732e636f6d2f75706c6f6164732f61727469636c65732f773475667931386b3366756d7231686f6374656d2e706e67" alt="Action on the client-side"&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Checklist:&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[x] My code follows the style guidelines of this project&lt;/li&gt;
&lt;li&gt;[x] I have performed a self-review of my own code&lt;/li&gt;
&lt;li&gt;[ ] I have commented my code, particularly in hard-to-understand areas
&lt;ul&gt;
&lt;li&gt;Referenced the code for other Google Drive component actions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;[ ] I have made corresponding changes to the documentation
&lt;ul&gt;
&lt;li&gt;Running &lt;code&gt;gradlew generateDocumentation&lt;/code&gt; for the module did not produce any documentation updates&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;[x] My changes generate no new warnings&lt;/li&gt;
&lt;li&gt;[x] I have added tests that prove my fix is effective or that my feature works&lt;/li&gt;
&lt;li&gt;[x] New and existing unit tests pass locally with my changes&lt;/li&gt;
&lt;/ul&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/bytechefhq/bytechef/pull/1753" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Afterthoughts
&lt;/h2&gt;

&lt;p&gt;Contributing to ByteChef was a valuable learning experience. I got to author new features and unit tests, learned the importance of taking time to understand the project structure and leveraging existing code as a reference for implementing new features. + I gained hands-on experience with new tools and libraries, including Gradle, Baserow, the Google Drive API SDK, JUnit, and Mockito.&lt;/p&gt;
&lt;/div&gt;

</description>
      <category>opensource</category>
      <category>java</category>
      <category>springboot</category>
    </item>
    <item>
      <title>Adding CI Workflows with GitHub Actions</title>
      <dc:creator>arinak1017</dc:creator>
      <pubDate>Sat, 16 Nov 2024 23:53:15 +0000</pubDate>
      <link>https://dev.to/arilloid/adding-ci-workflows-with-github-actions-d26</link>
      <guid>https://dev.to/arilloid/adding-ci-workflows-with-github-actions-d26</guid>
      <description>&lt;h2&gt;
  
  
  Hello, Blog!
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have just stumbled upon my OSD600 series of blog posts, it has been created to document and share my learnings as I progress through my Open Source Development college course.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another week, another blog post. This week, my classmates and I focused on creating a Continuous Integration workflow for our projects using GitHub Actions. Our mission was to create a GitHub Actions workflow that ensures our projects never get broken by automatically building the code and running tests on every Push and Pull Request to the &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;If you are curious, feel free to check out my project on GitHub:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;
        arilloid
      &lt;/a&gt; / &lt;a href="https://github.com/arilloid/addcom" rel="noopener noreferrer"&gt;
        addcom
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      a CLI tool for adding comments to your source code files
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;ADDCOM&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;addcom&lt;/code&gt; is a CLI source code documenter tool which provides coders with an easy way to add comments to their source code files
Give it a relative/absolute path to your file and it will analyze its contents and add comments using a Large Language Model's chat completion.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://private-user-images.githubusercontent.com/105298302/366692445-e01f1c1b-faf4-4c2d-b62b-a2492de1475b.gif?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzE4MDE0OTUsIm5iZiI6MTczMTgwMTE5NSwicGF0aCI6Ii8xMDUyOTgzMDIvMzY2NjkyNDQ1LWUwMWYxYzFiLWZhZjQtNGMyZC1iNjJiLWEyNDkyZGUxNDc1Yi5naWY_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQxMTE2JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MTExNlQyMzUzMTVaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1mMTc2MGI3NjNkOGEzYTdhODAyMzI5YTNiNjUzYmY4ZmRmMzU1NzM2NGUzN2QxZGIyMGZhODI0N2U3OTAyNjJjJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.EWugFVsNJxTAt1zPwz-pGTW8z4NyT02dKKnTXWAGsAM"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fprivate-user-images.githubusercontent.com%2F105298302%2F366692445-e01f1c1b-faf4-4c2d-b62b-a2492de1475b.gif%3Fjwt%3DeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzE4MDE0OTUsIm5iZiI6MTczMTgwMTE5NSwicGF0aCI6Ii8xMDUyOTgzMDIvMzY2NjkyNDQ1LWUwMWYxYzFiLWZhZjQtNGMyZC1iNjJiLWEyNDkyZGUxNDc1Yi5naWY_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQxMTE2JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MTExNlQyMzUzMTVaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1mMTc2MGI3NjNkOGEzYTdhODAyMzI5YTNiNjUzYmY4ZmRmMzU1NzM2NGUzN2QxZGIyMGZhODI0N2U3OTAyNjJjJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.EWugFVsNJxTAt1zPwz-pGTW8z4NyT02dKKnTXWAGsAM" alt="addcom"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See a demo of the functionality on YouTube: &lt;a href="https://youtu.be/3jKifG2BLzc?si=M2MNCW2BASBnDQ7z" rel="nofollow noopener noreferrer"&gt;addcom-demo&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Setup Instructions&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Prerequisites&lt;/h3&gt;

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Make sure Python is installed on your system (you can download it here: &lt;a href="https://www.python.org/downloads/" rel="nofollow noopener noreferrer"&gt;https://www.python.org/downloads/&lt;/a&gt;).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;1. After cloning the repo cd into the project folder and simply run:&lt;/h4&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-batchfile notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;pip install .&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;2. Default: Create an account and generate the API key here: &lt;a href="https://console.groq.com/" rel="nofollow noopener noreferrer"&gt;https://console.groq.com/&lt;/a&gt;
&lt;/h4&gt;

&lt;/div&gt;
&lt;p&gt;By default, addcom uses the Groq API endpoint for chat completion. However, you can specify a custom endpoint using the &lt;code&gt;--base-url&lt;/code&gt; or &lt;code&gt;-u&lt;/code&gt; flag option. (If you do this, make sure to obtain an appropriate API key and specify the model supported by the chosen provider using…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/arilloid/addcom" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I welcome feedback/&lt;a href="https://github.com/arilloid/addcom/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;contributions&lt;/a&gt;, so don’t hesitate to take a look and get involved 😊&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a GitHub Actions Workflow
&lt;/h2&gt;

&lt;p&gt;To set up my workflow, I used the GitHub Actions web interface and followed GitHub's &lt;a href="https://docs.github.com/en/actions/use-cases-and-examples/building-and-testing/building-and-testing-python" rel="noopener noreferrer"&gt;Building and testing Python guide&lt;/a&gt;. I started with the Python Application workflow template. I tweaked it to build and test my project based on the guide's instructions.&lt;/p&gt;

&lt;p&gt;The final workflow file with the &lt;code&gt;build-and-test&lt;/code&gt; job: &lt;a href="https://github.com/arilloid/addcom/blob/main/.github/workflows/python-app.yml" rel="noopener noreferrer"&gt;python-app.yml&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Unit Tests&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main"&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main"&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build-and-test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout code&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Python&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v5&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.12"&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build the tool&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;pip install .&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test with pytest&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;pip install pytest pytest-mock&lt;/span&gt;
        &lt;span class="s"&gt;pytest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;On every push and pull request to &lt;code&gt;main&lt;/code&gt;, this workflow sets up a Python 3.12 environment, installs the project as a package, and runs tests using &lt;code&gt;pytest&lt;/code&gt; to maintain code reliability.&lt;/p&gt;
&lt;h2&gt;
  
  
  Adding Tests to Another Project
&lt;/h2&gt;

&lt;p&gt;After setting up and testing my CI workflow, the next step was adding a new test case to one of my classmates' projects. This week, I worked on Jin's project:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/gitdevjin" rel="noopener noreferrer"&gt;
        gitdevjin
      &lt;/a&gt; / &lt;a href="https://github.com/gitdevjin/code-mage" rel="noopener noreferrer"&gt;
        code-mage
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/ab3d44f6fe1f1e7bc0b724be66557c87f2cd1d0b704f702597d50f3bbbc31872/68747470733a2f2f7668732e636861726d2e73682f7668732d35497a427a77593559764c554b694f314e74713844582e676966"&gt;&lt;img src="https://camo.githubusercontent.com/ab3d44f6fe1f1e7bc0b724be66557c87f2cd1d0b704f702597d50f3bbbc31872/68747470733a2f2f7668732e636861726d2e73682f7668732d35497a427a77593559764c554b694f314e74713844582e676966"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Description&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;CodeMage&lt;/strong&gt; is a tool that translates a source file written in one programming language into another language
The translation will be done by Large Language Model AI(such as ChatGPT)&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Release 0.1&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Features&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;1. Supported Languages: Javascript, Python, C++, Java
2. Default target Language is Python
3. Supported LLM model: openrouter, groq
4. Default LLM model is openrouter(sao10k/l3-euryale-70b)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Getting Started&lt;/h1&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;1. Install Python : &lt;a href="https://www.python.org/downloads/" rel="nofollow noopener noreferrer"&gt;https://www.python.org/downloads/&lt;/a&gt;
&lt;/h3&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;2. Install Poetry&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-text-shell-session notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c1"&gt;curl -sSL https://install.python-poetry.org | python3 -&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;OR&lt;/strong&gt; if you have &lt;code&gt;pipx&lt;/code&gt; installed on your local machine, you can use the following commend&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/pypa/pipx" rel="noopener noreferrer"&gt;How to download &lt;code&gt;pipx&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight highlight-text-shell-session notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c1"&gt;pipx install poetry&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;3. Clone the repository&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-text-shell-session notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c1"&gt;git clone https://github.com/gitdevjin/code-mage.git&lt;/span&gt;
&lt;span class="pl-c1"&gt;cd code_mage&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;4. Install Poetry Package&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-text-shell-session notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c1"&gt;poetry install&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;5. Create your API_KEY at &lt;a href="https://openrouter.ai/docs/api-keys" rel="nofollow noopener noreferrer"&gt;openrouter&lt;/a&gt; Or &lt;a href="https://console.groq.com/keys" rel="nofollow noopener noreferrer"&gt;Groq&lt;/a&gt;
&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;It's free with sign-up. You can easily sign-up with your google account&lt;/p&gt;
&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;6. Create &lt;code&gt;.env&lt;/code&gt; file in the root directory and save the following:&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;OPENROUTER_API_KEY=your_open_router_api_key
GROQ_API_KEY=your_groq_api_key
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now you are ready…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/gitdevjin/code-mage" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;As I scanned Jin's repository, I noticed that our testing and workflow setups share many similarities, likely because we both have Python projects and use &lt;code&gt;pytest&lt;/code&gt; for testing. However, there were a few notable differences: Jin uses &lt;code&gt;Poetry&lt;/code&gt; for packaging and dependency management, causing the differences in the build and test setup; he organizes test cases by file rather than by function, as I do; and he relies on &lt;code&gt;unittest.mock&lt;/code&gt; instead of &lt;code&gt;pytest-mock&lt;/code&gt; for mocking.&lt;/p&gt;

&lt;p&gt;Since I was already familiar with the stack, writing a new test case for Jin's project didn’t pose any challenges. The main hurdle was identifying an untested area, as Jin had already written comprehensive tests for most of the functionality. After discussing it with him, he suggested focusing on argument parsing.&lt;/p&gt;

&lt;p&gt;Following his recommendation, I reviewed the existing argument parsing function and tests and decided to write a test case for handling invalid flag argument options:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Test invalid flag argument option
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_arg_parser_invalid_option&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sys.argv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code_mage.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--invalid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;SystemExit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;excinfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;arg_parser&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;excinfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="nb"&gt;SystemExit&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;excinfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I added this test to the &lt;a href="https://github.com/gitdevjin/code-mage/blob/main/tests/test_argsParser.py" rel="noopener noreferrer"&gt;tests/test_argsParser.py&lt;/a&gt;, ran it locally to ensure that it works as intended, and submitted a PR. My code passed Jin's CI workflow and got merged to &lt;code&gt;main&lt;/code&gt; almost right away.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/gitdevjin/code-mage/pull/17" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Added a new test case in test_argsParser.py
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#17&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F105298302%3Fv%3D4" alt="arilloid avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;arilloid&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/gitdevjin/code-mage/pull/17" rel="noopener noreferrer"&gt;&lt;time&gt;Nov 15, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Hello @gitdevjin ,&lt;/p&gt;
&lt;p&gt;I added a new test case in &lt;code&gt;test_argsParser.py&lt;/code&gt; to make sure that the argument parser terminates the program with a non-zero code when invoked with an invalid flag.&lt;/p&gt;
&lt;div class="highlight highlight-source-python js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;# Test invalid flag argument option&lt;/span&gt;
&lt;span class="pl-k"&gt;def&lt;/span&gt; &lt;span class="pl-en"&gt;test_arg_parser_invalid_option&lt;/span&gt;():
    &lt;span class="pl-k"&gt;with&lt;/span&gt; &lt;span class="pl-en"&gt;patch&lt;/span&gt;(&lt;span class="pl-s"&gt;"sys.argv"&lt;/span&gt;, [&lt;span class="pl-s"&gt;"code_mage.py"&lt;/span&gt;, &lt;span class="pl-s"&gt;"--invalid"&lt;/span&gt;]):
        &lt;span class="pl-k"&gt;with&lt;/span&gt; &lt;span class="pl-s1"&gt;pytest&lt;/span&gt;.&lt;span class="pl-en"&gt;raises&lt;/span&gt;(&lt;span class="pl-v"&gt;SystemExit&lt;/span&gt;) &lt;span class="pl-k"&gt;as&lt;/span&gt; &lt;span class="pl-s1"&gt;excinfo&lt;/span&gt;:
            &lt;span class="pl-en"&gt;arg_parser&lt;/span&gt;({})
        &lt;span class="pl-k"&gt;assert&lt;/span&gt; &lt;span class="pl-s1"&gt;excinfo&lt;/span&gt;.&lt;span class="pl-s1"&gt;type&lt;/span&gt; &lt;span class="pl-c1"&gt;is&lt;/span&gt; &lt;span class="pl-v"&gt;SystemExit&lt;/span&gt;
        &lt;span class="pl-k"&gt;assert&lt;/span&gt; &lt;span class="pl-s1"&gt;excinfo&lt;/span&gt;.&lt;span class="pl-s1"&gt;value&lt;/span&gt;.&lt;span class="pl-s1"&gt;code&lt;/span&gt; &lt;span class="pl-c1"&gt;!=&lt;/span&gt; &lt;span class="pl-c1"&gt;0&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/gitdevjin/code-mage/pull/17" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Afterthoughts
&lt;/h2&gt;

&lt;p&gt;Although I wasn’t too familiar with writing CI workflows at the start of this week, the entire process turned out to be straightforward (largely thanks to the simplicity of my CLI tool). + I’m glad I had the opportunity to dive into the GitHub Actions documentation, as I know that it will certainly come in handy in my future projects.&lt;/p&gt;

&lt;p&gt;Having been on both sides of the process - as a contributor and a repository maintainer, I can confidently say that a solid CI workflow is very helpful. It streamlines the development and provides peace of mind, knowing that no breaking changes will sneak into my &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;

</description>
      <category>github</category>
      <category>git</category>
      <category>ci</category>
    </item>
    <item>
      <title>Automated Testing with Pytest</title>
      <dc:creator>arinak1017</dc:creator>
      <pubDate>Sun, 10 Nov 2024 01:06:22 +0000</pubDate>
      <link>https://dev.to/arilloid/automated-testing-with-pytest-2c9g</link>
      <guid>https://dev.to/arilloid/automated-testing-with-pytest-2c9g</guid>
      <description>&lt;h2&gt;
  
  
  Hello, Blog!
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have just stumbled upon my OSD600 series of blog posts, it has been created to document and share my learnings as I progress through my Open Source Development college course.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aside from continuing to work on contributing to Open Source projects, this week's focus was on looking into "managing project complexity through the use of Automated Testing" &amp;amp; starting to write test cases for our CLI tools.&lt;/p&gt;

&lt;p&gt;Testing is a fundamental aspect of software development. Tests allow us to refine the code's logic, ensuring each component performs as expected even when handling edge cases. Automated tests make it easier to introduce changes to code without breaking its core logic, which is especially important in the Open Source project (as they rely on collaboration). &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Helpful links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://betterstack.com/community/guides/testing/pytest-guide/#step-7-parametrizing-tests-using-data-classes" rel="noopener noreferrer"&gt;A Beginner's Guide to Unit Testing with Pytest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@adocquin/mastering-unit-tests-in-python-with-pytest-a-comprehensive-guide-896c8c894304" rel="noopener noreferrer"&gt;Mastering Unit Tests in Python with pytest: A Comprehensive Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.pytest.org/en/stable/" rel="noopener noreferrer"&gt;pytest documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pytest-mock.readthedocs.io/en/latest/usage.html" rel="noopener noreferrer"&gt;pytests-mock documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/arilloid/addcom" rel="noopener noreferrer"&gt;My Project Repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/arilloid" rel="noopener noreferrer"&gt;
        arilloid
      &lt;/a&gt; / &lt;a href="https://github.com/arilloid/addcom" rel="noopener noreferrer"&gt;
        addcom
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      a CLI tool for adding comments to your source code files
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;ADDCOM&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;addcom&lt;/code&gt; is a CLI source code documenter tool which provides coders with an easy way to add comments to their source code files
Give it a relative/absolute path to your file and it will analyze its contents and add comments using a Large Language Model's chat completion.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://private-user-images.githubusercontent.com/105298302/366692445-e01f1c1b-faf4-4c2d-b62b-a2492de1475b.gif?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzEyMDIyMDEsIm5iZiI6MTczMTIwMTkwMSwicGF0aCI6Ii8xMDUyOTgzMDIvMzY2NjkyNDQ1LWUwMWYxYzFiLWZhZjQtNGMyZC1iNjJiLWEyNDkyZGUxNDc1Yi5naWY_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQxMTEwJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MTExMFQwMTI1MDFaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1mODYzNWU5NTYyZjM4YzAzMGE5MmEzYjhhNDk1NjAwNTc3NmVmYjc5NmM0YzZiZjQzMDZlMTQxZmE3ZmZmYjA3JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.Xv16jqgoOHj7-FUd5iUjlcH8YihJfj8BTlZWsNAuuxM"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fprivate-user-images.githubusercontent.com%2F105298302%2F366692445-e01f1c1b-faf4-4c2d-b62b-a2492de1475b.gif%3Fjwt%3DeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzEyMDIyMDEsIm5iZiI6MTczMTIwMTkwMSwicGF0aCI6Ii8xMDUyOTgzMDIvMzY2NjkyNDQ1LWUwMWYxYzFiLWZhZjQtNGMyZC1iNjJiLWEyNDkyZGUxNDc1Yi5naWY_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQxMTEwJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MTExMFQwMTI1MDFaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1mODYzNWU5NTYyZjM4YzAzMGE5MmEzYjhhNDk1NjAwNTc3NmVmYjc5NmM0YzZiZjQzMDZlMTQxZmE3ZmZmYjA3JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.Xv16jqgoOHj7-FUd5iUjlcH8YihJfj8BTlZWsNAuuxM" alt="addcom"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See a demo of the functionality on YouTube: &lt;a href="https://youtu.be/3jKifG2BLzc?si=M2MNCW2BASBnDQ7z" rel="nofollow noopener noreferrer"&gt;addcom-demo&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Setup Instructions&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Prerequisites&lt;/h3&gt;

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Make sure Python is installed on your system (you can download it here: &lt;a href="https://www.python.org/downloads/" rel="nofollow noopener noreferrer"&gt;https://www.python.org/downloads/&lt;/a&gt;).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;1. After cloning the repo cd into the project folder and simply run:&lt;/h4&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-batchfile notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;pip install .&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;2. Default: Create an account and generate the API key here: &lt;a href="https://console.groq.com/" rel="nofollow noopener noreferrer"&gt;https://console.groq.com/&lt;/a&gt;
&lt;/h4&gt;

&lt;/div&gt;
&lt;p&gt;By default, addcom uses the Groq API endpoint for chat completion. However, you can specify a custom endpoint using the &lt;code&gt;--base-url&lt;/code&gt; or &lt;code&gt;-u&lt;/code&gt; flag option. (If you do this, make sure to obtain an appropriate API key and specify the model supported by the chosen provider using…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/arilloid/addcom" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I welcome feedback/&lt;a href="https://github.com/arilloid/addcom/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;contributions&lt;/a&gt;, so don’t hesitate to take a look and get involved 😊&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting to write tests in Python
&lt;/h2&gt;

&lt;p&gt;Beforehand, I had only written tests using Jest in one of my Node.js projects, so I had a general understanding of how to approach testing. However, I had no experience with testing in Python. &lt;/p&gt;

&lt;p&gt;So, to start, I went "shopping" for the right testing library. After reading a couple of articles and community discussions, I decided to begin writing tests using &lt;a href="https://docs.pytest.org/en/stable/" rel="noopener noreferrer"&gt;Pytest&lt;/a&gt; in combination with the &lt;a href="https://pytest-mock.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;pytest-mock&lt;/a&gt; plugin, which I used to mock the API interactions with the LLM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Pytest?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Pytest&lt;/code&gt; is one of the most popular testing frameworks that combines simple syntax (e.g. less boilerplate code compared to Python's built-in &lt;code&gt;unittest&lt;/code&gt; library) with powerful features and a vast ecosystem of plugins for nearly every testing scenario.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prep &amp;amp; Setup
&lt;/h3&gt;

&lt;p&gt;Before diving straight into the documentation, I like to go through a few simple beginner guides to get a quick overview of the tools and their functionality. I did the same with Pytest, reading two beginner guides before jumping into setup and coding (&lt;a href="https://betterstack.com/community/guides/testing/pytest-guide/#step-7-parametrizing-tests-using-data-classes" rel="noopener noreferrer"&gt;A Beginner's Guide to Unit Testing with Pytest&lt;/a&gt;, &lt;a href="https://medium.com/@adocquin/mastering-unit-tests-in-python-with-pytest-a-comprehensive-guide-896c8c894304" rel="noopener noreferrer"&gt;Mastering Unit Tests in Python with pytest: A Comprehensive Guide&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The setup was close to none, I simply installed the library and the mocking plugin using &lt;code&gt;pip&lt;/code&gt;, created a new &lt;code&gt;tests/&lt;/code&gt; folder at the root of my project, and was good to go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;pytest pytest-mock
&lt;span class="nb"&gt;mkdir &lt;/span&gt;tests/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Writing the first test
&lt;/h3&gt;

&lt;p&gt;I began testing with the simplest function in my project: the &lt;code&gt;version_callback()&lt;/code&gt; function, which prints the version of the CLI tool when the &lt;code&gt;--version&lt;/code&gt;/&lt;code&gt;-v&lt;/code&gt; flag is provided.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I covered three test cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Successful version output – Verifying that the version prints correctly to the terminal when the flag is used.&lt;/li&gt;
&lt;li&gt;No flag behaviour – Ensuring that not providing the flag does not cause any unexpected behaviour.&lt;/li&gt;
&lt;li&gt;Handling unset version – Confirming that the function prints an appropriate message if the version is not set.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Writing the tests was straightforward, I mostly followed examples from guides and documentation, with occasional clarifications from an AI chatbot. &lt;/p&gt;

&lt;p&gt;I used &lt;code&gt;pytest&lt;/code&gt; assertions for stdout comparisons and &lt;code&gt;pytest.raises&lt;/code&gt; for exception checks and also got to try out the patching to replace the imported version value with &lt;code&gt;None&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typer&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Exit&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.core.callbacks&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;version_callback&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;__version__&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_version_callback_without_version_defined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mocker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capfd&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Test version callback function when the version is not defined
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;mocker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app.core.callbacks.__version__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;version_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;provided&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Capture the output
&lt;/span&gt;    &lt;span class="n"&gt;captured&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capfd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readouterr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Check that it prints a fallback message instead of the version
&lt;/span&gt;    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;version not defined&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;captured&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See the full code on &lt;a href="https://github.com/arilloid/addcom/blob/main/tests/test_version_callback.py" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing the core functionality/Mocking LLM interactions
&lt;/h3&gt;

&lt;p&gt;The core functionality of the tool revolves around interacting with the LLM, which is handled in the &lt;code&gt;generate_comments()&lt;/code&gt; function. To test this, I needed to mock the LLM interaction.&lt;/p&gt;

&lt;p&gt;To simulate the OpenAI client interaction, I used the &lt;code&gt;pytest-mock&lt;/code&gt; plugin with its &lt;code&gt;mocker&lt;/code&gt; fixture. This allowed me to mock the behaviour of the OpenAI client and control the responses returned by its methods during testing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In &lt;code&gt;pytest&lt;/code&gt;, a &lt;a href="https://docs.pytest.org/en/stable/explanation/fixtures.html" rel="noopener noreferrer"&gt;fixture&lt;/a&gt; is a function that prepares and provides the necessary setup for tests. Fixtures are defined with the &lt;code&gt;@pytest.fixture&lt;/code&gt; decorator and can be automatically passed into test functions as arguments.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@pytest.fixture&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mock_openai_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mocker&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Fixture to mock the OpenAI client and its responses
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Create a mock object with MagicMock()
&lt;/span&gt;    &lt;span class="n"&gt;mock_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mocker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;# Replace the client with the mock object whenever 
&lt;/span&gt;    &lt;span class="c1"&gt;# OpenaAI() is called in the code
&lt;/span&gt;    &lt;span class="n"&gt;mocker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app.core.api.OpenAI&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mock_client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mock_client&lt;/span&gt;

&lt;span class="c1"&gt;####################################################################
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_generate_comments_with_api_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test_parameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mocker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_openai_client&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Test that the function generates expected output when a valid file path and API key are provided
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;test_parameters&lt;/span&gt;

    &lt;span class="n"&gt;commented_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
                    def generate_fibonacci(limit):
                        # Initialize the Fibonacci sequence with the first two numbers
                        fibonacci_sequence = [0, 1]
                        # Generate Fibonacci numbers until the next number exceeds the given limit
                        while True:
                            # Calculate the next number in the sequence
                            next_number = fibonacci_sequence[-1] + fibonacci_sequence[-2]
                            # Stop generating if the next number exceeds the limit
                            if next_number &amp;gt; limit:
                                break
                            # Append the next number to the sequence
                            fibonacci_sequence.append(next_number)
                        return fibonacci_sequence

                    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# Replicate the OpenAI client response structure using mock objects
&lt;/span&gt;    &lt;span class="n"&gt;mock_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mocker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;mock_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;mocker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mocker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;commented_code&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="c1"&gt;# Set the result of the mock chat completion to the mock response,
&lt;/span&gt;    &lt;span class="c1"&gt;# so when the value is accessed in the code it gives the expected result
&lt;/span&gt;    &lt;span class="n"&gt;mock_openai_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mock_response&lt;/span&gt;

    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_comments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test_api_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;commented_code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See the full code on &lt;a href="https://github.com/arilloid/addcom/blob/main/tests/test_generate_comments.py" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Afterthoughts
&lt;/h2&gt;

&lt;p&gt;From the start, I tried making my code clean and modular by breaking it down into smaller functions. This approach certainly made my project more testable. But, along the way, I realized that I hadn't fully accounted for all possible edge cases ("Wait, does the logic break when this value is None?"). From now on, I will try to look at my code more critically by asking more "what if?" questions.&lt;/p&gt;

&lt;p&gt;Writing the first few tests helped me gain a solid understanding of &lt;code&gt;pytest&lt;/code&gt;. I learned how to do simple assertions, test exceptions, capture data written to the terminal, use &lt;code&gt;fixtures&lt;/code&gt; for setup, and how to replace values and mock different objects using &lt;code&gt;mocker&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Although testing the &lt;code&gt;generate_comments()&lt;/code&gt; and &lt;code&gt;version_callback()&lt;/code&gt; functions has given me a good foundation, I still need to improve test coverage, explore testing argument parsing and figure out a way to test the main entry point function.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>python</category>
    </item>
  </channel>
</rss>
