<?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>Forem: Dimitrios Desyllas</title>
    <description>The latest articles on Forem by Dimitrios Desyllas (@pcmagas).</description>
    <link>https://forem.com/pcmagas</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%2F220271%2Fa708bc93-e149-448c-a66e-f871603dcb6e.jpg</url>
      <title>Forem: Dimitrios Desyllas</title>
      <link>https://forem.com/pcmagas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/pcmagas"/>
    <language>en</language>
    <item>
      <title>How I can perform spellcheck in a TkInter Entry:</title>
      <dc:creator>Dimitrios Desyllas</dc:creator>
      <pubDate>Tue, 10 Mar 2026 17:12:33 +0000</pubDate>
      <link>https://forem.com/pcmagas/how-i-can-perform-spellcheck-in-a-tkinter-entry-56pc</link>
      <guid>https://forem.com/pcmagas/how-i-can-perform-spellcheck-in-a-tkinter-entry-56pc</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__stackexchange--container"&gt;
  &lt;div class="ltag__stackexchange--title-container"&gt;
    
      &lt;div class="ltag__stackexchange--title"&gt;
        &lt;div class="ltag__stackexchange--header"&gt;
          &lt;img src="https://assets.dev.to/assets/stackoverflow-logo-b42691ae545e4810b105ee957979a853a696085e67e43ee14c5699cf3e890fb4.svg" alt=""&gt;
          &lt;a href="https://stackoverflow.com/questions/79904760/how-i-can-perform-spellcheck-in-a-tkinter-entry" rel="noopener noreferrer"&gt;
            How I can perform spellcheck in a TkInter Entry:
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="ltag__stackexchange--post-metadata"&gt;
          &lt;span&gt;Mar 10 '26&lt;/span&gt;
            &lt;span&gt;Comments: 1&lt;/span&gt;
            &lt;span&gt;Answers: 1&lt;/span&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;a class="ltag__stackexchange--score-container" href="https://stackoverflow.com/questions/79904760/how-i-can-perform-spellcheck-in-a-tkinter-entry" rel="noopener noreferrer"&gt;
        &lt;img src="https://assets.dev.to/assets/stackexchange-arrow-up-eff2e2849e67d156181d258e38802c0b57fa011f74164a7f97675ca3b6ab756b.svg" alt=""&gt;
        &lt;div class="ltag__stackexchange--score-number"&gt;
          0
        &lt;/div&gt;
        &lt;img src="https://assets.dev.to/assets/stackexchange-arrow-down-4349fac0dd932d284fab7e4dd9846f19a3710558efde0d2dfd05897f3eeb9aba.svg" alt=""&gt;
      &lt;/a&gt;
    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--body"&gt;
    
&lt;p&gt;I made this type of input:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
class PasteableEntry(tk.Entry)
    def __init__(self, master=None,initial_value:str="", **kwargs):
        super().__init__(master, **kwargs)
        self.initial_value = initial_value
        self.insert(tk.END, self.initial_value)

        # Clipboard bindings
        self.bind("&amp;lt;Control-c&amp;gt;", self.copy)
        self.bind("&amp;lt;Control-x&amp;gt;", self.cut)
        self.bind("&amp;lt;Control-v&amp;gt;", self.paste)

        # Undo binding
        self.bind("&amp;lt;Control-z&amp;gt;", self.reset_value)

        # Border
        self.configure(highlightthickness=2, highlightbackground="gray", highlightcolor="blue")

    # --- Clipboard overrides ---
    def copy(self, event=None):
        try:
            selection = self.selection_get()&lt;/code&gt;&lt;/pre&gt;…
    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--btn--container"&gt;
    &lt;a href="https://stackoverflow.com/questions/79904760/how-i-can-perform-spellcheck-in-a-tkinter-entry" class="ltag__stackexchange--btn" rel="noopener noreferrer"&gt;Open Full Question&lt;/a&gt;
  &lt;/div&gt;
&lt;/div&gt;




&lt;p&gt;As I ask in question above I am looking for an apprkach on how I can spellcheck an tkInter entry. I am building a whatsappo template manager and I want to be able to spellcheck my inputs.&lt;/p&gt;

&lt;p&gt;Can you reccomend me an approach?&lt;/p&gt;

</description>
      <category>help</category>
      <category>python</category>
    </item>
    <item>
      <title>Why I am unable to close the A Tkinter frame and create another one?</title>
      <dc:creator>Dimitrios Desyllas</dc:creator>
      <pubDate>Wed, 04 Mar 2026 17:20:00 +0000</pubDate>
      <link>https://forem.com/pcmagas/why-i-am-unable-to-close-the-a-tkinter-frame-and-create-another-one-3ao9</link>
      <guid>https://forem.com/pcmagas/why-i-am-unable-to-close-the-a-tkinter-frame-and-create-another-one-3ao9</guid>
      <description>&lt;p&gt;As I ask upon:&lt;br&gt;


&lt;/p&gt;
&lt;div class="ltag__stackexchange--container"&gt;
  &lt;div class="ltag__stackexchange--title-container"&gt;
    
      &lt;div class="ltag__stackexchange--title"&gt;
        &lt;div class="ltag__stackexchange--header"&gt;
          &lt;img src="https://assets.dev.to/assets/stackoverflow-logo-b42691ae545e4810b105ee957979a853a696085e67e43ee14c5699cf3e890fb4.svg" alt=""&gt;
          &lt;a href="https://stackoverflow.com/questions/79901060/why-i-am-unable-to-close-the-a-tkinter-frame-and-create-another-one" rel="noopener noreferrer"&gt;
            Why I am unable to close the A Tkinter frame and create another one?
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="ltag__stackexchange--post-metadata"&gt;
          &lt;span&gt;Mar  4 '26&lt;/span&gt;
            &lt;span&gt;Comments: 2&lt;/span&gt;
            &lt;span&gt;Answers: 1&lt;/span&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;a class="ltag__stackexchange--score-container" href="https://stackoverflow.com/questions/79901060/why-i-am-unable-to-close-the-a-tkinter-frame-and-create-another-one" rel="noopener noreferrer"&gt;
        &lt;img src="https://assets.dev.to/assets/stackexchange-arrow-up-eff2e2849e67d156181d258e38802c0b57fa011f74164a7f97675ca3b6ab756b.svg" alt=""&gt;
        &lt;div class="ltag__stackexchange--score-number"&gt;
          0
        &lt;/div&gt;
        &lt;img src="https://assets.dev.to/assets/stackexchange-arrow-down-4349fac0dd932d284fab7e4dd9846f19a3710558efde0d2dfd05897f3eeb9aba.svg" alt=""&gt;
      &lt;/a&gt;
    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--body"&gt;
    
&lt;p&gt;I made this tkinter app:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import os
import tkinter as tk
from tkinter import ttk
class SelectBodyScreen(ttk.Frame):

    def __init__(self,root, lang, prod_text,test_text, on_next):
        super().__init__(root)

        self.lang = lang
        self.prod_text_content = prod_text
        self.test_text_content = test_text
        self.root = root

        self.build_ui()
        self.on_next = on_next

    def next_clicked(self):
        selected_body = self.final_text.get("1.0", tk.END).strip()
        self.on_next(selected_body)

    def use_prod(self):
        text =&lt;/code&gt;&lt;/pre&gt;…
    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--btn--container"&gt;
    &lt;a href="https://stackoverflow.com/questions/79901060/why-i-am-unable-to-close-the-a-tkinter-frame-and-create-another-one" class="ltag__stackexchange--btn" rel="noopener noreferrer"&gt;Open Full Question&lt;/a&gt;
  &lt;/div&gt;
&lt;/div&gt;




&lt;p&gt;I am making a wizard where it generated a frame whilst closes another one upon next using Tkinter.&lt;/p&gt;

