<?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: Sarah Siqueira</title>
    <description>The latest articles on Forem by Sarah Siqueira (@sarahcssiqueira).</description>
    <link>https://forem.com/sarahcssiqueira</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%2F926397%2F04940e21-34d5-43f9-a0b7-f07f8cfc42d4.jpg</url>
      <title>Forem: Sarah Siqueira</title>
      <link>https://forem.com/sarahcssiqueira</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sarahcssiqueira"/>
    <language>en</language>
    <item>
      <title>Automatically Deploying Drupal Projects with GitHub Actions (Modules, Themes &amp; Config)</title>
      <dc:creator>Sarah Siqueira</dc:creator>
      <pubDate>Wed, 25 Mar 2026 02:15:06 +0000</pubDate>
      <link>https://forem.com/sarahcssiqueira/automatically-deploying-drupal-projects-with-github-actions-modules-themes-config-mfk</link>
      <guid>https://forem.com/sarahcssiqueira/automatically-deploying-drupal-projects-with-github-actions-modules-themes-config-mfk</guid>
      <description>&lt;p&gt;When working with Drupal, deployment goes beyond simply uploading modules or themes. Unlike other CMS platforms, Drupal relies heavily on configuration management, Composer dependencies, and database updates.&lt;/p&gt;

&lt;p&gt;In this guide, I'll show you how to automatically deploy a Drupal project using GitHub Actions, including custom modules, themes, and configuration changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Drupal Deployment
&lt;/h2&gt;

&lt;p&gt;Before jumping into automation, it's important to understand how Drupal handles deployments.&lt;/p&gt;

&lt;p&gt;A Drupal application consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Codebase&lt;/strong&gt; (modules, themes, core)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependencies&lt;/strong&gt; (managed via Composer)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration&lt;/strong&gt; (stored in &lt;code&gt;/config/sync&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Database updates&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means deployment is not just copying files, it's a controlled process that ensures consistency across environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;A typical Drupal project looks 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;/web
  /modules/custom
  /themes/custom
/config/sync
composer.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our custom work (modules/themes) lives inside &lt;code&gt;/web&lt;/code&gt;, but everything is orchestrated through Composer and configuration management.&lt;/p&gt;

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

&lt;p&gt;Below is a basic GitHub Actions pipeline to deploy a Drupal project:&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;Deploy Drupal&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="nv"&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;deploy&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 repository&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;Setup PHP&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;shivammathur/setup-php@v2&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;php-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8.1&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;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;composer install --no-dev --optimize-autoloader&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;Deploy files to server&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;rsync -avz --delete ./ user@your-server:/var/www/drupal-project&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;Run Drupal commands&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;ssh user@your-server "&lt;/span&gt;
            &lt;span class="s"&gt;cd /var/www/drupal-project &amp;amp;&amp;amp;&lt;/span&gt;
            &lt;span class="s"&gt;drush cim -y &amp;amp;&amp;amp;&lt;/span&gt;
            &lt;span class="s"&gt;drush updb -y &amp;amp;&amp;amp;&lt;/span&gt;
            &lt;span class="s"&gt;drush cr&lt;/span&gt;
          &lt;span class="s"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Happens During Deployment
&lt;/h2&gt;

&lt;p&gt;Each deployment executes three critical steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Import Configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;drush cim &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Syncs configuration changes (content types, fields, views, etc.)&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Run Database Updates
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;drush updb &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Applies pending schema changes from modules&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Clear Cache
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;drush cr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensures Drupal reflects the latest changes&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Differences from WordPress
&lt;/h2&gt;

&lt;p&gt;If you're coming from WordPress, like me when I started in Drupal, the biggest mindset shift is this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You don’t deploy &lt;em&gt;just a plugin&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;You deploy the &lt;strong&gt;entire application state&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This, in my opniion, makes Drupal deployments more predictable, but also more structured.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying Only a Custom Module - Optional
&lt;/h2&gt;

&lt;p&gt;While not recommended for production workflows, we &lt;em&gt;can&lt;/em&gt; deploy only a module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/web/modules/custom/your_module
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, westill need to clear cache:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;drush cr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a more robust approach, managing our module as a Composer package looks a better choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Always version your &lt;code&gt;/config/sync&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;Never edit configuration directly in production&lt;/li&gt;
&lt;li&gt;Use Composer for dependency management&lt;/li&gt;
&lt;li&gt;Automate Drush commands in your pipeline&lt;/li&gt;
&lt;li&gt;Treat Drupal as a full application, not just a CMS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Automating Drupal deployments with GitHub Actions provides a reliable and repeatable workflow. By combining Composer, configuration management, and Drush, we can ensure that every environment stays in sync.&lt;/p&gt;

&lt;p&gt;While this approach may feel more complex compared to other CMS platforms, it offers significantly more control and scalability,  especially in team environments and production systems.&lt;/p&gt;

&lt;p&gt;If you're already automating WordPress deployments, adopting this workflow for Drupal is a natural next step toward more advanced DevOps practices.&lt;/p&gt;

</description>
      <category>drupal</category>
      <category>cicd</category>
      <category>php</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Setting Up a Drupal Development Environment with DDEV</title>
      <dc:creator>Sarah Siqueira</dc:creator>
      <pubDate>Tue, 24 Mar 2026 22:40:36 +0000</pubDate>
      <link>https://forem.com/sarahcssiqueira/setting-up-a-drupal-development-environment-with-ddev-e7g</link>
      <guid>https://forem.com/sarahcssiqueira/setting-up-a-drupal-development-environment-with-ddev-e7g</guid>
      <description>&lt;p&gt;&lt;strong&gt;DDEV&lt;/strong&gt; is a powerful tool that &lt;strong&gt;simplifies the process of setting up local development environments for PHP applications&lt;/strong&gt;, including Drupal. In this guide, I'll walk you through the steps to install DDEV and configure a Drupal development environment.&lt;/p&gt;

&lt;p&gt;Requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ddev.com/" rel="noopener noreferrer"&gt;DDEV&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you have this, create your Drupal project directory:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir drupal-site&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Into your directory run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;composer create-project drupal/recommended-project:^9 .&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;At the moment I created this project, running &lt;code&gt;composer create-project drupal/recommended-project .&lt;/code&gt; automatically would download Drupal 10, which requires &lt;strong&gt;PHP version "&amp;gt;= 8.3.0".&lt;/strong&gt; This would trigger a fatal error:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Fatal error: Composer detected issues in your platform: Your Composer dependencies require a PHP version "&amp;gt;= 8.3.0". You are running 8.1.27. in /var/www/html/vendor/composer/platform_check.php on line 24&lt;/code&gt;&lt;br&gt;
because the DDEV container has an older PHP version. That’s why I explicitly asked for Drupal 9 in the command.&lt;/p&gt;

&lt;p&gt;Next, configure DDEV:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ddev config&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You will be prompted with some options. Select your project name, docroot location, and then the project type. You’ll see options like:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Project Type [backdrop, craftcms, django4, drupal10, drupal6, drupal7, drupal8, drupal9, laravel, magento, magento2, php, python, shopware6, silverstripe, typo3, wordpress]&lt;/code&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%2Fvgaunt96ean72y0xbf89.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%2Fvgaunt96ean72y0xbf89.png" alt=" " width="800" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, I selected drupal9. After that, run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ddev start&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You will see a success message with the URLs to access your Drupal project: &lt;code&gt;Project can be reached at https://drupal-site.ddev.site https://127.0.0.1:52810&lt;/code&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%2Fw6rr65zslcvmmpa54wfl.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%2Fw6rr65zslcvmmpa54wfl.png" alt=" " width="800" height="41"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open your chosen browser and finish the Drupal installation.&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%2Fq2rs5evnkokudjlyd4df.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%2Fq2rs5evnkokudjlyd4df.png" alt=" " width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Simple as that!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DDEV&lt;/strong&gt; can be used for a wide variety of &lt;strong&gt;PHP-based CMSs&lt;/strong&gt;, such as WordPress. You can follow a similar process; check out this article: &lt;a href="https://dev.to/sarahcssiqueira/setting-up-a-wordpress-development-environment-with-ddev-2bia"&gt;Setting up a WordPress development environment with DDEV.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is your favorite tool for local PHP development? From my experience with a wide variety of setups over the years, DDEV has proven to be an amazing solution for teams. It &lt;strong&gt;simplifies versioning, collaboration&lt;/strong&gt;, and later &lt;strong&gt;establishing deployment pipelines, making development smoother and more predictable.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Leave your comment below. I’d love to hear your thoughts!&lt;/p&gt;

&lt;p&gt;Image: &lt;a href="https://www.valuebound.com/resources/blog/how-use-ddev-streamline-your-drupal-development-process" rel="noopener noreferrer"&gt;https://www.valuebound.com/resources/blog/how-use-ddev-streamline-your-drupal-development-process&lt;/a&gt;&lt;/p&gt;

</description>
      <category>drupal</category>
      <category>development</category>
      <category>docker</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Publishing a NPM Package Automatically with GitHub Actions</title>
      <dc:creator>Sarah Siqueira</dc:creator>
      <pubDate>Sat, 14 Mar 2026 15:09:11 +0000</pubDate>
      <link>https://forem.com/sarahcssiqueira/publishing-a-npm-package-automatically-with-github-actions-322f</link>
      <guid>https://forem.com/sarahcssiqueira/publishing-a-npm-package-automatically-with-github-actions-322f</guid>
      <description>&lt;p&gt;That's one  is mostly for my future reference, but I hope it’s useful to others too. It’s interesting how different this feels compared to when I started this writing journey three years ago. Today, I can easily search my ChatGPT chat history for solutions. Still, I sometimes feel that relying too much on AI makes me lazier and less focused. Writing forces me to focus, something social media endless scrolling and asking AI can take away.&lt;/p&gt;

&lt;p&gt;Before this turns into a philosophical discussion on whether AI will take our jobs, I’ll stick to documenting how I publish an NPM package automatically using GitHub Actions.&lt;/p&gt;

&lt;p&gt;Even though AI can now generate &lt;code&gt;.yml&lt;/code&gt; workflows almost instantly, I still find writing them myself worthwhile because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It helps me internalize the knowledge &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Understanding what you’re doing is essential, relying blindly on generated code doesn’t help long-term.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Step 1 – Have a Package to Publish
&lt;/h1&gt;

&lt;p&gt;You need a valid Node.js package to publish to NPM. If you don’t have one yet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a package.json with npm init (or npm init -y to skip prompts).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add your source code and tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure your package has a &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;unique name on NPM&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this example, I’m using a &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;QR Code generator I built&lt;/a&gt;. It uses &lt;strong&gt;Reed-Solomon error correction codes&lt;/strong&gt; and was a &lt;strong&gt;fun exercise to practice logic.&lt;/strong&gt; The package is usable already, though I’m still not quite happy with that, so I am refining some logic.&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 2 – Set Up Your NPM Account and Token
&lt;/h1&gt;

&lt;p&gt;To publish packages automatically, you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An NPM account&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An access token with publish permissions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Store the token as a GitHub secret at the package repository you want to publis so the workflow we gonna build can access it securely.&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 3 – Publish Your Package Locally
&lt;/h1&gt;

&lt;p&gt;Before automating, make sure you can publish manually:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm publish&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This ensures your package configuration is correct, dependencies are installed, and there are no errors. You likely gonna be prompet to log at NPM by running this for the very first time.&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 4 – Automate Publishing with GitHub Actions
&lt;/h1&gt;

&lt;p&gt;Here’s a &lt;a href="https://github.com/sarahcssiqueira/qrcode-pack/blob/master/.github/workflows/generate-release.yml" rel="noopener noreferrer"&gt;workflow that automatically generates a GitHub release and publishes to NPM whenever you push a tag.&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;Generate Release and Publish to NPM&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;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&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-release&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="c1"&gt;# Get Tag Name&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;Get Tag name&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vars&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "TAG_NAME=${GITHUB_REF_NAME}" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;

      &lt;span class="c1"&gt;# Generate GitHub Release&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;Create GitHub Release&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;softprops/action-gh-release@v2&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;files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.ZIP_NAME }}&lt;/span&gt;
          &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;**QR Code Pack – Version ${{ github.ref_name }}**&lt;/span&gt;

            &lt;span class="s"&gt;For detailed changes in this version, see the automatically generated notes.&lt;/span&gt;
          &lt;span class="na"&gt;generate_release_notes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;make_latest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GH_PAT }}&lt;/span&gt;

      &lt;span class="c1"&gt;# Publish to NPM&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;Setup Node&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-node@v4&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;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
          &lt;span class="na"&gt;registry-url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://registry.npmjs.org/&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;Publish to NPM&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm publish&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;NODE_AUTH_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.NPM_TOKEN }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reference: &lt;a href="https://nearform.com/digital-community/publish-npm-packages/" rel="noopener noreferrer"&gt;An Open Source Maintainer's Guide to Publishing npm Package&lt;/a&gt; &lt;br&gt;