&lt;p&gt;My issue is that the frame is improperly closed as you can see upon:&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%2F0ipid4m6pqui413ztltq.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%2F0ipid4m6pqui413ztltq.png" alt="Improper closed Tkinter frame"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>help</category>
      <category>python</category>
    </item>
    <item>
      <title>Developing locally an aws lambda</title>
      <dc:creator>Dimitrios Desyllas</dc:creator>
      <pubDate>Wed, 24 Sep 2025 17:52:32 +0000</pubDate>
      <link>https://forem.com/pcmagas/developing-locally-an-aws-lambda-55ah</link>
      <guid>https://forem.com/pcmagas/developing-locally-an-aws-lambda-55ah</guid>
      <description>&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%2Fyqd3xm1rdsx8wwhkbwqc.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%2Fyqd3xm1rdsx8wwhkbwqc.png" alt=" " width="292" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem (as always)
&lt;/h2&gt;

&lt;p&gt;In my career, I’ve often seen AWS Lambdas deployed directly without the source code being committed to GitHub. Even worse, many projects lack a defined architecture or tooling that allows testing Lambdas locally before deployment.&lt;/p&gt;

&lt;p&gt;Here, I’ll walk through how to introduce some basic tools to fix this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup aws locally
&lt;/h2&gt;

&lt;p&gt;To run and debug Lambdas locally, we need an execution environment that mimics AWS services. For this, I recommend using LocalStack with Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:

    localstack:
      image: localstack/localstack
      ports:
        - "4566:4566"
        - "4510-4559:4510-4559"
      environment:
        - SERVICES=lambda,logs
        - DEBUG=1
        - LAMBDA_EXECUTOR=docker
        - DATA_DIR=/tmp/localstack/data
        - AWS_DEFAULT_REGION=eu-north-1
        - LOCALSTACK_API_KEY=${LOCALSTACK_API_KEY-}
        - USE_SSL=false
      volumes:
        - "./localstack/volume:/var/lib/localstack"
        - "/var/run/docker.sock:/var/run/docker.sock"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are 2 things you need to keep notice:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upon &lt;code&gt;SERVICES&lt;/code&gt; environmental variable we need to define 2 services:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;lambda&lt;/code&gt; that indicates we need to use localstack for lambda execution.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;logs&lt;/code&gt; in which any log outpud of the lambda would be outputed into stdout. This is the equivalent of cloudwatch service.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;We have disabled ssl upon &lt;code&gt;USE_SSL&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The spawned container need to communicate with docker in order to run the lambda. For this we need to define:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;LAMBDA_EXECUTOR&lt;/code&gt; as docker&lt;/li&gt;
&lt;li&gt;Map the docker socket file inside the container via a bind-mount. It is achieved via putting &lt;code&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/code&gt; upon volumes section.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Localstack is available thorugh &lt;code&gt;http://localhost:4566&lt;/code&gt; as defined upon:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ports:
        - "4566:4566"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Download Lambda code
&lt;/h2&gt;

&lt;p&gt;Lambda code is usually stored as a .zip file, which contains both the application code and its dependencies:&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%2Fqfxd2jnjmgnui3gp4td6.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%2Fqfxd2jnjmgnui3gp4td6.png" alt=" " width="292" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Detect lambda entrypoint
&lt;/h2&gt;

&lt;p&gt;Lambdas are node.js or python scripts, usually is is a function inside a specific file.&lt;/p&gt;

&lt;p&gt;For example, in a Python Lambda, the entrypoint is often defined as file_name.handler_function:&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%2F7kveq3ao67mskxah0eff.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%2F7kveq3ao67mskxah0eff.png" alt=" " width="800" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, AWS starts execution from the lambda_handler method inside lambda_function.py: &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%2Fsfp8iyg8sxfsh6h2ci9l.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%2Fsfp8iyg8sxfsh6h2ci9l.png" alt=" " width="800" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Identifying the entrypoint is crucial because it helps determine dependencies and setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing the Required Python or Node.js Version
&lt;/h2&gt;

&lt;p&gt;AWS Lambdas run with specific Python (or Node.js) runtimes (e.g., Python 3.9, 3.10).&lt;/p&gt;

&lt;p&gt;You can check which runtime is being used under the Code tab in the AWS Lambda console:&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%2Fcay1bue62uu6lmdvbpw2.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%2Fcay1bue62uu6lmdvbpw2.png" alt=" " width="800" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Organizing Code and Dependencies:
&lt;/h2&gt;

&lt;p&gt;Once you’ve downloaded the Lambda .zip, unzip it into a working directory. I recommend creating two folders:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Original Lambda → The raw contents of the .zip. (for example &lt;code&gt;my-lambda-orig&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Clean Repo → A structured project where you separate code from dependencies. (for example &lt;code&gt;my-lambda&lt;/code&gt;). Thefollowing stricture is reccomended:

&lt;ul&gt;
&lt;li&gt;src -&amp;gt; containing lambda source code&lt;/li&gt;
&lt;li&gt;tools -&amp;gt; for usesfull tools&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Why separate them?&lt;br&gt;
AWS often packages Lambdas with both source code and dependencies. Instead, you’ll want to manage dependencies with pip (and later, requirements.txt/poetry/pipenv).&lt;/p&gt;

&lt;p&gt;Here’s the process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copy the main Lambda file (e.g., lambda_function.py) into &lt;code&gt;./src&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Inspect the start of the Lambda file (e.g., lambda_function.py). There you can distinguish which files are needed ans which are 3rd party libraries. Any non 3rd party library copy them upon &lt;code&gt;src&lt;/code&gt; folder of the clean repo.&lt;/li&gt;
&lt;li&gt; Using the name you can detect which ones are 3rd-party and which ones are required. It is a good idea to keep a list with 3rd party libraries as well.&lt;/li&gt;
&lt;li&gt;Copy only the application code (your .py files) into the clean repo.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;A common Library is the &lt;code&gt;boto&lt;/code&gt; one which is used for interfacing with AWS itself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once seperate the code init git and fo a first commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git init
git commit -m "Cleaned Code"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create a virtualenv
&lt;/h2&gt;

&lt;p&gt;We need to have a list with lambda dependencies for that we ned to initialize a virtual env:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python -m venv ./.venv
echo ".env" &amp;gt; .gitignore
git add .gitignore
git commit -m "Ignoring virtualenv"
source .venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then using &lt;code&gt;pip install&lt;/code&gt; we are installing the nesesary dependencies, for example for &lt;code&gt;boto&lt;/code&gt; we run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install boto3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once depencendies installed we need to keep them into a list for that we need to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip freeze &amp;gt; ./requirements.txt
git add requirements.txt
git commit -m "Added Dependencies"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now every time we need to install them we can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Detect environmental variables
&lt;/h2&gt;

&lt;p&gt;Lambas also retrieve settings externally from environmental variables. For pythonk lambdas scan for strings such as &lt;code&gt;os.environ.get(&lt;/code&gt;, the parameter passed contains the environemtnal variable required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy upon localstack
&lt;/h2&gt;

&lt;p&gt;Now that we have code sorted out we can create a lambda into localstack. For this we need to package the lambda as a new zip:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
## Package lambda

mkdir package
echo "package" &amp;gt;&amp;gt; .gitignore
git add .gitignore
git commit -m "Ignoring support folder for packaging"

# Copy code
cp -r ./src package/

# Install dependencies upon package folder
pip install -r requirements.txt -t package

#  Zip package
cd package
zip -r9 function.zip 
cd ../

# Package folder is temporary
rm -rf ./package 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The commands above do 2 things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a intermediate folder where code is staged, the folder is named &lt;code&gt;package&lt;/code&gt;. This folder and it should be ignored from git. &lt;/li&gt;
&lt;li&gt;Copy all lambda source upon &lt;code&gt;package&lt;/code&gt; folder. keep in mind we need to copy the &lt;em&gt;contents&lt;/em&gt; of src and not the &lt;code&gt;src&lt;/code&gt; itself.&lt;/li&gt;
&lt;li&gt;Install all dependencies at &lt;code&gt;package&lt;/code&gt; folder. This is achieved via providing the folder name upon &lt;code&gt;-t&lt;/code&gt; parameter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The method described above can also be used for packaging the lambda for production as well. The zip file can be uploaded, thus replacing the lambda code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy on locakstack
&lt;/h2&gt;

&lt;p&gt;For this we can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   aws --endpoint-url=http://localhost:4566 lambda create-function\
    --function-name "my-function" \
    --runtime "python3.9" \
    --role "arn:aws:iam::000000000000:role/lambda-role" \
    --handler "python3.9" \
    --zip-file "fileb://function.zip" \
    --environment Variables="{VAR1=\"Hello\"}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command above creates the function &lt;code&gt;my-function&lt;/code&gt; this is the lambda function we need to create. At the command above we need to pay attention upon some arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--endpoint-url&lt;/code&gt; In our case we need to provide it with the localstack setup. If not it will try to create the lambda upon actual aws. In out case this si not desirable&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--fucntion-name&lt;/code&gt; a distinctive function name. Each lambda should have its own&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--role&lt;/code&gt; Keeping the value &lt;code&gt;arn:aws:iam::000000000000:role/lambda-role&lt;/code&gt; is fine on every time tyou crreatr a new lambda. Localstack does not check for roles but we need to place this in order to avoid any unwanted behaviour.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--handler&lt;/code&gt;: Place the one that actual lambda upon aws uses. Here we define what would be used for lambda execution.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--zip-file&lt;/code&gt; The file we created containing code + dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--environment&lt;/code&gt; If no environmental variables used, ommit it. The value is a string encloded in &lt;code&gt;{}&lt;/code&gt; having this format (do not confuse it with json):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    {VARIABLE_NAME=VALUE,VARIABLE_NAME2=VALUE2}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Develop and redeploy
&lt;/h2&gt;

&lt;p&gt;During development if a changes is needed you need to re-package the lambda. Re-creating is not needed unless localstack container is terminated. &lt;/p&gt;

&lt;p&gt;Updating the code is done 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;aws --endpoint-url=http://localhost:4566 lambda update-function-code --function-name "my-function" --zip-file "fileb://function.zip"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whilst if environmental variables need to change you can do it 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;aws --endpoint-url=$ENDPOINT lambda update-function-configuration \
    --function-name "my-function" \
    --environment Variables="{VARIABLE_NAME=VALUE,VARIABLE_NAME2=VALUE2}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Misc tips
&lt;/h2&gt;

&lt;p&gt;If an extra dependency is needed is it a good idea to enable the generated virtual environment, then install it via pip. Then update the code upon localstack as mentioned above.&lt;/p&gt;

</description>
      <category>howto</category>
      <category>aws</category>
      <category>lambda</category>
    </item>
    <item>
      <title>Create a Pull request into another repository using github actions.</title>
      <dc:creator>Dimitrios Desyllas</dc:creator>
      <pubDate>Fri, 05 Sep 2025 21:40:38 +0000</pubDate>
      <link>https://forem.com/pcmagas/create-a-pull-request-into-another-repository-using-github-actions-e04</link>
      <guid>https://forem.com/pcmagas/create-a-pull-request-into-another-repository-using-github-actions-e04</guid>
      <description>&lt;p&gt;Upon developing the &lt;a href="https://github.com/pc-magas/mkdotenv" rel="noopener noreferrer"&gt;mkdotenv&lt;/a&gt; project I hgad this partucilar problem. I needed to release upon mac as well and for that I need a repo that hosts the homebrew &lt;a href="https://github.com/pc-magas/homebrew-mkdotenv" rel="noopener noreferrer"&gt;tap&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The procedure I developed is the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upon mkdotenv actions create the homebrew tap&lt;/li&gt;
&lt;li&gt;Clone homebrew repo&lt;/li&gt;
&lt;li&gt;Create a branch and copy the file into &lt;code&gt;Formula&lt;/code&gt; folder&lt;/li&gt;
&lt;li&gt;Test that app is installed&lt;/li&gt;
&lt;li&gt;push the branch&lt;/li&gt;
&lt;li&gt;Create the PR&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The last steps was the one that caused me pain therefore I would explain what I did to solve it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Required apps and settings I needed to install
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step1 Install Qoomon Access Tokens for GitHub Actions
&lt;/h3&gt;

&lt;p&gt;I used the &lt;a href="https://github.com/qoomon/actions--access-token" rel="noopener noreferrer"&gt;qoomon/actions--access-token&lt;/a&gt; project, that provided me a GitHub App that can issue temporary tokens during a workflow run. These tokens are powerful because they can grant fine-grained permissions such as pushing branches or opening PRs across repositories — something the default GITHUB_TOKEN cannot always do. Also it is a better alternative than storing PAT upon secrets as well.&lt;/p&gt;

&lt;p&gt;In my case I installed it from &lt;a href="https://github.com/marketplace/access-manager-for-github-actions" rel="noopener noreferrer"&gt;Marketplace&lt;/a&gt;. Setup is free, but since it’s an app install, but I needed to go through the standard GitHub "purchase" flow (at $0), that required meto provide some basic private info (name and address mostly).&lt;/p&gt;

&lt;p&gt;Once the app is installed, I had to define token policies using YAML files. There are two levels of configuration:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Global policies (.github-access-token repo)&lt;/strong&gt;&lt;br&gt;
You create a dedicated repository named .github-access-token.&lt;br&gt;
Inside it, you add an access-token.yaml file that defines the general rules: which repositories can request tokens, and what operations are allowed.&lt;br&gt;
Think of this as your organization-wide or user-wide "master policy".&lt;br&gt;
👉 Example: my &lt;a href="https://github.com/pc-magas/.github-access-token/blob/master/access-token.yaml" rel="noopener noreferrer"&gt;.github-access-token repo&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Local policies (.github/access-token.yaml in a repo)&lt;br&gt;
Inside each target repo (the one you want to push to or create a PR against), you also create a file at .github/access-token.yaml.&lt;br&gt;
This file must match the owner of the global repo above and acts as a per-repository confirmation.&lt;br&gt;
It narrows down the rules from the global file to the specific repository, making sure you explicitly allow those actions in that repo.   &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In my case I have 3 repos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;pc-magas/.github-access-token&lt;/code&gt; in which I have the general policies of allowed action upon &lt;code&gt;access-token.yaml&lt;/code&gt;  in it&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pc-magas/homebrew-mkdotenv&lt;/code&gt; The homebrew tap in which pr's would be autogenerated&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pc-magas/mkdotenv&lt;/code&gt; in which:

&lt;ol&gt;
&lt;li&gt;Formula file is created&lt;/li&gt;
&lt;li&gt;Github action create and push a branch upon &lt;code&gt;pc-magas/homebrew-mkdotenv&lt;/code&gt; with the new formula&lt;/li&gt;
&lt;li&gt;A pr is created&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;As you notice all of them are owned by &lt;code&gt;pc-magas&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The general flow goes as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+---------------------------+                  +-----------------------------+
|   pc-magas/mkdotenv       |                  |  pc-magas/homebrew-mkdotenv |
|  (creates formula)        |                  |  (receives PRs)             |
|                           |                  |                             |
|  GitHub Action runs ---&amp;gt;  |  ----push----&amp;gt;   |   Branch created            |
|                           |                  |   PR opened                 |
+---------------------------+                  +-----------------------------+
             |                                               ^
             |                                               |
             v                                               |
   +---------------------------+                             |
   | .github-access-token repo |                             |
   | (global policy)           |                             |
   |  access-token.yaml        |                             |
   +---------------------------+                             |
             |                                               |
             |  defines who can request tokens               |
             v                                               |
   +---------------------------+                             |
   | target repo config        |                             |
   | .github/access-token.yaml |-----------------------------+
   | (local policy)            |
   +---------------------------+
             |
             v
   Tokens issued at workflow runtime
   with correct permissions

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2 configure generic policy upon &lt;code&gt;.github-access-token&lt;/code&gt; repo.
&lt;/h3&gt;

&lt;p&gt;As described above you need to create a repo named &lt;code&gt;.github-access-token&lt;/code&gt;, on it I needed to create a file named &lt;code&gt;access-token.yaml&lt;/code&gt;. &lt;br&gt;
In my case these are the settings I needed to place upon:&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;origin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pc-magas/.github-access-token&lt;/span&gt;


&lt;span class="na"&gt;allowed-repository-permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt; &lt;span class="c1"&gt;# read or write&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt; &lt;span class="c1"&gt;# read or write&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt; &lt;span class="c1"&gt;# read or write&lt;/span&gt;

&lt;span class="c1"&gt;# Grant owner scoped permissions (owner permission or owner wide repository permissions)&lt;/span&gt;
&lt;span class="c1"&gt;# NOTE: Every statement will always implicitly grant `metadata: read` permission.&lt;/span&gt;
&lt;span class="na"&gt;statements&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;subjects&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;repo:${origin}:ref:refs/heads/dev&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;repo:${origin}:workflow_ref:${origin}/.github/workflows/release.yml@refs/heads/dev&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  1. origin
&lt;/h4&gt;

&lt;p&gt;The origin field tells the app which .github-access-token repo defines the global policy.&lt;br&gt;
It always follows the format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OWNER/.github-access-token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;OWNER&lt;/code&gt; = your GitHub username or organization name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.github-access-token&lt;/code&gt; = the special repository that stores the global rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For my personal account (pc-magas), the repo is named &lt;code&gt;pc-magas/.github-access-token&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the owner was an organization named ellakcy, then it would be &lt;code&gt;ellakcy/.github-access-token&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This matters because when a workflow requests a token, the app checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which global policy repo (origin) it should look at&lt;/li&gt;
&lt;li&gt;Whether that policy allows issuing the token for the requested action&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. &lt;code&gt;allowed-repository-permissions&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;This section sets the maximum permissions a token can have when issued.&lt;br&gt;
Think of it as the "permission budget".&lt;br&gt;
For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;actions: write&lt;/code&gt; → allows running workflows&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;contents: write&lt;/code&gt; → allows pushing/pulling commits&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pull-requests: write&lt;/code&gt; → allows creating or updating PRs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is an full &lt;a href="https://github.com/qoomon/actions--access-token/blob/main/action/docs/access-token.owner-template.yaml" rel="noopener noreferrer"&gt;template&lt;/a&gt; that can be used upon for reference.&lt;/p&gt;
&lt;h4&gt;
  
  
  3. &lt;code&gt;statements&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;This section defines who is allowed to request a token and what extra permissions they get.&lt;br&gt;
It works like an access control rule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;subjects&lt;/code&gt;: → specifies which workflows or branches can ask for tokens&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;permissions&lt;/code&gt;: → specifies what those subjects are allowed to do&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example from above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;statements:
  - subjects:
      - repo:${origin}:ref:refs/heads/dev
      - repo:${origin}:workflow_ref:${origin}/.github/workflows/release.yml@refs/heads/dev
    permissions:
      pull-requests: write
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only workflows running from the dev branch of the .github-access-token repo can request a token.&lt;/li&gt;
&lt;li&gt;Those workflows are granted pull-requests: write permission (so they can open or update PRs).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to allow multiple repositories you need to add multiple sections and what permissions are allowed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 Define a local policy on repo you want to perform PR
&lt;/h3&gt;

&lt;p&gt;The local policy lives inside the target repository — the repo where you want to push code or create a pull request.&lt;br&gt;
This policy acts as an explicit opt-in: it tells GitHub, "yes, I allow workflows from these repos/branches to perform actions here."&lt;/p&gt;

&lt;p&gt;For my case, this file lives in &lt;code&gt;pc-magas/homebrew-mkdotenv&lt;/code&gt; repo upon&lt;code&gt;.github/access-token.yaml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;origin: pc-magas/homebrew-mkdotenv
statements:
  - subjects:
      - repo:pc-magas/mkdotenv:** # all refs, workflows, environments
    permissions:
      contents: write
      pull-requests: write
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing you notice is that this file is a more slimmed-down version of the global policy. Only origin and statements are present here. As before, the origin field simply points to the repository where this local policy file lives. Then, under the statements section, you describe which repositories are allowed to interact with this one and what they are allowed to do.&lt;/p&gt;

&lt;p&gt;You can add one or more entries under statements. Each entry can target a different repository or workflow and specify the actions it may perform. The actual actions are defined in the permissions section.&lt;/p&gt;

&lt;p&gt;In my case, I allow anything from pc-magas/mkdotenv — whether it’s a branch, a workflow, or an environment — to push code and open pull requests into &lt;code&gt;pc-magas/homebrew-mkdotenv&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implement Github action
&lt;/h2&gt;

&lt;p&gt;A minimal example of my full &lt;a href="https://raw.githubusercontent.com/pc-magas/mkdotenv/refs/heads/master/.github/workflows/release.yml" rel="noopener noreferrer"&gt;worflow&lt;/a&gt; is shown below. &lt;br&gt;
Upon myrepo the pipeline has multiple jobs, but the one that matters for creating the pull request is &lt;code&gt;test_homebrew&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
test_homebrew:
  runs-on: macos-latest
  permissions:
    contents: write
    id-token: write
  needs:
    - release
    - build_mac
  steps:

    - uses: actions/checkout@v4
      with:
        fetch-depth: 0

    - name: Download homebrew formula for macos
      uses: actions/download-artifact@v4
      with:
        name: mkdotenv-macos-homebrew-formula
        path: ./macos/bin

    - name: Generate GitHub App token
      id: token
      uses: qoomon/actions--access-token@v3
      with:
        repository: pc-magas/homebrew-mkdotenv
        permissions: |
          contents: write
          pull_requests: write

    - name: setup git and clone brew formula
      env:
        GH_PAT: ${{ steps.token.outputs.token }}
      run: |
        git config --global user.name "github-actions"
        git config --global user.email "actions@github.com"

        git clone https://x-access-token:${GH_PAT}@github.com/pc-magas/homebrew-mkdotenv.git
        cd homebrew-mkdotenv

        git checkout -b test-update-formula-${{ github.run_number }}

    - name: setup formula
      run: |
        cd homebrew-mkdotenv
        mkdir -p ./Formula
        cp ../macos/bin/mkdotenv.rb ./Formula/mkdotenv.rb

    - name: Create Pull Request to homebrew repo
      env:
        GH_PAT: ${{ steps.token.outputs.token }}
      run: |
        cd homebrew-mkdotenv

        BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
        git add ./Formula/mkdotenv.rb
        git commit -m "Update formula via GitHub Actions"
        git push origin ${BRANCH_NAME}

        VERSION=$(grep -E '^  version ' ./Formula/mkdotenv.rb | sed 's/.*"\(.*\)".*/\1/')

        curl --fail-with-body -vvv -X POST https://api.github.com/repos/pc-magas/homebrew-mkdotenv/pulls \
          -H "Authorization: Bearer $GH_PAT" \
          -H "Accept: application/vnd.github+json" \
          -H "Content-Type: application/json" \
          -H "X-GitHub-Api-Version: 2022-11-28" \
          -d "{\"title\": \"Update formula [VERSION $VERSION]\",\"head\": \"$BRANCH_NAME\",\"base\": \"master\",\"body\": \"Automated update\"}"


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

&lt;/div&gt;



&lt;p&gt;The flow follows a simple philosophy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone the target repo&lt;/li&gt;
&lt;li&gt;Create a new branch
3.Copy or modify the necessary files
4.Commit and push the changes
5.Open a pull request&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key part is how authentication works. The GitHub App token is generated here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      - name: Generate GitHub App token
        id: token
        uses: qoomon/actions--access-token@v3
        with:
          repository: pc-magas/homebrew-mkdotenv
          permissions: |
            contents: write
            pull_requests: write
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses the &lt;code&gt;qoomon/actions--access-token&lt;/code&gt; action to issue a temporary token with just the right permissions. The token is then exposed as &lt;code&gt;teps.token.outputs.token&lt;/code&gt; and passed into later steps through an environment variable called &lt;code&gt;GH_PAT&lt;/code&gt; 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; - name: setup git and clone brew formula
        env:
          GH_PAT: ${{ steps.token.outputs.token }}
        run: |
          # These are needed in order to config which does the push and PR
          git config --global user.name "github-actions"
          git config --global user.email "actions@github.com"

          git clone https://x-access-token:${GH_PAT}@github.com/pc-magas/homebrew-mkdotenv.git
          cd homebrew-mkdotenv

          # Create new branch for PR
          git checkout -b test-update-formula-${{ github.run_number }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When cloning the repo, authentication is set up by injecting that token into the HTTPS URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://x-access-token:${GH_PAT}@github.com/pc-magas/homebrew-mkdotenv.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the x-access-token:${GH_PAT} part inside the repository URL. This is what enables Git to authenticate in a non-interactive way during the workflow, so the branch can be created and pushed automatically.&lt;/p&gt;

&lt;p&gt;The PR itself is done using the &lt;a href="https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#create-a-pull-request" rel="noopener noreferrer"&gt;Github rest api&lt;/a&gt;, we use the very same key we used upon cloning. &lt;/p&gt;

&lt;p&gt;For api consumption we need to use &lt;code&gt;curl&lt;/code&gt;, the call is performed 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;          curl --fail-with-body -X POST https://api.github.com/repos/pc-magas/homebrew-mkdotenv/pulls \
            -H "Authorization: Bearer $GH_PAT" \
            -H "Accept: application/vnd.github+json" \
            -H "Content-Type: application/json" \
            -H "X-GitHub-Api-Version: 2022-11-28" \
            -d "{\"title\": \"Update formula [VERSION $VERSION]\",\"head\": \"$BRANCH_NAME\",\"base\": \"master\",\"body\": \"Automated update\"}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generated key is provided as bearer token. Also when using &lt;code&gt;curl&lt;/code&gt; upon github actions it is nice to aplo place the &lt;code&gt;--fail-with-body&lt;/code&gt; argument, that allows if rest api returns an error http status code (such as 4XX or 5XX) the whole step fails, that allows you to have a better view whether PR was created or not.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>githubactions</category>
      <category>git</category>
    </item>
    <item>
      <title>Dev Experience: `doctrine:schema:update` still outputs sql, despite changes applied upon db</title>
      <dc:creator>Dimitrios Desyllas</dc:creator>
      <pubDate>Tue, 02 Sep 2025 16:51:25 +0000</pubDate>
      <link>https://forem.com/pcmagas/dev-experience-doctrineschemaupdate-still-outputs-sql-despite-changes-applied-upon-db-3log</link>
      <guid>https://forem.com/pcmagas/dev-experience-doctrineschemaupdate-still-outputs-sql-despite-changes-applied-upon-db-3log</guid>
      <description>&lt;h1&gt;
  
  
  The problem
&lt;/h1&gt;

&lt;p&gt;Today I was deploying an app, team uses diffs instead of migration.&lt;/p&gt;

&lt;p&gt;Therefore, I saw what changes upon db needs to be applied via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ php bin/console doctrine:schema:update --dump-sql 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That outputed me ~93 queries (well lots of changes needed to be applied upon db):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALTER TABLE xxx1 CHANGE expires\_at expires\_at DATETIME DEFAULT NULL, CHANGE created\_at created\_at DATETIME DEFAULT NULL, CHANGE updated\_at updated\_at DATETIME DEFAULT NULL;

ALTER TABLE xx2 CHANGE name name VARCHAR(255) DEFAULT NULL, CHANGE created\_at created\_at DATETIME DEFAULT NULL, CHANGE updated\_at updated\_at DATETIME DEFAULT NULL, CHANGE unique\_identifier unique\_identifier VARCHAR(255) DEFAULT NULL;

ALTER TABLE xx3 CHANGE description description VARCHAR(255) DEFAULT NULL, CHANGE created\_at created\_at DATETIME DEFAULT NULL, CHANGE updated\_at updated\_at DATETIME DEFAULT NULL, CHANGE deleted\_at deleted\_at DATETIME DEFAULT NULL, CHANGE unique\_identifier unique\_identifier VARCHAR(255) DEFAULT NULL;

.....
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I tried to apply them via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ php bin/console doctrine:schema:update --force
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And I re-checked for changes via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ php bin/console doctrine:schema:update --dump-sql 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And still outputed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALTER TABLE xxx1 CHANGE expires\_at expires\_at DATETIME DEFAULT NULL, CHANGE created\_at created\_at DATETIME DEFAULT NULL, CHANGE updated\_at updated\_at DATETIME DEFAULT NULL;

ALTER TABLE xx2 CHANGE name name VARCHAR(255) DEFAULT NULL, CHANGE created\_at created\_at DATETIME DEFAULT NULL, CHANGE updated\_at updated\_at DATETIME DEFAULT NULL, CHANGE unique\_identifier unique\_identifier VARCHAR(255) DEFAULT NULL;

ALTER TABLE xx3 CHANGE description description VARCHAR(255) DEFAULT NULL, CHANGE created\_at created\_at DATETIME DEFAULT NULL, CHANGE updated\_at updated\_at DATETIME DEFAULT NULL, CHANGE deleted\_at deleted\_at DATETIME DEFAULT NULL, CHANGE unique\_identifier unique\_identifier VARCHAR(255) DEFAULT NULL;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As not notice same sql is outputed despite being applied.&lt;/p&gt;

&lt;h1&gt;
  
  
  The solution
&lt;/h1&gt;

&lt;p&gt;Well, I asked for help from a coleague of mine. He tried to make a migration 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;php bin/console doctrine:migrations:diff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But that returned the error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The metadata storage is not up to date, please run the sync-metadata-storage command to fix this issue.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rationale behind this is because both &lt;code&gt;doctrine:migrations:diff&lt;/code&gt; and &lt;code&gt;doctrine:schema:update&lt;/code&gt; use same logic for diffs. Migration generation though also exposes any error as well.&lt;/p&gt;

&lt;p&gt;The reason why i got both upon migration generation an error and why also &lt;code&gt;schema:update&lt;/code&gt; outputes same sql was, a &lt;code&gt;serverVersion&lt;/code&gt; option upon .env:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE_URL=mysql://xxx:yyy@127.0.0.1:3306/testtest?serverVersion=10.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use mariadb for db and as you notice above &lt;code&gt;serverVersion&lt;/code&gt; contains the mariadb version. The soplution is either get the correct version (incl minor one) from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And set the &lt;code&gt;serverVersion&lt;/code&gt; into &lt;code&gt;mariadb-10.4.1&lt;/code&gt; (yours may differ). The value is comming from the mariadb version shown upon the command above prefixed with &lt;code&gt;mariadb&lt;/code&gt; to indicate that it is mariadb instead of mysql.&lt;/p&gt;

&lt;p&gt;The option we chose though, was to ditch completely the &lt;code&gt;serverVersion&lt;/code&gt; argument upon &lt;code&gt;DATABASE_URL&lt;/code&gt;, that fixed the issue as well.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>php</category>
      <category>symfony</category>
    </item>
    <item>
      <title>Run background jobs (eg. queue listener) on an environment that does not allow root access.</title>
      <dc:creator>Dimitrios Desyllas</dc:creator>
      <pubDate>Thu, 03 Jul 2025 16:33:47 +0000</pubDate>
      <link>https://forem.com/pcmagas/no-supervisor-no-problem-36p4</link>
      <guid>https://forem.com/pcmagas/no-supervisor-no-problem-36p4</guid>
      <description>&lt;p&gt;Recently, in my work, I came across a peculiar problem. I needed to run reliably a queue listener. My go-to solution in this problem is to set up supervisor, but in order to do that requires root/sudo access and I did not have this privilege.&lt;/p&gt;

&lt;p&gt;The server does ship with a Linux distro but running apt-get, or any other package manager, does require &lt;code&gt;sudo&lt;/code&gt; or &lt;code&gt;su&lt;/code&gt; in order to get root access. In my case I was unable to do that.&lt;/p&gt;

&lt;p&gt;Well, supervisor is not the only option for utilizing a process manager. There's another option that also comes preinstalled on every linux distro, it is called systemd and many services use that.&lt;/p&gt;

&lt;p&gt;Each user can run its own systemd services as non root-user.&lt;br&gt;
First and foremost, you need to create the &lt;code&gt;~/.config/systemd/user/&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p ~/.config/systemd/user/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we need to place a file upon &lt;code&gt;~/.config/systemd/user/&lt;/code&gt;, for example in my case it was a symfony queueu listener, therefore I run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
nano ~/.config/systemd/user/queue_runner.service

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

&lt;/div&gt;



&lt;p&gt;And placed the following contents&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=Symfony Queue message Listener

StartLimitIntervalSec=20s
StartLimitBurst=5

[Service]
Type=simple

WorkingDirectory=/home/qpassstage/public_html_test
ExecStart=/usr/bin/php -d memory_limit=-1 bin/console messenger:consume async -vv

Restart=always
RestartSec=1
TimeoutSec=300

[Install]
WantedBy=default.target

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

&lt;/div&gt;



&lt;p&gt;It is important the filename to end with &lt;code&gt;.service&lt;/code&gt; and exist upon &lt;code&gt;~/.config/systemd/user/&lt;/code&gt; instead of &lt;code&gt;/etc/systemd/system/&lt;/code&gt; where system-wide services live upon. &lt;/p&gt;

&lt;p&gt;Also, it is important upon &lt;code&gt;[Install]&lt;/code&gt; section of the file to contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WantedBy=default.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usually upon authoring service file upon &lt;code&gt;Install&lt;/code&gt; section contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WantedBy=multi.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The directive &lt;code&gt;default.target&lt;/code&gt; allows you to run the service as the default user instead of root user.&lt;/p&gt;

&lt;p&gt;Furthermore upon the service file above the command we need to launch as a service is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; /usr/bin/php -d memory_limit=-1 bin/console messenger:consume async -vv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And is defined upon &lt;code&gt;ExecStart&lt;/code&gt; whereas upon &lt;code&gt;WorkingDirectory&lt;/code&gt; we define the location where command that will run as a service is located upon.&lt;/p&gt;

&lt;p&gt;The section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Restart=always
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensures that once command unexpecteddly stops working then systemd would execute it once more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Launcing Service
&lt;/h2&gt;

&lt;p&gt;Once placed, you need to ensure that systemd has recognized the service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl --user daemon-reload  

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

&lt;/div&gt;



&lt;p&gt;Then launch the service. In our case we run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl --user start queue_runner.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then ensure it run upon rebbot via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl --user enable queue_runner.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use these commands for logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl --user status queue_runner.service
journalctl --user -u queue_runner.service -f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In case your user is not upon &lt;code&gt;journal&lt;/code&gt; group use file instead by placing these directives upon service file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=Symfony Queue message Listener

StartLimitIntervalSec=20s
StartLimitBurst=5

[Service]
Type=simple

WorkingDirectory=/home/qpassstage/public_html_test
ExecStart=/usr/bin/php -d memory_limit=-1 bin/console messenger:consume async -vv

Restart=always
RestartSec=1
TimeoutSec=300

StandardOutput=append:/home/myapp/public_html/var/log/messenger.log
StandardError=append:/home/myapp/public_html/var/log/messenger.log

[Install]
WantedBy=default.target

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

&lt;/div&gt;



&lt;p&gt;And run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl --user daemon-reload
systemctl --user start queue_runner.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you notice, we used the file &lt;code&gt;/home/qpassstage/public_html/var/log/messenger.log&lt;/code&gt; to store the output of the command the directive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;StandardOutput
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Saves the output of stdout in the file, whilst the:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;StandardError
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Saves the output of stderr upon the file. In my case the directory &lt;code&gt;/home/myapp/public_html/var/log&lt;/code&gt; already existed, therefore I did not make it.&lt;/p&gt;

&lt;p&gt;If the folder does not exist, using &lt;code&gt;mkdir -p&lt;/code&gt; you can make it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p /home/myapp/public_html/var/log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Replace &lt;code&gt;/home/myapp/public_html/var/log&lt;/code&gt; with your own path, then update service file accordingly.)&lt;/p&gt;

</description>
      <category>howto</category>
      <category>linux</category>
    </item>
    <item>
      <title>Hey you! Deploying the application can you hear me?</title>
      <dc:creator>Dimitrios Desyllas</dc:creator>
      <pubDate>Wed, 02 Jul 2025 19:32:13 +0000</pubDate>
      <link>https://forem.com/pcmagas/hey-you-deploying-the-application-can-you-hear-me-57pk</link>
      <guid>https://forem.com/pcmagas/hey-you-deploying-the-application-can-you-hear-me-57pk</guid>
      <description>&lt;p&gt;Hey you! Setting secrets upon &lt;code&gt;.env&lt;/code&gt; file via a CI/CD pipeline, can you hear me?&lt;/p&gt;

&lt;p&gt;Recently I am making a small utility tool named mkdotenv. Its goal simple: manipulate values upon .env files in a CI/CD pipeline. It is designed to run inside a pipeline during deployment and modify and set values upon &lt;code&gt;.env&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;It is shipped in #fedora, #ubuntu, #linux, #windows and #mac. &lt;/p&gt;

&lt;p&gt;Look here: &lt;a href="https://github.com/pc-magas/mkdotenv" rel="noopener noreferrer"&gt;https://github.com/pc-magas/mkdotenv&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Available on Fedora #corpr, Ubuntu/Mint #ppa and #homebrew (for M-Series mac). Also, building from source is easy-peasy-lemon-sqeezy it just needs #go and #make and no other external dependencies.&lt;/p&gt;

&lt;p&gt;Please have a strong look as I develop it into a stable version.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>go</category>
      <category>ppa</category>
    </item>
    <item>
      <title>How to setup a dev db for symfony development where migration scripts are not used.</title>
      <dc:creator>Dimitrios Desyllas</dc:creator>
      <pubDate>Wed, 28 May 2025 20:17:22 +0000</pubDate>
      <link>https://forem.com/pcmagas/how-to-setup-a-dev-db-for-symfony-development-where-migration-scripts-are-not-used-2ag5</link>
      <guid>https://forem.com/pcmagas/how-to-setup-a-dev-db-for-symfony-development-where-migration-scripts-are-not-used-2ag5</guid>
      <description>&lt;p&gt;In my work, I develop a symfony application. As usual, migration scripts are abandoned and I have no easy way of setting up a development mysql database in my machine for local development.&lt;/p&gt;

&lt;p&gt;But I found an easy solution to setup the db shema. &lt;/p&gt;

&lt;h2&gt;
  
  
  STEP 1 Import a db dump - initialise database
&lt;/h2&gt;

&lt;p&gt;At the first step, you need to obtain a dump of a development db and import it using mysql. This needs to run every time you create a fresh db instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql -h 127.0.0.1 -u dbusr -pXXXX somedb &amp;lt; dump.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each time you drop and recreate the db, import the dump it is a good idea to keep it upon your hard disk.&lt;/p&gt;

&lt;h2&gt;
  
  
  STEP 2 Update schema
&lt;/h2&gt;

&lt;p&gt;Then I use symfony's &lt;code&gt;shema:update&lt;/code&gt; and I post-process it (it can generate some unwanted sql):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php bin/console doctrine:schema:update --dump-sql | \
awk '/^ALTER TABLE/ {
    gsub(/,$/, "", $0);
    table=$3;
    sub(/^ALTER TABLE [^ ]+ /, "", $0);
    n=split($0, parts, /, */);
    for (i=1; i&amp;lt;=n; i++) {
        print "ALTER TABLE " table " " parts[i] ";"
    }
    next
}
{ print }
' | \
tee /dev/tty | mysql -h 127.0.0.1 -u dbusr -pXXXX somedb 

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

&lt;/div&gt;



&lt;p&gt;Let me explain this monstrocity I typed above a bit:&lt;/p&gt;

&lt;h3&gt;
  
  
  1 Generate schema update sql
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php bin/console doctrine:schema:update --dump-sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this command I get the SQL from &lt;code&gt;doctrine:schema:update&lt;/code&gt; using the parameter &lt;code&gt;--dump-sql&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2 Postprocess sql using awk
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;awk '/^ALTER TABLE/ {
    gsub(/,$/, "", $0);
    table=$3;
    sub(/^ALTER TABLE [^ ]+ /, "", $0);
    n=split($0, parts, /, */);
    for (i=1; i&amp;lt;=n; i++) {
        print "ALTER TABLE " table " " parts[i] ";"
    }
    next
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using awk I split any &lt;code&gt;ALTER TABLE&lt;/code&gt; sql statement into smaller ones. I use awk because if an &lt;code&gt;ALTER TABLE&lt;/code&gt; statement alters multiple colums it may fail. &lt;/p&gt;

&lt;p&gt;I wanted each &lt;code&gt;ALTER TABLE&lt;/code&gt; statement to add, alter or drop only one column at a time, increasing changes of the updates to successfully run upon db.&lt;/p&gt;

&lt;p&gt;That allows me to fix any issues at my own time.&lt;/p&gt;

&lt;h3&gt;
  
  
  3 Print upon console
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tee /dev/tty 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, I wanted to show what sql statements run upon db whilst I also pass it upon mysql command:&lt;/p&gt;

&lt;h3&gt;
  
  
  4 run sql statements
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql --force -h 127.0.0.1 -u dbusr -pXXXX somedb 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, using mysql I run the statements that are generated upon db. I use &lt;code&gt;--force&lt;/code&gt; option because if ommited and an sql statement fails other will not run upon db. &lt;/p&gt;

&lt;p&gt;What I wanted was to run any sql statement that updated the db schema.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;p&gt;This method is subpar to the use of db migration scripts. But many cases where for various reasons db migrations are not maintained properly (lack of time or knowledge) this is the next best thing.&lt;/p&gt;

&lt;p&gt;If upon your team db migrations used properly this method should be avoided and use the migration scripts to setup the db.&lt;/p&gt;

&lt;p&gt;Also this method forces any sql statement to run upon db without some sort of controll or test. Some of them can be dangerous do irreversible damage to db schema. Furthermor a db setup or migrations also need need data migration as well that this method does not provide. &lt;/p&gt;

&lt;p&gt;This approach is recommended for a &lt;strong&gt;local db setup&lt;/strong&gt; during development and should be &lt;strong&gt;avoided&lt;/strong&gt; for app deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The good things about this method
&lt;/h2&gt;

&lt;p&gt;This method though offers fixed steps to setup and update a development database at any given moment. Personally, I made 2 bash scripts:&lt;/p&gt;

&lt;p&gt;One that nukes and creates a fresh db from a db dump (as mentioned upon step 1):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/usr/bin/env bash

mysql -h 127.0.0.1 -u dbusr -pXXXX -e "DROP DATABASE app_db"
mysql -h 127.0.0.1 -u dbusr -pXXXX somedb -e "CREATE DATABASE app_db"

# Init
mysql -h 127.0.0.1 -u dbusr -pXXXX somedb &amp;lt; dump.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And one that updates the schema (as mentioned upon step 2)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/usr/bin/env bash

php bin/console doctrine:schema:update --dump-sql | \
awk '/^ALTER TABLE/ {
    gsub(/,$/, "", $0);
    table=$3;
    sub(/^ALTER TABLE [^ ]+ /, "", $0);
    n=split($0, parts, /, */);
    for (i=1; i&amp;lt;=n; i++) {
        print "ALTER TABLE " table " " parts[i] ";"
    }
    next
}
{ print }
' | \
tee /dev/tty | mysql -h 127.0.0.1 -u dbusr -pXXXX somedb 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These can be adjusted for example if php app runs through a docker container named &lt;code&gt;php&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/usr/bin/env bash

docker exec -u www-data php php bin/console doctrine:schema:update --dump-sql  | \
awk '/^ALTER TABLE/ {
    gsub(/,$/, "", $0);
    table=$3;
    sub(/^ALTER TABLE [^ ]+ /, "", $0);
    n=split($0, parts, /, */);
    for (i=1; i&amp;lt;=n; i++) {
        print "ALTER TABLE " table " " parts[i] ";"
    }
    next
}
{ print }
' | \
tee /dev/tty | mysql -h 127.0.0.1 -u dbusr -pXXXX somedb 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope this to be found usefull.&lt;/p&gt;