Image: &lt;a href="https://nearform.com/digital-community/publish-npm-packages/" rel="noopener noreferrer"&gt;https://nearform.com/digital-community/publish-npm-packages/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>github</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Using GitHub Copilot to Manage Issues (and Save Time)</title>
      <dc:creator>Sarah Siqueira</dc:creator>
      <pubDate>Thu, 31 Jul 2025 22:10:32 +0000</pubDate>
      <link>https://forem.com/sarahcssiqueira/using-github-copilot-to-manage-issues-and-save-time-3549</link>
      <guid>https://forem.com/sarahcssiqueira/using-github-copilot-to-manage-issues-and-save-time-3549</guid>
      <description>&lt;p&gt;Managing issues efficiently is crucial for any project or collaborative development effort. As a maintainer for some or open souce projects, I've always looked for ways to streamline the process of creating, analyzing, and tracking issues. Recently, I've started using GitHub Copilot on my github.com projects to automate and accelerate these tasks, and it’s been surprisingly helpful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Copilot for Issue Management?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It’s fast:&lt;/strong&gt; I can draft and save issues without switching tabs or digging through templates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It understands the context:&lt;/strong&gt; Copilot pulls info from the codebase, past issues, etc., so the suggestions aren’t random.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It helps with analysis:&lt;/strong&gt; You can get a summary or a nicely formatted version of any issue on demand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Keeps things tidy:&lt;/strong&gt; Labels, formatting, and author info stay consistent across all issues.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Create and Manage Issues Using Copilot (Step-by-Step)
&lt;/h2&gt;

&lt;p&gt;Here’s a practical workflow, based on my recent experience managing issues for a WordPress theme repository:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Start a Session with Copilot
&lt;/h3&gt;

&lt;p&gt;You can begin by opening a conversation with Copilot directly on GitHub. Let Copilot know what you need—whether it’s drafting a new issue, analyzing an existing one, or fetching details.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Ask for a Draft
&lt;/h3&gt;

&lt;p&gt;Simply tell Copilot your intent, something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Draft an issue for adding Full Site Editing support.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And Copilot gives me a clean, formatted issue with suggested labels. Sometimes I tweak it a bit, but it’s a solid starting point.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Save the Issue
&lt;/h3&gt;

&lt;p&gt;When I’m happy with the draft, I tell Copilot to save it—and it creates the issue with all the usual metadata to your repository 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;list type="issue"
data:
- url: https://github.com/sarahcssiqueira/base-wp-theme/issues/11
  state: "open"
  draft: false
  title: "Add Full Site Editing (FSE) and Block Theme Support"
  number: 11
  author: sarahcssiqueira
  created_at: "2025-07-26T19:36:28Z"
  closed_at: null
  labels:
    - name: "enhancement"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Fetch and Analyze Issues
&lt;/h3&gt;

&lt;p&gt;You can ask Copilot to fetch details for any issue—just provide the issue URL. Copilot returns the data in a clean, YAML format for easy reading, reporting, or further automation.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Repeat as Needed
&lt;/h3&gt;

&lt;p&gt;This process can be repeated for any new feature, bug, or enhancement. I go through the same flow. It helps me stay consistent and organized. Copilot keeps track of labels, author, timestamps, and more. &lt;/p&gt;

&lt;h3&gt;
  
  
  6. Aggregate and Review
&lt;/h3&gt;

&lt;p&gt;Because Copilot outputs issues in a standardized format, you can quickly aggregate, filter, or export issue data for project analysis or reporting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Workflow Recap
&lt;/h2&gt;

&lt;p&gt;Here’s a summary of what I did using Copilot:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Drafted several issues:&lt;/strong&gt; For features like FSE support, asset management, performance optimization, and i18n/RTL support.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Saved each issue:&lt;/strong&gt; Copilot created them on GitHub and provided YAML-formatted data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fetched details:&lt;/strong&gt; I could retrieve or summarize any issue instantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reviewed and analyzed:&lt;/strong&gt; All issues were ready for tracking and reporting.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Want to See It in Action?
&lt;/h2&gt;

&lt;p&gt;You can check out the actual issues I’ve been working on in this repo: &lt;a href="https://github.com/sarahcssiqueira/base-wp-theme/issues" rel="noopener noreferrer"&gt;Base WP Theme&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot isn’t just for code—it’s a fantastic productivity booster for project management too. If you’re looking to save time, maintain consistency, and analyze your project’s workflow, give Copilot a try for issue management!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have questions, tips, or your own Copilot workflows? Share below!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Follow me for more insights on open source automation and productivity.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>githubcopilot</category>
      <category>productivity</category>
      <category>opensource</category>
      <category>management</category>
    </item>
    <item>
      <title>When Physics Meets Code: Did We Find a Bug Fix in the Universe? Is the Universe Debugging Itself?</title>
      <dc:creator>Sarah Siqueira</dc:creator>
      <pubDate>Thu, 03 Jul 2025 23:27:36 +0000</pubDate>
      <link>https://forem.com/sarahcssiqueira/did-a-physicist-find-error-correcting-code-in-reality-and-what-that-means-to-us-developers-19b7</link>
      <guid>https://forem.com/sarahcssiqueira/did-a-physicist-find-error-correcting-code-in-reality-and-what-that-means-to-us-developers-19b7</guid>
      <description>&lt;p&gt;This post is very different from the random tutorials I’ve published before (mostly about WordPress). It’s more philosophical and maybe even mind-blowing. &lt;/p&gt;

&lt;p&gt;The best programmers I’ve ever met are incredibly curious. They break things and learn how to fix them. Constantly. Same with scientists. The main difference, at least in Brazil, is that developers tend to earn more than scientists on average.&lt;/p&gt;

&lt;p&gt;Long story short, I once wanted to be a scientist, a physicist. But I didn’t feel my math skills were strong enough (thanks, Oppenheimer). So I became a developer to pay the bills… and ended up enjoying it.&lt;br&gt;&lt;br&gt;
The actual coding? That’s fun.&lt;/p&gt;

&lt;p&gt;Still, part of me never stopped staring at the universe. I often catch myself spotting patterns in everyday life, especially in nature.&lt;/p&gt;

&lt;p&gt;It’s like my brain runs on developer mode: I see things as if they were frameworks or packages just waiting to be unpacked.&lt;br&gt;
A seed? Feels like nature’s own NPM package, once installed, it becomes a flower, a tree, or something even more intricate.&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%2Fnbhi5b40wfz5uely6wqc.jpg" 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%2Fnbhi5b40wfz5uely6wqc.jpg" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m constantly trying to “decode” reality through that lens.&lt;br&gt;
And sometimes, it even feels like the whole thing is structured... maybe even designed?&lt;/p&gt;

&lt;p&gt;That’s what sparked this random article, written on a cold and boring day.&lt;br&gt;
I was remembering one of the most “whoa” moments I’ve had while on physics college.&lt;br&gt;&lt;br&gt;
Mark this name: &lt;strong&gt;James Gates Jr.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Did a Physicist Find Error-Correcting Code in Reality?
&lt;/h2&gt;

&lt;p&gt;Back in college, I read about this guy, the theoretical physicist &lt;strong&gt;James Gates Jr.&lt;/strong&gt; who claimed to have found &lt;strong&gt;binary error-correcting codes&lt;/strong&gt; hidden in the mathematics of string theory.&lt;/p&gt;

&lt;p&gt;At the time, I barely knew how to code. But even then, it sounded wild.&lt;/p&gt;

&lt;p&gt;I know, it sounds like clickbait. But it’s not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strings, Not Particles
&lt;/h2&gt;

&lt;p&gt;I won’t dive deep into string theory here, that would take years and a lot more coffee. But here’s just enough context to follow along:&lt;/p&gt;

&lt;p&gt;String theory suggests that the smallest building blocks of reality aren’t particles, but &lt;strong&gt;tiny vibrating strings&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Different vibrations = different particles.&lt;/p&gt;

&lt;p&gt;It’s a beautiful, deeply mathematical framework that tries to unify gravity, electromagnetism, and nuclear forces. But when researchers dove deeper into &lt;strong&gt;supersymmetric string theory&lt;/strong&gt;, something weird happened...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;They found the &lt;strong&gt;same kind of codes&lt;/strong&gt; we developers use to prevent data loss or transmission errors.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let me be clear: this isn’t pseudoscience or a conspiracy theory. This is high-level math, developed by some of the brightest minds in the world. It deserves, at the very least, our curiosity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who Is James Gates Jr.?
&lt;/h2&gt;

&lt;p&gt;Dr. Gates was studying representations of &lt;strong&gt;supersymmetry&lt;/strong&gt;, a principle that (simplified) connects force particles (bosons) and matter particles (fermions).&lt;/p&gt;