</description>
      <category>howto</category>
      <category>productivity</category>
      <category>symfony</category>
    </item>
    <item>
      <title>Mkdotenv: the tool that makes .env manipulation a breeze</title>
      <dc:creator>Dimitrios Desyllas</dc:creator>
      <pubDate>Mon, 07 Apr 2025 19:55:33 +0000</pubDate>
      <link>https://forem.com/pcmagas/mkdotenv-the-tool-that-makes-env-manipulation-a-breeze-16m8</link>
      <guid>https://forem.com/pcmagas/mkdotenv-the-tool-that-makes-env-manipulation-a-breeze-16m8</guid>
      <description>&lt;p&gt;Hello hello hello,&lt;br&gt;
Recently, I got my hands dirty with go and made a simple tool for manipulating .env files:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pc-magas/mkdotenv" rel="noopener noreferrer"&gt;https://github.com/pc-magas/mkdotenv&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Currently, I release for linux (x86_64 architectures) with debian and rpm packages. I also attempted to release for alpine but somehow got stuck in aports.&lt;/p&gt;

&lt;p&gt;Also, it is available through ppa: &lt;a href="https://launchpad.net/%7Epcmagas/+archive/ubuntu/mkdotenv" rel="noopener noreferrer"&gt;https://launchpad.net/~pcmagas/+archive/ubuntu/mkdotenv&lt;/a&gt; and includes a full manpage as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;man mkdotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feel free to download and place any issue in: &lt;a href="https://github.com/pc-magas/mkdotenv/issues" rel="noopener noreferrer"&gt;https://github.com/pc-magas/mkdotenv/issues&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I made this because I thought a tool that is able to run in a CI/CD pipeline and manipulates &lt;code&gt;.env&lt;/code&gt; file before releasing your app into production (or staging) maybe a good idea.&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>External Versioning in GCC: Defining Project Versions Without Modifying Source Code</title>
      <dc:creator>Dimitrios Desyllas</dc:creator>
      <pubDate>Sat, 08 Mar 2025 15:45:35 +0000</pubDate>
      <link>https://forem.com/pcmagas/quicktip-how-to-define-version-your-project-written-in-c-4o8c</link>
      <guid>https://forem.com/pcmagas/quicktip-how-to-define-version-your-project-written-in-c-4o8c</guid>
      <description>&lt;p&gt;I was experimenting with gcc linker and how I could define the version of my project externally. The idea is to have a version bump procedure, but without needing to modify source code for just a version.&lt;/p&gt;

&lt;p&gt;So assuming we have this file named &lt;code&gt;test.c&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#ifndef VERSION
#define VERSION "default"
#endif

int main(){
    printf(VERSION);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a piece of code that needs to output its version Instead of relying in a constant, we define the version with a placeholder.&lt;/p&gt;

&lt;p&gt;The #define is a way to define macros, pieces of code that the preprocessor of the compiler will take and replace the values inside out actual code.&lt;/p&gt;

&lt;p&gt;In our case, the preprocessor will replace the constant version with string &lt;code&gt;"default"&lt;/code&gt;. So once compiled, the piece of software above will just print &lt;code&gt;default&lt;/code&gt; if compiled 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;gcc test.c
chmod +x ./a.out
./a.out
default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But as no noticed we did not just place a simple &lt;code&gt;#define&lt;/code&gt; but instead we used &lt;code&gt;#ifndef ... #endif&lt;/code&gt;. With that we tell the preprocessor to define the &lt;code&gt;VERSION&lt;/code&gt; if not defined.&lt;/p&gt;

&lt;p&gt;But is there a way to define it externally? YES babe YES we use the &lt;code&gt;-D&lt;/code&gt; argument to define the desired version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcc -DVERSION="\"0.9.0\"" test.c
chmod +x ./a.out
./a.out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Will output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0.9.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the &lt;code&gt;gcc&lt;/code&gt;'s &lt;code&gt;-D&lt;/code&gt; parameter we defined the constant &lt;code&gt;VERSION&lt;/code&gt; externally resulting for the VERSION to be defined as &lt;code&gt;0.9.0&lt;/code&gt; and not as &lt;code&gt;default&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Therefore, we can use a file in which contains the version. Usually I name it VERSION. In our case it will contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0.9.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I use a Makefile to build it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VERSION := $(shell cat VERSION)
CC := go

.PHONY: all compile

# Default target
all: compile

# Compile Go binary
compile:
    gcc -DVERSION="\"$(VERSION)\"" test.c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So in order to compile I just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, I can version bump my project upon release. I just need to place the necessary version without needing to modify code, but instead I can set it upon compile time.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>c</category>
    </item>
    <item>
      <title>Do not use from with getRepository when creating query builder</title>
      <dc:creator>Dimitrios Desyllas</dc:creator>
      <pubDate>Tue, 04 Mar 2025 17:37:08 +0000</pubDate>
      <link>https://forem.com/pcmagas/do-not-use-from-with-getrepository-when-creating-query-builder-2h5</link>
      <guid>https://forem.com/pcmagas/do-not-use-from-with-getrepository-when-creating-query-builder-2h5</guid>
      <description>&lt;p&gt;In my symfony project, I was using the query builder in order to query a table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Infrastructure\Services&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Doctrine\ORM\EntityManagerInterface&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Entity\MyModel&lt;/span&gt;

&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FetchResultFromDb&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;EntityManagerInterface&lt;/span&gt; &lt;span class="nv"&gt;$entityManager&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;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getEarliestResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$rowNum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="nv"&gt;$queryBuilder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;entityManager&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MyModel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;createQueryBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'m'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$queryBuilder&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MyModel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'m'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'m.id'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;orderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'m.sentTimestamp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'ASC'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setMaxResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$rowNum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getQuery&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getResult&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I noticed that calling the &lt;code&gt;getEarliestResult&lt;/code&gt; on a row containing ~10000 rows took too long:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Command&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\Console\Attribute\AsCommand&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\Console\Command\Command&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\Console\Input\InputArgument&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\Console\Input\InputInterface&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\Console\Input\InputOption&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\Console\Output\OutputInterface&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\Console\Style\SymfonyStyle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;AsCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'test:query'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Add a short description for your command'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestQueryCommand&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Command&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;FetchResultFromDb&lt;/span&gt; &lt;span class="nv"&gt;$service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;InputInterface&lt;/span&gt; &lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;OutputInterface&lt;/span&gt; &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getEarliestResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Rest of code gows here ommited for simplicity&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;In my case was ~75 second. &lt;/p&gt;

&lt;p&gt;In order to see the cause of this delay the first stem was to refactor my method and dump the generated SQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace App\Infrastructure\Services;

use Doctrine\ORM\EntityManagerInterface;

use App\Entity\MyModel

class FetchResultFromDb 
{

    public function __construct(private EntityManagerInterface $entityManager)
    {
    }


    public function getEarliestResult(int $rowNum)
    {

        $queryBuilder = $this-&amp;gt;entityManager-&amp;gt;getRepository(MyModel::class)-&amp;gt;createQueryBuilder('m');

        $q=$queryBuilder
            -&amp;gt;from(MyModel::class, 'm')
            -&amp;gt;select('m.id')
            -&amp;gt;orderBy('m.sentTimestamp', 'ASC')
            -&amp;gt;setMaxResults($rowNum)
            -&amp;gt;getQuery();

       dump($q-&amp;gt;getSql());
       return $q-&amp;gt;getResult();
    }  

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

&lt;/div&gt;



&lt;p&gt;But the dump resulted retrieving this sql:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT m0_.id AS id_0 FROM my_model m1_, my_model m0_ ORDER BY m0_.sent_timestamp ASC LIMIT 5000;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the query does a cartetian product of all entries in database. That means that query iterates 5000X5000=&lt;em&gt;25000000&lt;/em&gt; results for just fetching only the 5000.&lt;/p&gt;

&lt;p&gt;That is wasteful of resources. In my case, I just wanted to do a simpler query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT id from my_model order by sent_timestamp LIMIT 5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  SOLUTION
&lt;/h1&gt;

&lt;p&gt;I managed to solve it this issue using 2 approaches:&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 1 Do not use &lt;code&gt;getRepository&lt;/code&gt; when creating a query builder:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace App\Infrastructure\Services;

use Doctrine\ORM\EntityManagerInterface;

use App\Entity\MyModel

class FetchResultFromDb 
{

    public function __construct(private EntityManagerInterface $entityManager)
    {
    }


    public function getEarliestResult(int $rowNum)
    {

        $queryBuilder = $this-&amp;gt;entityManager-&amp;gt;createQueryBuilder('m');

        return $queryBuilder
            -&amp;gt;from(MyModel::class, 'm')
            -&amp;gt;select('m.id')
            -&amp;gt;orderBy('m.sentTimestamp', 'ASC')
            -&amp;gt;setMaxResults($rowNum)
            -&amp;gt;getQuery()
            -&amp;gt;getResult();

    }  

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

&lt;/div&gt;



&lt;p&gt;As you can see, instead of using &lt;code&gt;$this-&amp;gt;entityManager-&amp;gt;getRepository(MyModel::class)-&amp;gt;createQueryBuilder('m');&lt;/code&gt; I used &lt;code&gt;$this-&amp;gt;entityManager-&amp;gt;createQueryBuilder('m');&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In other words, I removed the call of the method &lt;code&gt;getRepository&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 2 Do not use &lt;code&gt;from&lt;/code&gt; in the query Builder:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace App\Infrastructure\Services;

use Doctrine\ORM\EntityManagerInterface;

use App\Entity\MyModel

class FetchResultFromDb 
{

    public function __construct(private EntityManagerInterface $entityManager)
    {
    }


    public function getEarliestResult(int $rowNum)
    {

        $queryBuilder = $this-&amp;gt;entityManager-&amp;gt;getRepository(MyModel::class)-&amp;gt;createQueryBuilder('m');

        $q=$queryBuilder
            -&amp;gt;select('m.id')
            -&amp;gt;orderBy('m.sentTimestamp', 'ASC')
            -&amp;gt;setMaxResults($rowNum)
            -&amp;gt;getQuery();

       return $q-&amp;gt;getResult();
    }  

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

&lt;/div&gt;



&lt;p&gt;Calling &lt;code&gt;getRepository(MyModel::class)&lt;/code&gt; and then &lt;code&gt;createQueryBuilder('m')&lt;/code&gt; has a result for the query builder to append on its own the necessary &lt;code&gt;from&lt;/code&gt; section in the final sql that qill be executed upon db.&lt;/p&gt;

&lt;p&gt;Therefore, placing from does not offer any beneft whatoever.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclution
&lt;/h1&gt;

&lt;p&gt;To sum up when creating a query builder do it 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;$this-&amp;gt;entityManager-&amp;gt;createQueryBuilder('m');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you get the repository first avoid using &lt;code&gt;from&lt;/code&gt; because it results a cartetian product.&lt;/p&gt;

</description>
      <category>php</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How I can join with count subquery upon doctrine?</title>
      <dc:creator>Dimitrios Desyllas</dc:creator>
      <pubDate>Tue, 04 Mar 2025 17:11:05 +0000</pubDate>
      <link>https://forem.com/pcmagas/how-i-can-join-with-count-subquery-upon-doctrine-1opf</link>
      <guid>https://forem.com/pcmagas/how-i-can-join-with-count-subquery-upon-doctrine-1opf</guid>
      <description>&lt;p&gt;Hello can you help me with this?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/79484363/how-i-can-join-using-counts-using-doctrine" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/79484363/how-i-can-join-using-counts-using-doctrine&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What I try to do is run the following query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;select
    user.*,
    business_count.count
from
    user
join (
    select
        count(*) as count,
        user_id
    from
        business
    group by
        user_id) as business_count on business_count.user_id = user.id;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the doctrine's query builder. But for not it does not allow me:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  [Semantical Error] line 0, col 48 near 'JOIN (SELECT': Error: Subquery is not supported here  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Therefore, I am exploring any solutikn to this.&lt;/p&gt;

</description>
      <category>php</category>
      <category>symfony</category>
    </item>
  </channel>
</rss>