&lt;p&gt;To visualize these relationships, he used graphical tools called &lt;strong&gt;Adinkras&lt;/strong&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%2Ftwywm9d11563ub9tc0zc.jpg" 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%2Ftwywm9d11563ub9tc0zc.jpg" alt=" " width="799" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And while working with these structures, he discovered something surprising:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We discovered that these equations contain codes, actual, literal error-correcting codes. The same ones used in computers to detect and fix errors in digital data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Specifically, he found:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Doubly-even self-dual binary linear block codes&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wait… What Are Those?
&lt;/h2&gt;

&lt;p&gt;At the time, I didn’t understand any of this. Now, after almost 10 years in development, I feel more at home with these concepts. Here’s a basic breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Binary&lt;/strong&gt;: Made of 0s and 1s
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linear&lt;/strong&gt;: The XOR of any two valid codewords is another valid codeword
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-dual&lt;/strong&gt;: The code equals its own dual (like a mirror image)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Doubly-even&lt;/strong&gt;: All codewords have a number of 1s divisible by 4
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These principles are core to digital integrity, and show up in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ECC memory&lt;/li&gt;
&lt;li&gt;Satellite data transmission&lt;/li&gt;
&lt;li&gt;DVDs&lt;/li&gt;
&lt;li&gt;RAID storage systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And now, apparently... &lt;strong&gt;the math of the universe.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Is the Universe Debugging Itself?
&lt;/h2&gt;

&lt;p&gt;This finding raises a fascinating question:  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is the universe capable of &lt;strong&gt;self-correction&lt;/strong&gt;?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dr. Gates isn’t saying we’re living in a simulation... but he’s also &lt;strong&gt;not&lt;/strong&gt; saying we’re &lt;em&gt;not&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Finding built-in error-correction logic within physical equations is eerie.&lt;br&gt;&lt;br&gt;
It’s like discovering a &lt;code&gt;try/catch&lt;/code&gt; block in raw spacetime.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“If we’re seeing code in the equations of physics,” Dr. Gates said, “maybe there’s a deeper layer to reality. Maybe reality is structured, or computed.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Honestly? That idea made my brain itch in the best way.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Built a JS Demo
&lt;/h2&gt;

&lt;p&gt;Because I’m a curious dev (read: obsessive), I wanted to understand how these codes worked. I ended up spending way more time than I should’ve tinkering with C++ and compiling assembly, seriously, I should’ve been out there living life, for God’s sake.&lt;/p&gt;

&lt;p&gt;Eventually, I built a small JS demo to visualize how digital integrity is preserved.&lt;/p&gt;

&lt;p&gt;You can check out the full demo and source code in my &lt;a href="https://github.com/sarahcssiqueira/doubly-even-code-checker" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It’s basic, but seeing the patterns come alive gave me chills.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This stuff is &lt;strong&gt;not trivial&lt;/strong&gt;. It’s complex. It’s deep. And it’s philosophical.&lt;/p&gt;

&lt;p&gt;As someone who studied physics for six semesters, I can say I still don’t have the full math chops to understand it all.&lt;br&gt;&lt;br&gt;
And as a web developer? Well, binary code and self-dual logic aren’t exactly part of my day job.&lt;/p&gt;

&lt;p&gt;But if you’re curious like me, here’s what you’d need to dive deeper:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linear Algebra&lt;/strong&gt; – for understanding vector spaces and matrices
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Introduction to Coding Theory&lt;/strong&gt; – binary linear codes, self-duality
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic Quantum Mechanics&lt;/strong&gt; – wave functions, observables
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intro to Supersymmetry&lt;/strong&gt; – even at a conceptual level
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mathematics of String Theory&lt;/strong&gt; – only after building the foundation
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s not easy, it requires both technical depth and mental flexibility. But the implications?&lt;br&gt;&lt;br&gt;
They’re worth exploring.&lt;/p&gt;

&lt;p&gt;Because if the universe is built on &lt;strong&gt;code&lt;/strong&gt;, maybe learning this is our way of &lt;strong&gt;reading the source&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We usually debug &lt;strong&gt;our code&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
But what if &lt;strong&gt;the universe is debugging itself&lt;/strong&gt;?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What if physics is full of hidden logic designed to self-correct?&lt;br&gt;&lt;br&gt;
What if developers and physicists are solving similar problems, just on different scales?&lt;/p&gt;

&lt;p&gt;Maybe we’re not just building things inside the system.&lt;br&gt;
Maybe we’re studying the system... from the inside.&lt;/p&gt;

&lt;p&gt;Just don’t dive too deep without coming up for air. Stare too long into the abyss, it might stare back.&lt;/p&gt;

&lt;p&gt;Remember to breathe. Pay your bills. Enjoy your food. Travel. Laugh with people you love.&lt;br&gt;
Live fully, simulation or not, it’s a beautiful one.&lt;/p&gt;

&lt;p&gt;But yeah... this is wild. I need some coffee and to go be blissfully dumb for a while.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/abs/0806.0051" rel="noopener noreferrer"&gt;Relating Doubly-Even Error-Correcting Codes, Graphs, and Supersymmetry (arXiv)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://onbeing.org/programs/s-james-gates-uncovering-the-codes-for-reality/" rel="noopener noreferrer"&gt;Uncovering the Codes for Reality – interview with James Gates Jr. (On Being)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Through the Wormhole&lt;/em&gt; – &lt;a href="https://www.youtube.com/watch?v=tlTKTTt47WE" rel="noopener noreferrer"&gt;Are We Living in a Simulation? (YouTube)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Error_correction_code" rel="noopener noreferrer"&gt;Error-Correcting Codes - Wikipedia&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.reddit.com/r/explainlikeimfive/comments/2t6z2e/eli5_physicist_james_gates_claims_that_you_can/" rel="noopener noreferrer"&gt;Physicist James Gates claims that you can find computer code in the equations that we use to describe our universe in string theory. &lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>physics</category>
      <category>javascript</category>
      <category>code</category>
    </item>
    <item>
      <title>Setting Up a WordPress Development Environment with DDEV</title>
      <dc:creator>Sarah Siqueira</dc:creator>
      <pubDate>Thu, 31 Oct 2024 17:01:39 +0000</pubDate>
      <link>https://forem.com/sarahcssiqueira/setting-up-a-wordpress-development-environment-with-ddev-2bia</link>
      <guid>https://forem.com/sarahcssiqueira/setting-up-a-wordpress-development-environment-with-ddev-2bia</guid>
      <description>&lt;p&gt;**&lt;a href="https://ddev.com/" rel="noopener noreferrer"&gt;DDEV&lt;/a&gt; is a powerful tool that simplifies the process of setting up local development environments for PHP applications, including WordPress. Similar to how I explored &lt;a href="https://dev.to/sarahcssiqueira/setting-up-a-drupal-development-environment-with-ddev-e7g"&gt;setting up Drupal with DDEV&lt;/a&gt; in another guide, this article will walk you through the steps to install DDEV and configure a WordPress development environment.&lt;/p&gt;

&lt;p&gt;Requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ddev.com/" rel="noopener noreferrer"&gt;DDEV&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you have this, create your WordPress project directory:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir wp-test-site&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Into your directory run &lt;/p&gt;

&lt;p&gt;&lt;code&gt;ddev config&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then, choose the project name and the project type, which in this case will be WordPress. Run&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ddev start&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You will see the output with the path to access your WordPress installation: &lt;a href="https://wp-test.ddev.site" rel="noopener noreferrer"&gt;https://wp-test.ddev.site&lt;/a&gt; &lt;a href="https://127.0.0.1:port" rel="noopener noreferrer"&gt;https://127.0.0.1:port&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Access through your choose browser and finish WordPress install.&lt;/p&gt;

&lt;p&gt;Simple as that! (Or should be).&lt;/p&gt;

&lt;p&gt;Seems kind of dumb for looking at it now, but on the first time I came across it a few months ago, while setting the dev environment for a new project I was assigned to, in the agency I worked, I got stuck with the error: &lt;strong&gt;403 forbidden nginx&lt;/strong&gt; for quite some time.&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%2Figtykg6f4iyweo6g3abd.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%2Figtykg6f4iyweo6g3abd.png" alt=" " width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It took me a few to me realize the thing was: there were no WordPress core files into my root project folder.&lt;/p&gt;

&lt;p&gt;The solution?&lt;/p&gt;

&lt;p&gt;Download the WordPress files to the root folder, duuh.But, it not practical do it everytime I had to start the project. So, my plan here:&lt;/p&gt;

&lt;h3&gt;
  
  
  Edit the config.yml on .ddev folder
&lt;/h3&gt;

&lt;p&gt;Within the root project folder, find the ./ddev/config.yml file and add this:&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;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;post-start&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;exec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;curl&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-O&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;https://wordpress.org/latest.tar.gz"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;exec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tar&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-xzf&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;latest.tar.gz&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--strip-components=1"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;exec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rm&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;latest.tar.gz"&lt;/span&gt; &lt;span class="s"&gt;on config.yml.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this does is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;post-start: This hook runs commands after the DDEV project starts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the commands:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;curl -O &lt;a href="https://wordpress.org/latest.tar.gz:" rel="noopener noreferrer"&gt;https://wordpress.org/latest.tar.gz:&lt;/a&gt; Downloads the latest version of WordPress.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tar -xzf latest.tar.gz --strip-components=1: Extracts the contents of the tar file into the current directory, removing the top-level directory from the extracted files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;rm latest.tar.gz: Cleans up by removing the downloaded tar file.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also add a conditional check to verify if the WordPress core files are present, otherwise, everytime you run &lt;code&gt;ddev stop&lt;/code&gt; and then &lt;code&gt;ddev start&lt;/code&gt; again, it will download the WordPress core files all over again, we don't need that.&lt;/p&gt;

&lt;p&gt;Command updated with conditional checks:&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;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;post-start&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;exec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;!&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-f&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;wp-load.php&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(curl&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-O&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;https://wordpress.org/latest.tar.gz&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tar&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-xzf&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;latest.tar.gz&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--strip-components=1&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;rm&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;latest.tar.gz)&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;||&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;echo&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"WordPress&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;core&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;files&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;already&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;present,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;skipping&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;download."'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that the hooks only run the installation if WordPress is not already present. By run &lt;code&gt;ddev start&lt;/code&gt; on your terminal, if the WordPress core files are present, you will see the message &lt;em&gt;"WordPress core files already present, skipping download."&lt;/em&gt; instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally, start Your DDEV Project
&lt;/h2&gt;

&lt;p&gt;Run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ddev start&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The first time, may take more time, depending on your internet connection, as  it will need to install the core files. But the next times, will be easy peasy.&lt;/p&gt;

&lt;p&gt;Important Note: Make sure to run &lt;code&gt;ddev start&lt;/code&gt; from your project root directory, where the &lt;code&gt;config.yaml&lt;/code&gt; file is located. &lt;/p&gt;

&lt;p&gt;It's incredibly &lt;strong&gt;useful to share projects among teams&lt;/strong&gt;, we can also add some other features like &lt;code&gt;ddev pull&lt;/code&gt;, to &lt;strong&gt;pull the DB&lt;/strong&gt; of a staging website your team is working for example. You can a*&lt;em&gt;dd environment variables and so on&lt;/em&gt;*, but this is out of the scope of this article, which was simply to explain how to start a DDEV environment in a few steps.&lt;/p&gt;

&lt;p&gt;I had an old &lt;a href="https://github.com/sarahcssiqueira/docker-wordpress" rel="noopener noreferrer"&gt;docker environment I developed&lt;/a&gt; for personal use over time, wrote &lt;a href="https://dev.to/sarahcssiqueira/docker-environment-for-wordpress-development-p46"&gt;about it here&lt;/a&gt;. It was a such improvement for me back then (&lt;strong&gt;moving from ancient XAMPP&lt;/strong&gt;), but now, it seems so poor compared to DDEV lol.&lt;/p&gt;

&lt;p&gt;That's it for now. Start work with DDEV and Happy coding!&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>development</category>
      <category>docker</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Fixing PHP_CodeSniffer Null Trim() Errors in WordPress Coding Standards</title>
      <dc:creator>Sarah Siqueira</dc:creator>
      <pubDate>Tue, 15 Oct 2024 18:41:41 +0000</pubDate>
      <link>https://forem.com/sarahcssiqueira/fixing-phpcodesniffer-null-trim-errors-in-wordpress-coding-standards-31k1</link>
      <guid>https://forem.com/sarahcssiqueira/fixing-phpcodesniffer-null-trim-errors-in-wordpress-coding-standards-31k1</guid>
      <description>&lt;p&gt;While working on WordPress projects with PHP 8.x, you may encounter the following error:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Fatal error: Uncaught PHP_CodeSniffer\Exceptions\RuntimeException: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /path/...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This error occurs due to a deprecation warning in PHP 8.x, where passing &lt;code&gt;null&lt;/code&gt; to the &lt;code&gt;trim()&lt;/code&gt; function is no longer permitted. Specifically, this issue arises within a WordPress Coding Standards (WPCS) sniff, part of the PHP_CodeSniffer setup. As of the date of this writing, even with the latest versions of PHP_CodeSniffer and WordPress Coding Standards, this issue persists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding PHP_CodeSniffer and WPCS
&lt;/h2&gt;

&lt;p&gt;PHP_CodeSniffer is a tool that helps developers maintain coding standards by checking their PHP code for violations of specified rules. WordPress Coding Standards (WPCS) provide a set of guidelines for writing consistent and clean code in WordPress projects. The error mentioned above typically indicates that a code snippet is not adhering to these standards due to changes in PHP's behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing
&lt;/h2&gt;

&lt;p&gt;To fix this, we can manually modify the file causing the issue, locate the line where &lt;code&gt;trim()&lt;/code&gt; is called and update the code to ensuring that null values are properly handled when calling &lt;code&gt;trim()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, in the file &lt;strong&gt;vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/PrefixAllGlobalsSniff.php&lt;/strong&gt;, locate line 280 and replace the following line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// this 
$cl_prefixes = trim( PHPCSHelper::get_config_data( 'prefixes' );

// to this 

$cl_prefixes = is_null( PHPCSHelper::get_config_data( 'prefixes' ) ) ? '' : trim( PHPCSHelper::get_config_data( 'prefixes' ) );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, as in lots of decisions in software development, &lt;strong&gt;just because you can do this, doesn't mean you should&lt;/strong&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%2Fcxvlme6mfbh6anz85tqn.jpg" 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%2Fcxvlme6mfbh6anz85tqn.jpg" alt=" " width="320" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While the previous approach may fix the error, it's important to remember that &lt;strong&gt;modifying vendor files is not a sustainable solution&lt;/strong&gt;. Changes will be lost every time you update your dependencies via Composer.&lt;/p&gt;

&lt;p&gt;A better approach, then, is to create a patch file.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating a Patch File
&lt;/h1&gt;

&lt;p&gt;Here is a step-by-step guide on how to create and apply a patch for the issue&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the Patch File
&lt;/h2&gt;

&lt;p&gt;A more robust solution is to create a patch file. This method allows you to apply your changes automatically every time you install or update your dependencies.&lt;/p&gt;

&lt;p&gt;A patch file is a text file that contains the differences between two versions of a file—essentially a "before" and "after" snapshot.&lt;/p&gt;

&lt;p&gt;In your project directory, create a folder to hold the patch file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir -p patches&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Inside the patches/ folder, create a new patch file called fix-null-trim.patch. You can do this with your text editor:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch patches/fix-null-trim.patch&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Open fix-null-trim.patch in your text editor and &lt;a href="https://gist.github.com/sarahcssiqueira/3799fb5c09e086722ba80eff34830d3f" rel="noopener noreferrer"&gt;add the following content&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  --- a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/PrefixAllGlobalsSniff.php
+++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/PrefixAllGlobalsSniff.php
@@ -280,7 +280,7 @@

        // Original code with `trim()`
        // Update this line:
-       $cl_prefixes = trim( PHPCSHelper::get_config_data( 'prefixes' ) );
+       $cl_prefixes = is_null( PHPCSHelper::get_config_data( 'prefixes' ) ) ? '' : trim( PHPCSHelper::get_config_data( 'prefixes' ) );

--- a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/I18nSniff.php
+++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/WP/I18nSniff.php
@@ -194,7 +194,7 @@

        // Original code with `trim()`
        // Update this line:
-       $cl_text_domain = trim( PHPCSHelper::get_config_data( 'text_domain' ) );
+       $cl_text_domain = is_null(PHPCSHelper::get_config_data( 'text_domain' )) ? '' : trim( PHPCSHelper::get_config_data( 'text_domain' ) );

--- a/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Sniff.php
+++ b/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Sniff.php
@@ -1144,7 +1144,7 @@

        // Original code with `trim()`
        // Update this line:
-       $cl_supported_version = trim( PHPCSHelper::get_config_data( 'minimum_supported_wp_version' ) );
+       $cl_supported_version = is_null(PHPCSHelper::get_config_data( 'minimum_supported_wp_version' )) ? '' : trim( PHPCSHelper::get_config_data( 'minimum_supported_wp_version' ) );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This patch tells Composer to replace the problematic line in PrefixAllGlobalsSniff.php with a safer version that uses the null coalescing operator (??) to avoid passing null to trim().&lt;/p&gt;

&lt;h2&gt;
  
  
  Modify composer.json to Apply the Patch
&lt;/h2&gt;

&lt;p&gt;Next, you need to instruct Composer to apply this patch automatically whenever you install or update your dependencies.&lt;/p&gt;

&lt;p&gt;Open your project's composer.json file. Add the following configuration under the "extra" section. If the "extra" section does not already exist, you will need to create it.&lt;br&gt;
&lt;/p&gt;

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

    "extra": {
        "patches": {
            "wp-coding-standards/wpcs": {
                "Fix null trim() issue": "patches/fix-null-trim.patch"
            }
        }
    }

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

&lt;/div&gt;



&lt;p&gt;This tells Composer to apply the fix-null-trim.patch file to the wp-coding-standards/wpcs package when it installs or updates dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install the Composer Patch Plugin
&lt;/h2&gt;

&lt;p&gt;To apply patches via Composer, you need the composer-patches plugin.Run the following command to install:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;composer require cweagans/composer-patches&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Apply the Patch
&lt;/h2&gt;

&lt;p&gt;Now, you can apply the patch by running the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;composer install&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;During the installation, Composer will apply the patch from the patches/ folder to the PrefixAllGlobalsSniff.php file.&lt;/p&gt;

&lt;p&gt;By creating and applying a &lt;strong&gt;patch file&lt;/strong&gt;, you &lt;strong&gt;ensure&lt;/strong&gt; that your &lt;strong&gt;fixes persist across Composer updates&lt;/strong&gt;, adhering to best practices in software development. Regularly monitor updates to PHP_CodeSniffer and WordPress Coding Standards, as &lt;strong&gt;these issues may be resolved in future releases.&lt;/strong&gt; This proactive approach not only enhances code quality but also improves your development workflow in PHP 8.x environments.&lt;/p&gt;

&lt;p&gt;I've shared the patch file in this &lt;a href="https://gist.github.com/sarahcssiqueira/3799fb5c09e086722ba80eff34830d3f" rel="noopener noreferrer"&gt;Gist&lt;/a&gt;. Feel free to use it as a reference to implement similar fixes in your projects!&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>php</category>
      <category>patche</category>
    </item>
    <item>
      <title>Managing Ruby versions on macOS Apple Silicon with rbenv</title>
      <dc:creator>Sarah Siqueira</dc:creator>
      <pubDate>Mon, 02 Sep 2024 14:47:53 +0000</pubDate>
      <link>https://forem.com/sarahcssiqueira/managing-ruby-versions-on-macos-apple-silicon-with-rbenv-1mon</link>
      <guid>https://forem.com/sarahcssiqueira/managing-ruby-versions-on-macos-apple-silicon-with-rbenv-1mon</guid>
      <description>&lt;p&gt;Imagine this common scenario: You need to use a specific Ruby version, so you check which one is currently installed by running:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ruby -v&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The output shows:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;output ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin23]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Realizing that you need a newer version, you attempt to update Ruby. However, after running the update, you check the version again with &lt;code&gt;ruby -v&lt;/code&gt;, only to see the same output as before:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;output ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin23]&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does This Happen?
&lt;/h2&gt;

&lt;p&gt;This issue occurs because &lt;strong&gt;macOS comes with a system version of Ruby pre-installed&lt;/strong&gt;. This version is managed by the operating system and is located in a system directory, usually /usr/bin. &lt;strong&gt;Even if you install a new Ruby version using tools like Homebrew&lt;/strong&gt;, your terminal may still point to the system’s default Ruby version because it appears earlier in your $PATH.&lt;/p&gt;

&lt;p&gt;The $PATH is an environment variable that tells your shell where to look for executable files. If the system Ruby appears first in your $PATH, running &lt;code&gt;ruby -v&lt;/code&gt; &lt;strong&gt;will return the system version instead of the one you just installed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To override this, you need to manage Ruby versions using a version manager like &lt;a href="https://rbenv.org/" rel="noopener noreferrer"&gt;rbenv&lt;/a&gt;, which can properly set the desired Ruby version as the default.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to 'fix' this?
&lt;/h2&gt;

&lt;p&gt;To resolve this issue, you can use &lt;strong&gt;&lt;a href="https://rbenv.org/" rel="noopener noreferrer"&gt;rbenv&lt;/a&gt;&lt;/strong&gt;, a lightweight tool that allows you to easily install and manage multiple Ruby versions.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is rbenv?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://rbenv.org/" rel="noopener noreferrer"&gt;rbenv&lt;/a&gt; is a version management tool for Ruby. It allows you to switch between multiple Ruby versions without needing to mess with your system’s default Ruby installation. With rbenv, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install multiple versions of Ruby: Easily install and use any Ruby version;&lt;/li&gt;
&lt;li&gt;Switch between Ruby versions: Set a global default Ruby version or specify a Ruby version for a specific project.&lt;/li&gt;
&lt;li&gt;Simplify your Ruby setup: Avoid issues with conflicting Ruby versions, which is particularly useful if you're working on multiple projects with different Ruby dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Install rbenv
&lt;/h3&gt;

&lt;p&gt;First, install rbenv using Homebrew:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;brew install rbenv&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command also installs ruby-build, a plugin for rbenv that simplifies the process of installing new Ruby versions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure Your Shell
&lt;/h3&gt;

&lt;p&gt;Next, you need to configure your shell to use rbenv by adding the following line to your shell's configuration file:&lt;/p&gt;

&lt;p&gt;If you're using Bash, open .bash_profile:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nano .bash_profile&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;If you're using Zsh (the default on macOS), open .zshrc:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nano .zhrc&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;At the beginning of the file, add this line:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;eval "$(rbenv init -)"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command sets up your shell to load rbenv automatically, allowing it to manage your Ruby versions seamlessly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reload your shell configuration:
&lt;/h3&gt;

&lt;p&gt;For Bash:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;source ~/.bash_profile&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For Zsh:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;source ~/.zshrc&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify rbenv Installation
&lt;/h3&gt;

&lt;p&gt;To verify that rbenv is installed correctly, run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;type rbenv&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This should return a path indicating that rbenv is set up. If it does, you're ready to start managing Ruby versions with rbenv.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install the Desired Ruby Version
&lt;/h3&gt;

&lt;p&gt;Now, list all available Ruby versions:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rbenv install --list-all&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will display a long list of Ruby versions. Choose the one you need (e.g., 3.3.3) and install it:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rbenv install 3.3.3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command downloads, compiles, and installs the specified Ruby version on your system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set the Ruby Version Globally
&lt;/h3&gt;

&lt;p&gt;To set this newly installed Ruby version as the global default, run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rbenv global 3.3.3&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify the Ruby Version
&lt;/h3&gt;

&lt;p&gt;Finally, let's check that the correct Ruby version is now active:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ruby -v&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You should see the updated version:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;output: ruby 3.3.3p20 (2022-04-12 revision 4491bb740a) [arm64-darwin23]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And that's it! You have successfully updated Ruby on your macOS system using rbenv. Whenever you need to switch to a different Ruby version in the future, simply run &lt;code&gt;rbenv install --list-all&lt;/code&gt; to view the available versions and install the one you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional rbenv Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local Versions:&lt;/strong&gt; If you need a different Ruby version for a specific project, you can set a local Ruby version by navigating to the project directory and running:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;rbenv local 2.7.6&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will create a .ruby-version file in the project directory that tells rbenv to use the specified version of Ruby whenever you're working in that directory.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rehashing:&lt;/strong&gt; After installing a new Ruby version or a gem with executables, run:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;rbenv rehash&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This updates rbenv's shims, making the new commands available in your shell.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Uninstalling Ruby Versions:&lt;/strong&gt; If you ever need to remove a Ruby version, simply run:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;rbenv uninstall 2.6.10&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;With rbenv, managing multiple Ruby versions becomes simple and straightforward, making it an essential tool for any Ruby developer!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rbenv</category>
      <category>devtools</category>
      <category>rails</category>
    </item>
    <item>
      <title>Run PHPUnit locally in your WordPress Plugin with DDEV</title>
      <dc:creator>Sarah Siqueira</dc:creator>
      <pubDate>Thu, 27 Jun 2024 17:16:49 +0000</pubDate>
      <link>https://forem.com/sarahcssiqueira/run-phpunit-locally-in-your-wordpress-plugin-with-ddev-2b3o</link>
      <guid>https://forem.com/sarahcssiqueira/run-phpunit-locally-in-your-wordpress-plugin-with-ddev-2b3o</guid>
      <description>&lt;p&gt;While working with WordPress over the years, I have used multiple solutions for local developments, ranging from old XAMPP setups and transferring files with FTP on FileZilla to Docker custom environments. By the way, here is an &lt;a href="https://github.com/sarahcssiqueira/docker-wordpress" rel="noopener noreferrer"&gt;example of one of my Dockers&lt;/a&gt; you can refer. &lt;/p&gt;

&lt;p&gt;Recently, I discovered DDEV. &lt;a href="https://ddev.com/" rel="noopener noreferrer"&gt;DDEV&lt;/a&gt; is an open source tool for launching local web development environments that can be extended, version controlled, and shared across a team easily. With DDEV, we can &lt;strong&gt;take advantage of a Docker workflow without Docker experience&lt;/strong&gt;. Cool right? Of course, it is important to know how docker works under the hood, and beginners should experiment with it. However, later on, why to reinvent the wheel? Give DDEV a chance, and you won't regret it.&lt;/p&gt;

&lt;p&gt;Okay, I am digressing; the focus here is &lt;a href="https://phpunit.de/index.html" rel="noopener noreferrer"&gt;PHPUnit&lt;/a&gt; for plugins. &lt;strong&gt;As with many of my other articles, my goal is to create a reference for myself to use when I need it in the future.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Given my &lt;a href="https://ddev.com/" rel="noopener noreferrer"&gt;DDEV&lt;/a&gt; environment running, I also want to run tests locally in my projects, in this case a &lt;strong&gt;WordPress plugin&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DDEV&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;PHP 8.3&lt;/li&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;SVN&lt;/li&gt;
&lt;li&gt;git&lt;/li&gt;
&lt;li&gt;WP-CLI&lt;/li&gt;
&lt;li&gt;wget&lt;/li&gt;
&lt;li&gt;plugin-folder&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The versions for &lt;strong&gt;PHP, PHPUnit and PHP Code Coverage&lt;/strong&gt; I am using, were the compatible ones on the date I am writing this post, June 2024. To check compatibility with PHPUnit and PHP, &lt;a href="https://phpunit.de/supported-versions.html" rel="noopener noreferrer"&gt;please refer to official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First step is to install PHPUnit if it is not installed yet. There are multiple ways to do this, but I choose to do it per project, through Composer with the following command in the plugin root folder:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;composer require --dev phpunit/phpunit ^9.5&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Also, will need those dependencies:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;composer require --dev phpunit/php-code-coverage ^9.2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Remembering proper unit tests for a plugin or theme would not load WordPress. By loading WordPress those will be integration tests. &lt;/p&gt;

&lt;p&gt;That said, to generate the plugin test files, run on your plugin root folder:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ddev exec wp scaffold plugin-tests your-plugin-name&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;While working in a DDEV environment, don't forget to use &lt;strong&gt;ddev exec&lt;/strong&gt; before &lt;strong&gt;wp cli&lt;/strong&gt; commands.&lt;/p&gt;

&lt;p&gt;Next, run the install script (which will require &lt;strong&gt;wget&lt;/strong&gt;):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;bash bin/install-wp-tests.sh wordpress_test root '' localhost latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The script above first installs a copy of WordPress in the /tmp directory (by default) as well as the WordPress unit testing tools. Then it creates a database to be used while running tests. More details &lt;a href="https://make.wordpress.org/cli/handbook/misc/plugin-unit-tests/#2-generate-the-plugin-test-files" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Error: The PHPUnit Polyfills library is a requirement for running the WP test suite.&lt;br&gt;
If you are trying to run plugin/theme integration tests, make sure the PHPUnit Polyfills library (&lt;a href="https://github.com/Yoast/PHPUnit-Polyfills" rel="noopener noreferrer"&gt;https://github.com/Yoast/PHPUnit-Polyfills&lt;/a&gt;) is available and either load the autoload file of this library in your own test bootstrap before calling the WP Core test bootstrap file; or set the absolute path to the PHPUnit Polyfills library in a "WP_TESTS_PHPUNIT_POLYFILLS_PATH" constant to allow the WP Core bootstrap to load the Polyfills.&lt;br&gt;
If you are trying to run the WP Core tests, make sure to set the "WP_RUN_CORE_TESTS" constant to 1 and run &lt;code&gt;composer update -W&lt;/code&gt; before running the tests.&lt;br&gt;
Once the dependencies are installed, you can run the tests using the Composer-installed version of PHPUnit or using a PHPUnit phar file, but the dependencies do need to be installed whichever way the tests are run.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To fix the error above, install:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;composer require --dev yoast/phpunit-polyfills *&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Edit the &lt;strong&gt;./tests/bootstrap.php&lt;/strong&gt; file created with the previous scaffold step, in order to require this file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;require dirname( dirname( __FILE__ ) ) . '/vendor/yoast/phpunit-polyfills/phpunitpolyfills-autoload.php';&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start to write your tests!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run tests by using &lt;code&gt;./vendor/bin/phpunit filename&lt;/code&gt; or register a Composer script, as I did: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;"scripts": {&lt;br&gt;
    "test": "vendor/bin/phpunit"&lt;br&gt;
  },&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, I can simply run &lt;code&gt;composer test filename&lt;/code&gt; and that's it!&lt;/p&gt;

</description>
      <category>phpunit</category>
      <category>wordpress</category>
      <category>ddev</category>
      <category>unittests</category>
    </item>
    <item>
      <title>My WordPress learning journey, so far...</title>
      <dc:creator>Sarah Siqueira</dc:creator>
      <pubDate>Mon, 06 May 2024 23:11:30 +0000</pubDate>
      <link>https://forem.com/sarahcssiqueira/my-wordpress-learning-journey-so-far-2223</link>
      <guid>https://forem.com/sarahcssiqueira/my-wordpress-learning-journey-so-far-2223</guid>
      <description>&lt;p&gt;I started to work with &lt;strong&gt;WordPress back in 2015&lt;/strong&gt;, while in physics college, just to get some money. At first, as a freelancer, I was just a plugin/theme installer by saying so, with &lt;strong&gt;no clue about how things worked under the hood&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Over time, I needed to understand how WordPress plugins and themes were hosted, which led me to learn about host companies and set DNS domains, and tasks using CPanel. Later on, I had to work with VPS, hosted by companies like Digital Ocean and AWS. Also, that's how I learned to work with Apache, NGINX, and Linux servers back in 2016.&lt;/p&gt;

&lt;h2&gt;
  
  
  WordPress under the hood
&lt;/h2&gt;

&lt;p&gt;Ok, after working on tasks setting up all DNS domains, installing WordPress, connecting with the database, choosing a theme, and installing plugins for clients' projects, I came to the question: How do those themes and plugins interact with those bunch of WordPress core files downloaded from WordPress.org? To understand that, one of the things I had to learn was PHP, which started in 2016. With PHP knowledge I was able to actually understand WordPress - even wrote an article about that: &lt;a href="https://dev.to/sarahcssiqueira/the-wordpress-request-lifecycle-45ie"&gt;WordPress under the Hood&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  WordPress themes
&lt;/h2&gt;

&lt;p&gt;Despite the amazing &lt;a href="https://wordpress.org/themes/" rel="noopener noreferrer"&gt;themes available for download&lt;/a&gt; on WordPress.org, I needed to make websites look beautiful to the client's eyes, and sometimes the projects needed further customizations. That led me to research, learn, and work with WordPress themes. Initially, I learned how to create WordPress child themes, and later on, finally learned to create my own themes - something I am still learning to be honest.&lt;/p&gt;

&lt;p&gt;Here are two open-source themes I worked on, you can see &lt;a href="https://github.com/sarahcssiqueira/purpleish-theme" rel="noopener noreferrer"&gt;here &lt;/a&gt; and &lt;a href="https://github.com/sarahcssiqueira/base-wp-theme" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
In the process of creating a WordPress theme, I needed to handle the frontend part, which led me to dive, among other things, into CSS and JavaScript about 6 years ago, in 2017.&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS
&lt;/h2&gt;

&lt;p&gt;CSS can be very tricky if we underestimate it. If you work alone on a project and everything is still fresh in your head, it's easy to maintain, but after some time, if you don't structure things well, it becomes a nightmare to maintain.&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%2Fc4z7yzexc84gykp2810n.jpg" 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%2Fc4z7yzexc84gykp2810n.jpg" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you jump into a project with distributed teams, you must find ways to organize things. After that conclusion, one of the things I started to learn was SCSS, which proved to be great for my needs and my chosen option nowadays. However, compiling all the files took SCSS a lot much time. To increase productivity and get rid of this manual task, I learned Gulp. &lt;br&gt;
Somehow I read that Weppack was more complete but had a bigger learning curve, well, I am not afraid to research, so I learned Webpack, my way to go nowadays.&lt;/p&gt;

&lt;p&gt;Here is a &lt;a href="https://gist.github.com/sarahcssiqueira/67cdfa82fd3f310719e7f076010ae13b" rel="noopener noreferrer"&gt;Webpack sample I developed to work in a WordPress&lt;/a&gt; theme.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript
&lt;/h2&gt;

&lt;p&gt;JavaScript was also required to create mobile menus and carousels for example. The same problem with CSS arose in JavaScript: compiling and minifying those files used to take so long, here is where Webpack shows up again and is very handy.&lt;br&gt;
Again, &lt;a href="https://gist.github.com/sarahcssiqueira/67cdfa82fd3f310719e7f076010ae13b" rel="noopener noreferrer"&gt;my webpack configuration file&lt;/a&gt; is here.&lt;br&gt;
Of course, JavaScript is not used only for that, there are a million possible uses, and that's why something I keep learning and searching (and will do forever).&lt;/p&gt;

&lt;h2&gt;
  
  
  E-commerce
&lt;/h2&gt;

&lt;p&gt;In 2018, after this journey as a freelancer, I started an e-commerce of pet supplies. The project was and still is based on WordPress and Woo (former WooCommerce). During this time, I faced lots of challenges being the most experienced IT person in the room at some points.&lt;br&gt;
On the e-commerce, aspect, Woo has several amazing plugins to enhance an e-commerce project, but paying for them was not an option back then. At that point, among other tasks, I started to learn how to build plugins.&lt;/p&gt;

&lt;h2&gt;
  
  
  WordPress plugins
&lt;/h2&gt;

&lt;p&gt;Due to our tiny budget, I had to create our own plugins, like this to customize order status or this other one to create custom post types.&lt;/p&gt;

&lt;h2&gt;
  
  
  MySQL
&lt;/h2&gt;

&lt;p&gt;What tells about databases? Last year, I worked in server migration, from AWS to Digital Ocean LAMP server, migrating all tables of a WordPress/Woo project, handling errors with data formats, and primary keys, cleaning data that was not needed anymore, optimizing, changing the collation for InnoDB. &lt;br&gt;
I like to use &lt;strong&gt;PhpMyAdmin&lt;/strong&gt; as a tool to handle those MySQL-related tasks. &lt;/p&gt;

&lt;h2&gt;
  
  
  Coding Standards
&lt;/h2&gt;

&lt;p&gt;There are multiple ways to solve the same problem, also we can organize files differently, but in the open-source world, using standards makes it easier to share your work with others.&lt;br&gt;
Today, I use Composer to manage PHP_CodeSniffer rules like WordPress Coding Standards. &lt;a href="https://dev.to/sarahcssiqueira/setting-wordpress-coding-standards-per-project-using-composer-g46"&gt;I wrote an article about how to set up it correctly&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As a project grows, everyone involved must speak the same language, it will make things way easier and will help with productivity.&lt;/p&gt;

&lt;h2&gt;
  
  
  React and Next
&lt;/h2&gt;

&lt;p&gt;Yes, I had to learn React to work with WordPress, but that's a subject for another post, I think.&lt;/p&gt;

&lt;h2&gt;
  
  
  DevOps
&lt;/h2&gt;

&lt;p&gt;In the WordPress context, deployment is basically synchronizing plugins and theme files to the respective paths.&lt;/p&gt;

&lt;p&gt;I used the old approach, syncing files through FTP - which is not a very productive approach let's be honest - so I started to use automation like GitHub actions for CI/CD. &lt;/p&gt;

&lt;p&gt;In this repository, I share some &lt;a href="https://github.com/sarahcssiqueira/reusable-wp-workflows" rel="noopener noreferrer"&gt;workflow samples&lt;/a&gt; to deploy WordPress projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  My next steps
&lt;/h2&gt;

&lt;p&gt;Right now, in my learning journey, I am focusing on exploring advanced WordPress aspects like Gutenberg Blocks and Block Themes. Also trying to improve my writing test skills with PHPUnit.&lt;/p&gt;

&lt;p&gt;Through the years, I got the ability to see the bigger picture. And if got stuck on some problem I don't know exactly how to solve, I am not afraid to jump in and acquire the needed missing skill. That's my learning approach, sometimes I get lost banging my head against the wall, but when I finally get why something is happening, that's my friends is the funny part of this work.&lt;/p&gt;

&lt;p&gt;And you? What about your learning journey? Any suggestions about something I need to learn/explore?&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>careerdevelopment</category>
      <category>learning</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Syncing a Spreadsheet with Google Calendar using Google Scripts to be (or at least try) more productive</title>
      <dc:creator>Sarah Siqueira</dc:creator>
      <pubDate>Sat, 04 Nov 2023 17:53:35 +0000</pubDate>
      <link>https://forem.com/sarahcssiqueira/syncing-a-spreadsheet-with-google-calendar-using-google-scripts-to-be-or-at-least-try-more-productive-18cc</link>
      <guid>https://forem.com/sarahcssiqueira/syncing-a-spreadsheet-with-google-calendar-using-google-scripts-to-be-or-at-least-try-more-productive-18cc</guid>
      <description>&lt;p&gt;Remote working requires discipline, that's a fact. And I must admit I have this problem of lack of focus, I am curious and easily get bored, I am always tempted to start a new project because of some random article I read. &lt;strong&gt;That's something I have been fighting against since&lt;/strong&gt; I was 17 years old in my first job in an accountant's office. For a long time, &lt;strong&gt;I was told that was my weakness.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Later, at some point I became a developer and &lt;strong&gt;realized this curiosity and eagerness to learn something new could also be my biggest strength&lt;/strong&gt;, as long I could be able to not get lost in my random ideas.&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%2Fx9zsw3w97mkqwn4djib3.jpg" 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%2Fx9zsw3w97mkqwn4djib3.jpg" alt=" " width="618" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I tried to find tools to help me be more productive and there are lots of books about that, tutorials, coaches' lectures, etc. I tried several approaches through the years but guess what? Furthermore, I didn't was able to use any fancy tool with consistency, no matter how awesome were the tools.&lt;/p&gt;

&lt;p&gt;After trying dozens, and hundreds of productivity tools I realized the one that would work for me was that I would be able to follow with consistency, and turns out the obvious answer was right in front of my eyes: Excel.&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%2Fiw63vd3sbbe49xy2u09t.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%2Fiw63vd3sbbe49xy2u09t.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Microsoft Excel&lt;/strong&gt; doesn't require a presentation, and I know it can seem boring for developers, but it is a tool I always liked and learned to use in my account work times. Well, I do not know how to do those insane things the guys from the financial market do, but I can do one thing or another. It also was a tool I used with some consistency for making notes and even for controlling my finances.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Why does not apply to control my dev working routine? And what about if I could share it with my team? That would be perfect.&lt;br&gt;
Okay, new awesome project idea. How could I do that?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As a Google products fan, I moved to Google Spreadsheets and started to register my work planning and any new project idea in a Spreadsheet, similar to &lt;a href="https://docs.google.com/spreadsheets/d/1SO8Ealz15EUsJdb51sZYLiMsokyFSk0OQNZXXusKyvU/edit?usp=sharing" rel="noopener noreferrer"&gt;this one here&lt;/a&gt;. I was also using Google Calendar to schedule meetings, etc., so &lt;strong&gt;why not synchronize everything&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After some googling&lt;/strong&gt;, I discovered some product add-ons available, but none of them seemed right for my needs. Then, a few more googling to &lt;strong&gt;discover how those product add-ons for Google Workspace were made&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;I discovered &lt;a href="https://www.google.com/script/start/" rel="noopener noreferrer"&gt;Google Apps Scripts&lt;/a&gt;, and now we finally reach the main point of this post: &lt;strong&gt;to share how we can synchronize a Google Spreadsheet with a Google Calendar using Google App Scripts.&lt;/strong&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%2Fvpcltnznbhr1kxi2397c.jpg" 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%2Fvpcltnznbhr1kxi2397c.jpg" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Google Account&lt;/li&gt;
&lt;li&gt;Some JavaScript Knowledge&lt;/li&gt;
&lt;li&gt;Google Spreadsheets and Google Calendar familiarity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because we are going to handle data formats, we need to be careful with the spreadsheet to avoid errors. That's a &lt;a href="https://docs.google.com/spreadsheets/d/1SO8Ealz15EUsJdb51sZYLiMsokyFSk0OQNZXXusKyvU/edit?usp=sharing" rel="noopener noreferrer"&gt;sample of my current spreadsheet&lt;/a&gt; already correctly formatted to work with the following script.&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%2Fkq0ychbs49e6yge53rom.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%2Fkq0ychbs49e6yge53rom.png" alt=" " width="800" height="257"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1 - Log in your Google Account
&lt;/h3&gt;

&lt;p&gt;After login to your Google Account, at your spreadsheet menu, go to the tab &lt;strong&gt;Extensions &amp;gt; Apps Script&lt;/strong&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%2Fyty4dez4bu54vnlffspi.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%2Fyty4dez4bu54vnlffspi.png" alt=" " width="751" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on it, and now you are in the &lt;strong&gt;Google Apps Script&lt;/strong&gt; editor:&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%2Fbk6cle94yjqav8bg8dzc.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%2Fbk6cle94yjqav8bg8dzc.png" alt=" " width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.google.com/script/start/" rel="noopener noreferrer"&gt;Google Apps Script Editor&lt;/a&gt; is a web-based integrated development environment (IDE) provided by Google for creating, editing, and deploying custom scripts and automation solutions for various &lt;strong&gt;Google Workspace (formerly G Suite)&lt;/strong&gt; applications. It allows users to write code in JavaScript to extend the functionality of Google Apps, automate tasks, and build custom applications within the Google ecosystem.&lt;/p&gt;

&lt;p&gt;Give a name to your project, I called mine &lt;strong&gt;Sheet &amp;amp; Calendar Synchronizer&lt;/strong&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%2F7bb1enmqsu5fu00d2jut.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%2F7bb1enmqsu5fu00d2jut.png" alt=" " width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2 - Write the code
&lt;/h3&gt;

&lt;p&gt;In the web-based IDE, paste the following codes, and make sure to make the proper replacements.&lt;/p&gt;
&lt;h4&gt;
  
  
  To create or update events
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function createorUpdateEvents() {

  /*
  * Open the Calendar
  */
  const calendarId = 'YOUR CALENDAR ID';
  const sheet = SpreadsheetApp.getActiveSheet();

  /*
  * Import events data from the spreadsheet
  */
  const events = sheet.getRange("A2:G1000").getValues();

  /*
  * Event details for creating an event
  */

  let event; // Declare event variable outside the loop

  for ( i = 0; i &amp;lt; events.length; i++ ) {
    const shift = events[i];
    const eventID = shift[0];
    const eventsubject = shift[1];
    const startTime = shift[2];
    const endTime = shift[3];
    const description = shift[4];
    const color = shift[5];


     // Check if all variables are defined
      if (
        eventID !== undefined &amp;amp;&amp;amp; 
        eventsubject !== undefined &amp;amp;&amp;amp; 
        description !== undefined &amp;amp;&amp;amp; 
        color !== undefined &amp;amp;&amp;amp; 
        startTime instanceof Date &amp;amp;&amp;amp; 
        endTime instanceof Date
        ) {
        const event = {
            id: eventID,
            summary: eventsubject,
            description: description,
            'start': {
                'dateTime': startTime.toISOString(),
                'timeZone': 'America/Sao_Paulo'
            },
            'end': {
                'dateTime': endTime.toISOString(),
                'timeZone': 'America/Sao_Paulo'
            },
            colorId: color
        };

        /** 
        * Insert or update event
        **/
       try {
        let createOrUpdate;
        if (event.id) {
          createOrUpdate = Calendar.Events.update(event, calendarId, eventID);
        } else {
          createOrUpdate = Calendar.Events.insert(event, calendarId);
        }
      } catch (e) {
        if (e.message &amp;amp;&amp;amp; e.message.indexOf("Not Found") !== -1) {
          createOrUpdate = Calendar.Events.insert(event, calendarId);
        } else {
          console.error("Error:", e);
        }
      }
    }
  }
}

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

&lt;/div&gt;


&lt;p&gt;Replace &lt;code&gt;'YOUR CALENDAR ID'&lt;/code&gt; with your &lt;strong&gt;Google Calendar ID&lt;/strong&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  To get events from Calendar to Sheet
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function exportCalendarEventsToSheet() {

  const calendarId = 'YOUR CALENDAR ID';
  const startDate = new Date('2023-01-01');
  const endDate = new Date('2023-12-31');
  const calendar = CalendarApp.getCalendarById(calendarId);
  const sheet = SpreadsheetApp.getActiveSheet();
  const events = calendar.getEvents(startDate, endDate);
  const data = [];


  if (events.length &amp;gt; 0) {
    for (let i = 0; i &amp;lt; events.length; i++) {
      const event = events[i];
      const eventID = event.getId().split('@')[0];
      const eventTitle = event.getTitle();
      const startTime = event.getStartTime();
      const endTime = event.getEndTime();
      const description = event.getDescription();
      const color = event.getColor();

      data.push([eventID, eventTitle, startTime, endTime, description, color]);
    }

    const numRows = data.length;
    const numCols = data[0].length;
    sheet.getRange(2, 1, numRows, numCols).setValues(data);
  } else {
    console.log('No events exist for the specified range');
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Step 3 - Add services
&lt;/h3&gt;

&lt;p&gt;In the left panel, add the services Google Calendar API and Google Sheets API&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%2Fswrmd5hb92kbw9lpflg1.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%2Fswrmd5hb92kbw9lpflg1.png" alt=" " width="325" height="401"&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%2Fg5zka5chozz5zfh0ouy6.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%2Fg5zka5chozz5zfh0ouy6.png" alt=" " width="543" height="615"&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%2F266vancrcu94qjysyfq2.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%2F266vancrcu94qjysyfq2.png" alt=" " width="561" height="605"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 4 - Run the code
&lt;/h3&gt;

&lt;p&gt;You need to run the scripts, you can do that by clicking on run in the web-based IDE every time you need.&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%2Fkagaaul8rldwj9rww844.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%2Fkagaaul8rldwj9rww844.png" alt=" " width="800" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, that is not practical for daily basis use. So we will need a few more codes to create a menu that will allow us to run the code directly through the Google spreadsheets menu.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 5 - The Menu Code
&lt;/h3&gt;

&lt;p&gt;In the editor, place the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('Sync Data with Calendar')
    .addItem('Calendar to Sheet', 'exportCalendarEventsToSheet')
    .addItem('Sheet to Calendar', 'createorUpdateEvents')
    .addSeparator()
    .addSubMenu(
      ui.createMenu('About')
        .addItem('Documentation', 'showDocumentation')
    )
    .addToUi();
}

function showDocumentation() {
  var htmlOutput = HtmlService.createHtmlOutput('&amp;lt;p&amp;gt;For more info, visit &amp;lt;a href="https://github.com/sarahcssiqueira/google-sheets-calendar-synchronizer" target="_blank"&amp;gt;this link&amp;lt;/a&amp;gt;.');
  var ui = SpreadsheetApp.getUi();
  ui.showModalDialog(htmlOutput, 'Documentation');
}

function closeDialog() {
  google.script.host.close();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a menu like the one in the image, and you will be able to execute the scripts directly from the spreadsheet menu.&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%2F4dww9f2h56ryoviji9zb.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%2F4dww9f2h56ryoviji9zb.png" alt=" " width="387" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6 - Give permissions
&lt;/h3&gt;

&lt;p&gt;The first time you try to use the project by clicking on the menu button, you may be asked to give permission. Allow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Create the spreadsheet where you intend to save your events and actually list your events, following this format.&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%2Fxllx1aps18pl59veax8o.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%2Fxllx1aps18pl59veax8o.png" alt=" " width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you hit the Sheet to Calendar button, it will create or updates all events listed in the spreadsheet in the Google Calendar you choose.&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%2Fpcopksnjcaiu8968pg6v.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%2Fpcopksnjcaiu8968pg6v.png" alt=" " width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also drag and drop your events on Calendar, and by hitting the &lt;strong&gt;Calendar to Sheet&lt;/strong&gt; button, these changes will be reflected in the spreadsheet.&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%2F8fnelmdyt1iix6ifn4jk.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%2F8fnelmdyt1iix6ifn4jk.png" alt=" " width="513" height="449"&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%2F35x71fo37amgh2j7j1fb.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%2F35x71fo37amgh2j7j1fb.png" alt=" " width="800" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  About the event's colors
&lt;/h2&gt;

&lt;p&gt;There are eleven colors available we can use, those colors should be listed in the color column or selected in the Calendar. More &lt;a href="https://developers.google.com/apps-script/reference/calendar/event-color?hl=pt-br" rel="noopener noreferrer"&gt;info here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This code was written for personal use, so certainly there are room for improvement. Feel free to improve giving your suggestions in the comments below or even through PR in &lt;a href="https://github.com/sarahcssiqueira/google-sheets-calendar-synchronizer" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. If it was useful for you, please consider leaving a star in the &lt;a href="https://github.com/sarahcssiqueira/google-sheets-calendar-synchronizer" rel="noopener noreferrer"&gt;repository&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://workspace.google.com/blog/productivity-collaboration/g-suite-pro-tip-how-to-automatically-add-a-schedule-from-google-sheets-into-calendar" rel="noopener noreferrer"&gt;G Suite Pro Tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/apps-script/reference/calendar/calendar?hl=pt-br#createAllDayEvent(String,Date,Object)" rel="noopener noreferrer"&gt;Class Calendar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=FxxPq2wXcK4" rel="noopener noreferrer"&gt;Google Sheets - Use Apps Script to Create Google Calendar Events Automatically&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/apps-script/reference/calendar/event-color?hl=pt-br" rel="noopener noreferrer"&gt;Custom Colors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/apps-script/guides/menus?hl=pt-br" rel="noopener noreferrer"&gt;Custom Menus&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>productivity</category>
      <category>google</category>
      <category>spreadsheets</category>
      <category>calendar</category>
    </item>
    <item>
      <title>Automatically deploying WordPress plugins and/or themes with GitHub actions</title>
      <dc:creator>Sarah Siqueira</dc:creator>
      <pubDate>Tue, 24 Oct 2023 21:29:47 +0000</pubDate>
      <link>https://forem.com/sarahcssiqueira/automatically-deploying-wordpress-plugins-andor-themes-with-github-actions-4m4n</link>
      <guid>https://forem.com/sarahcssiqueira/automatically-deploying-wordpress-plugins-andor-themes-with-github-actions-4m4n</guid>
      <description>&lt;p&gt;There are a lot of ways in which a WordPress GitHub integration can be helpful in &lt;strong&gt;WordPress development&lt;/strong&gt; and project collaboration. One of them is in deploy routines with automatic deployments, instead of the &lt;em&gt;cowboy coding approach&lt;/em&gt;, using FTP, manually grabbing our themes and/or plugin files, and uploading them manually using software like &lt;a href="https://filezilla-project.org/" rel="noopener noreferrer"&gt;FileZilla&lt;/a&gt;, we can deploy directly from GitHub to our live WordPress site.&lt;/p&gt;

&lt;p&gt;That's why I wrote this post and, as always, to record what I did for when I forget it in a few months from now.&lt;/p&gt;

&lt;p&gt;We will review &lt;strong&gt;how to set up a WordPress GitHub integration&lt;/strong&gt; to manage the deployment of our WordPress themes and WordPress plugins, which can save us a lot of time and is especially important if we are using custom themes and plugins.&lt;/p&gt;

&lt;p&gt;We will not cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The WordPress Core:&lt;/strong&gt; Well, we should never edit core WordPress files, so it doesn't make sense to include the core files in our repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The database:&lt;/strong&gt; Trying to version control the WordPress database &lt;strong&gt;opens up a can of worms&lt;/strong&gt; and we will not open that now.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;WordPress development of plugins and themes:&lt;/strong&gt; I am assuming you have this done, ready to deploy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get started with the sample workflows we will gonna use to synchronize our WordPress themes and plugins!&lt;/p&gt;

&lt;h1&gt;
  
  
  Deploying a WordPress Theme
&lt;/h1&gt;

&lt;p&gt;The following .yml code is used to synchronize the theme files you coded, with the &lt;strong&gt;/wp-content/themes&lt;/strong&gt; folder in your server. For a LAMP server hosted in a company like Digital Ocean, that's a sample workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Deploy Theme

on:
  push:
    branches: [master]

env:
  SSH_USER: ${{ secrets.SSH_USER }}
  SSH_HOST: ${{ secrets.SSH_HOST }}

jobs:
  deploy:
    name: Deploy WordPress Theme on Digital Ocean
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Set SSH Connection
        run: |
          mkdir -p ~/.ssh/
          echo "$SSH_KEY" &amp;gt; ~/.ssh/deploy.key
          chmod 600 ~/.ssh/deploy.key
          cat &amp;gt;&amp;gt;~/.ssh/config &amp;lt;&amp;lt;END
          Host digitalocean
            HostName $SSH_HOST
            User $SSH_USER
            IdentityFile ~/.ssh/deploy.key
            StrictHostKeyChecking no
          END
        env:
          SSH_KEY: ${{ secrets.DEPLOY_KEY }}

      - name: Sync theme files
        run: "rsync --delete -avO
          --exclude /deploy_key \
          --exclude /.git/ \
          --exclude /.github/ \
          ./ ${{ env.SSH_USER }}@${{ env.SSH_HOST }}:${{ env.DEST }}"
        env:
          SSH_HOST: digitalocean
          # That's the most commom path in a WordPress instalation on a LAMP stack,
          # but you can change the destination according to your needs.
          DEST: "/var/www/your-domain/wp-content/themes/theme-folder"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Workflow name
&lt;/h3&gt;

&lt;p&gt;In the first line we have the workflow name &lt;code&gt;name: Deploy Theme&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Workflow triggers
&lt;/h3&gt;

&lt;p&gt;Later, we have the trigger definition, in this case, whenever I push a commit to the master branch on the repository with my WordPress theme, the workflow will be triggered. You can custom that, for more details, you can refer to GitHub documentation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;on:
  push:
    branches: [master]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Secrets
&lt;/h3&gt;

&lt;p&gt;I create variables for the custom secrets. More info &lt;a href="https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#creating-encrypted-secrets-for-a-repository" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env:
  SSH_USER: ${{ secrets.SSH_USER }}
  SSH_HOST: ${{ secrets.SSH_HOST }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Jobs
&lt;/h3&gt;

&lt;p&gt;The jobs section in a GitHub Actions workflow file defines one or more jobs to be executed when a workflow is triggered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jobs:
  deploy:
    name: Deploy WordPress Theme on Digital Ocean
    runs-on: ubuntu-latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;deploy&lt;/strong&gt; is the name of the job, which can be customized to describe the job's purpose.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;name&lt;/strong&gt; is an optional field we use to making it more understandable when viewing the workflow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;runs-on&lt;/strong&gt; specifies the type of virtual environment or runner on which the job will be executed. In this case, it uses the ubuntu-latest runner, indicating that the job runs on the latest available version of the Ubuntu operating system.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Steps
&lt;/h3&gt;

&lt;p&gt;The steps section in a GitHub Actions workflow file defines a series of individual tasks that are executed as part of a job.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;steps:
      - name: Checkout
        uses: actions/checkout@v2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;steps:&lt;/strong&gt; contains a list of actions to be executed in the specified order. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;name&lt;/strong&gt;: is an optional field we use to making it more understandable when viewing the workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;uses:&lt;/strong&gt; Specifies the action to be performed. In this example, the &lt;strong&gt;actions/checkout@v2&lt;/strong&gt; action is used to check out the source code repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Setting SSH Conection
&lt;/h4&gt;

&lt;p&gt;This is the section of your workflow responsible to sets up an SSH connection for secure access to our remote host.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Set SSH Connection
        run: |
          mkdir -p ~/.ssh/
          echo "$SSH_KEY" &amp;gt; ~/.ssh/deploy.key
          chmod 600 ~/.ssh/deploy.key
          cat &amp;gt;&amp;gt;~/.ssh/config &amp;lt;&amp;lt;END
          Host digitalocean
            HostName $SSH_HOST
            User $SSH_USER
            IdentityFile ~/.ssh/deploy.key
            StrictHostKeyChecking no
          END
        env:
          SSH_KEY: ${{ secrets.DEPLOY_KEY }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;- name:&lt;/strong&gt; as in the previous parts, it's a optional field making it more understandable for us, ins this case we will see: Set SSH Connection.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;run&lt;/strong&gt; defines the steps or shell commands to execute. In this case:

&lt;ul&gt;
&lt;li&gt;Creates the ~/.ssh/ directory if it doesn't already exist.&lt;/li&gt;
&lt;li&gt;Writes the SSH key, stored in the SSH_KEY environment variable, to ~/.ssh/deploy.key.&lt;/li&gt;
&lt;li&gt;Sets the permissions of ~/.ssh/deploy.key to ensure it's only accessible by the user.&lt;/li&gt;
&lt;li&gt;Appends SSH configuration to ~/.ssh/config, including the hostname, username, and path to the SSH key. &lt;/li&gt;
&lt;li&gt;Additionally, it disables strict host key checking for the "digitalocean" host.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;env&lt;/strong&gt; section specifies environment variables used in the workflow, in this case, it defines the SSH_KEY variable and retrieves its value from a GitHub secret (DEPLOY_KEY).&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  Syncing the theme files:
&lt;/h4&gt;

&lt;p&gt;This syncing section is responsible for syncing theme files to the remote server using the &lt;strong&gt;rsync command&lt;/strong&gt;. In some hosts, may be necessaire to &lt;a href="https://serverspace.io/support/help/use-rsync-to-create-a-backup-on-ubuntu/" rel="noopener noreferrer"&gt;install manually rsync&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  - name: Sync theme files
        run: "rsync --delete -avO
          --exclude /deploy_key \
          --exclude /.git/ \
          --exclude /.github/ \
          ./ ${{ env.SSH_USER }}@${{ env.SSH_HOST }}:${{ env.DEST }}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rsync command performs the following tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;--delete: Ensures that files deleted locally are also deleted on the remote server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;-avO: Sets rsync options for archive mode, verbose output, and optimization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;--exclude: Specifies which files or directories to exclude from the synchronization. In this example, it excludes the /deploy_key, /.git/, and /.github/ folders, but you can customize according to your project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;./: Specifies the source directory to sync from, which is the current directory of the workflow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;${{ env.SSH_USER }}@${{ env.SSH_HOST }}:${{ env.DEST }}:&lt;/code&gt;Specifies the destination for the synchronization. It uses environment variables for the SSH username, host, and destination path.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  The var definition
&lt;/h4&gt;

&lt;p&gt;In this section there are some other environment variables that are used within the workflow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; env:
          SSH_HOST: digitalocean
          # That's the most commom path in a WordPress instalation on a LAMP stack,
          # but you can change the destination according to your needs.
          DEST: "/var/www/your-domain/wp-content/themes/theme-folder"

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Deploying a WordPress Plugin
&lt;/h1&gt;

&lt;p&gt;To deploy a plugin, you can follow the same idea above, just changing the deploy path to &lt;code&gt;/var/www/your-domain/wp-content/plugins/plugin-folder&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The sample workflow below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
name: Deploy Plugin

on:
  push:
    branches: [master]

env:
  SSH_USER: ${{ secrets.SSH_USER }}
  SSH_HOST: ${{ secrets.SSH_HOST }}

jobs:
  deploy:
    name: Deploy WordPress Plugin on Digital Ocean
    runs-on: ubuntu-20.04

    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Set SSH Connection
        run: |
          mkdir -p ~/.ssh/
          echo "$SSH_KEY" &amp;gt; ~/.ssh/deploy.key
          chmod 600 ~/.ssh/deploy.key
          cat &amp;gt;&amp;gt;~/.ssh/config &amp;lt;&amp;lt;END
          Host digitalocean
            HostName $SSH_HOST
            User $SSH_USER
            IdentityFile ~/.ssh/deploy.key
            StrictHostKeyChecking no
          END
        env:
          SSH_KEY: ${{ secrets.DEPLOY_KEY }}

      - name: Sync plugin files
        run: "rsync --delete -avO
          --exclude /deploy_key \
          --exclude /.git/ \
          --exclude /.github/ \
          ./ ${{ env.SSH_USER }}@${{ env.SSH_HOST }}:${{ env.DEST }}"
        env:
          SSH_HOST: digitalocean
          # That's the most commom path in a WordPress instalation on a LAMP stack,
          # but you can change the destination according to your needs.
          DEST: "/var/www/your-domain/wp-content/plugins/plugin-folder"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's my repository with some &lt;a href="https://github.com/sarahcssiqueira/reusable-wp-workflows" rel="noopener noreferrer"&gt;sample workflows customized&lt;/a&gt; for different servers. Be free to &lt;strong&gt;&lt;a href="https://github.com/sarahcssiqueira/reusable-wp-workflows" rel="noopener noreferrer"&gt;contribute through pull requests&lt;/a&gt;&lt;/strong&gt; adding more workflows or even suggest improvements to the current ones. If that was useful for you, please consider leaving a star in the repository.&lt;/p&gt;

&lt;p&gt;References and special thanks to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository" rel="noopener noreferrer"&gt;https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#about-environments" rel="noopener noreferrer"&gt;https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#about-environments&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://blog.hubspot.com/website/wordpress-github-integration" rel="noopener noreferrer"&gt;https://blog.hubspot.com/website/wordpress-github-integration&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://css-tricks.com/continuous-deployments-for-wordpress-using-github-actions/" rel="noopener noreferrer"&gt;https://css-tricks.com/continuous-deployments-for-wordpress-using-github-actions/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://engineering.monstar-lab.com/en/post/2023/01/02/How-to-setup-CI-CD-pipeline-for-WordPress-with-GitHub-Actions-and-AWS/" rel="noopener noreferrer"&gt;https://engineering.monstar-lab.com/en/post/2023/01/02/How-to-setup-CI-CD-pipeline-for-WordPress-with-GitHub-Actions-and-AWS/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://felipeelia.dev/ftp-no-more-deploying-wordpress-sites-with-github-actions/" rel="noopener noreferrer"&gt;https://felipeelia.dev/ftp-no-more-deploying-wordpress-sites-with-github-actions/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>continuousdeployment</category>
      <category>tutorial</category>
      <category>githubactions</category>
      <category>wordpress</category>
    </item>
  </channel>
</rss>
