<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tonic</title>
    <description>The latest articles on DEV Community by Tonic (@tonic).</description>
    <link>https://dev.to/tonic</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%2F1624522%2F71005415-dac4-42a5-8500-6a1ead30aa36.png</url>
      <title>DEV Community: Tonic</title>
      <link>https://dev.to/tonic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tonic"/>
    <language>en</language>
    <item>
      <title>excellent human-written post about a very under-rated topic 👇🏻</title>
      <dc:creator>Tonic</dc:creator>
      <pubDate>Mon, 23 Jun 2025 19:45:06 +0000</pubDate>
      <link>https://dev.to/tonic/excellent-human-written-post-about-a-very-under-rated-topic-5hld</link>
      <guid>https://dev.to/tonic/excellent-human-written-post-about-a-very-under-rated-topic-5hld</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/kylepena/gradient-descent-on-llm-input-space-a-modernbert-experiment-3053" class="crayons-story__hidden-navigation-link"&gt;Gradient Descent on Token Input Embeddings&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/kylepena" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F2288666%2F99573d2e-58cc-4972-85dd-785d1b22b190.jpeg" alt="kylepena profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/kylepena" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Kyle Pena
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Kyle Pena
                
              
              &lt;div id="story-author-preview-content-2610074" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/kylepena" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F2288666%2F99573d2e-58cc-4972-85dd-785d1b22b190.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Kyle Pena&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/kylepena/gradient-descent-on-llm-input-space-a-modernbert-experiment-3053" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 23 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/kylepena/gradient-descent-on-llm-input-space-a-modernbert-experiment-3053" id="article-link-2610074"&gt;
          Gradient Descent on Token Input Embeddings
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/llm"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;llm&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/machinelearning"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;machinelearning&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/deeplearning"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;deeplearning&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/kylepena/gradient-descent-on-llm-input-space-a-modernbert-experiment-3053" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;6&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/kylepena/gradient-descent-on-llm-input-space-a-modernbert-experiment-3053#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            9 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>llm</category>
      <category>machinelearning</category>
      <category>deeplearning</category>
    </item>
    <item>
      <title>Clearing GitHub Notifications with a Shell Script: An Introduction to Underutilized GitHub API Endpoints</title>
      <dc:creator>Tonic</dc:creator>
      <pubDate>Sun, 08 Sep 2024 08:00:07 +0000</pubDate>
      <link>https://dev.to/tonic/clearing-github-notifications-with-a-shell-script-an-introduction-to-underutilized-github-api-endpoints-5gf6</link>
      <guid>https://dev.to/tonic/clearing-github-notifications-with-a-shell-script-an-introduction-to-underutilized-github-api-endpoints-5gf6</guid>
      <description>&lt;p&gt;If you’re an active GitHub user, chances are you’ve experienced notification overload at some point. While GitHub’s notification system helps keep you up to date on all the repositories you follow, it can get overwhelming quickly. Thankfully, GitHub provides a robust API that allows us to manage notifications (among many other things) in ways that are not always obvious in the user interface.&lt;/p&gt;

&lt;p&gt;In this post, we’ll cover how to use a simple shell script to clear GitHub notifications using the GitHub API. We’ll also explore some lesser-known and underutilized areas of the GitHub API that can help you automate and streamline your development workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  Clearing GitHub Notifications with a Shell Script
&lt;/h2&gt;

&lt;p&gt;Imagine you have a backlog of unread GitHub notifications, and no matter what you do, the notification count won’t clear. Luckily, GitHub provides a dedicated &lt;a href="https://docs.github.com/en/rest/reference/activity#notifications" rel="noopener noreferrer"&gt;Notifications API&lt;/a&gt; that allows developers to interact with their notification feed. Using this API, we can mark notifications as read with a single API call.&lt;/p&gt;

&lt;p&gt;Let’s walk through a simple shell script that takes a GitHub Personal Access Token (PAT) as an argument and clears all notifications.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Shell Script
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# Check if the token was passed as an argument&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;GitHub Personal Access Token&amp;gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# GitHub Personal Access Token&lt;/span&gt;
&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;

&lt;span class="c"&gt;# Get the current date and time in ISO 8601 format&lt;/span&gt;
&lt;span class="nv"&gt;now&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%Y-%m-%dT%H:%M:%SZ&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# cURL command to mark all notifications as read&lt;/span&gt;
curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: bearer &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-X&lt;/span&gt; PUT &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Accept: application/vnd.github.v3+json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     https://api.github.com/notifications &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"last_read_at":"'&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$now&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s1"&gt;'"}'&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"All notifications have been marked as read!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Personal Access Token (PAT)&lt;/strong&gt;: The script expects your PAT as an argument. You can create one by following &lt;a href="https://github.com/settings/tokens/new" rel="noopener noreferrer"&gt;this guide&lt;/a&gt;. Make sure it has the appropriate permissions for notifications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Current Timestamp&lt;/strong&gt;: The script grabs the current date and time in the ISO 8601 format (&lt;code&gt;YYYY-MM-DDTHH:MM:SSZ&lt;/code&gt;) to mark notifications as read up to that point.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;API Call&lt;/strong&gt;: Using the &lt;code&gt;curl&lt;/code&gt; command, the script sends a &lt;code&gt;PUT&lt;/code&gt; request to the GitHub API with the &lt;code&gt;last_read_at&lt;/code&gt; parameter set to the current timestamp. This effectively marks all notifications as read.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How to Use the Script
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Save the script to a file, for example, &lt;code&gt;clear_github_notifications.sh&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give the script execution permission by running:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;chmod&lt;/span&gt; +x clear_github_notifications.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Run the script and pass your GitHub PAT as an argument:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   ./clear_github_notifications.sh &amp;lt;your-github-personal-access-token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running the script, all your notifications will be marked as read, clearing your inbox and resetting the notification count.&lt;/p&gt;




&lt;h2&gt;
  
  
  Exploring Other Underutilized Areas of the GitHub API
&lt;/h2&gt;

&lt;p&gt;The GitHub API is incredibly powerful, yet many of its features are underutilized by developers. Here are a few lesser-known API endpoints and use cases that can help you take your GitHub automation to the next level.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Automating Repository Management with the Repositories API&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://docs.github.com/en/rest/reference/repos" rel="noopener noreferrer"&gt;Repositories API&lt;/a&gt; is a rich part of the GitHub API, yet many people don’t use it to its full potential. Here are some handy things you can do with this API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatically Archiving Repositories&lt;/strong&gt;: When a project reaches its end of life, you can archive it automatically. This endpoint allows you to archive a repository by sending a simple API request.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   curl &lt;span class="nt"&gt;-X&lt;/span&gt; PUT &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: bearer &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        https://api.github.com/repos/yourusername/repo-name/archive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatically Creating Repositories&lt;/strong&gt;: You can automate the creation of repositories using the API. This is great if you manage multiple projects and want to create new repositories based on templates.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: bearer &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "new-repo", "auto_init": true}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        https://api.github.com/user/repos
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;strong&gt;Managing Workflow Runs with the Actions API&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;GitHub Actions is a powerful automation tool, but did you know you can manage your workflows directly from the API? The &lt;a href="https://docs.github.com/en/rest/actions" rel="noopener noreferrer"&gt;Actions API&lt;/a&gt; allows you to list, rerun, or cancel workflow runs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rerun a Workflow&lt;/strong&gt;: Need to rerun a failed workflow? You can trigger a rerun directly from the API.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: bearer &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        https://api.github.com/repos/yourusername/repo-name/actions/runs/workflow_id/rerun
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Get Workflow Logs&lt;/strong&gt;: Retrieve logs for a specific workflow run and diagnose issues without even opening the GitHub UI.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: bearer &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        https://api.github.com/repos/yourusername/repo-name/actions/runs/workflow_id/logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. &lt;strong&gt;Tracking Issues and Pull Requests with the Issues API&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://docs.github.com/en/rest/reference/issues" rel="noopener noreferrer"&gt;Issues API&lt;/a&gt; is a lifesaver if you’re tracking multiple projects and issues. With this API, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatically Assign Issues&lt;/strong&gt;: Automatically assign issues to team members based on predefined criteria.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: bearer &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"assignees": ["username"]}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        https://api.github.com/repos/yourusername/repo-name/issues/issue_number
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Label Issues&lt;/strong&gt;: Automatically label issues to prioritize or categorize them for easier tracking.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: bearer &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"labels": ["bug", "priority"]}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        https://api.github.com/repos/yourusername/repo-name/issues/issue_number/labels
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. &lt;strong&gt;Interacting with GitHub Discussions Using the Discussions API&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;GitHub Discussions is an increasingly popular feature for community engagement, and the &lt;a href="https://docs.github.com/en/rest/discussions" rel="noopener noreferrer"&gt;Discussions API&lt;/a&gt; makes it easy to automate and manage discussions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Creating a New Discussion&lt;/strong&gt;: Use the API to create new discussions for community input or project-related queries.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: bearer &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"title": "New Discussion", "body": "Let'&lt;/span&gt;s talk about this!&lt;span class="s2"&gt;", "&lt;/span&gt;category_id&lt;span class="s2"&gt;": 123}' &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
        https://api.github.com/repos/yourusername/repo-name/discussions
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;While GitHub’s user interface is powerful, there are plenty of ways to extend and automate your workflows using the GitHub API. Whether you want to clear notifications, automate repository management, rerun workflows, or manage issues and discussions, the API provides endless possibilities.&lt;/p&gt;

&lt;p&gt;The simple shell script we provided is just one example of how you can start harnessing the power of the GitHub API. From automating tedious tasks to implementing custom workflows, the GitHub API can transform the way you manage your projects and collaborate with your team.&lt;/p&gt;

&lt;p&gt;Start exploring, experiment with different API endpoints, and you’ll soon discover a world of automation opportunities on GitHub!&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>bash</category>
      <category>workplace</category>
    </item>
    <item>
      <title>Self-Hosting Forem on AWS</title>
      <dc:creator>Tonic</dc:creator>
      <pubDate>Sat, 10 Aug 2024 20:52:39 +0000</pubDate>
      <link>https://dev.to/tonic/self-hosting-forem-on-aws-50pc</link>
      <guid>https://dev.to/tonic/self-hosting-forem-on-aws-50pc</guid>
      <description>&lt;p&gt;These instructions will guide you through deploying a production-ready Forem instance on Amazon Web Services (AWS).&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;An AWS account&lt;/li&gt;
&lt;li&gt;AWS CLI installed and configured&lt;/li&gt;
&lt;li&gt;Basic knowledge of AWS services&lt;/li&gt;
&lt;li&gt;Domain name registered and configured in Route 53&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Set up VPC and Networking
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create VPC&lt;/span&gt;
aws ec2 create-vpc &lt;span class="nt"&gt;--cidr-block&lt;/span&gt; 10.0.0.0/16 &lt;span class="nt"&gt;--tag-specifications&lt;/span&gt; &lt;span class="s1"&gt;'ResourceType=vpc,Tags=[{Key=Name,Value=forem-vpc}]'&lt;/span&gt;

&lt;span class="c"&gt;# Create public subnet&lt;/span&gt;
aws ec2 create-subnet &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; &amp;lt;vpc-id&amp;gt; &lt;span class="nt"&gt;--cidr-block&lt;/span&gt; 10.0.1.0/24 &lt;span class="nt"&gt;--availability-zone&lt;/span&gt; us-east-1a

&lt;span class="c"&gt;# Create internet gateway&lt;/span&gt;
aws ec2 create-internet-gateway &lt;span class="nt"&gt;--tag-specifications&lt;/span&gt; &lt;span class="s1"&gt;'ResourceType=internet-gateway,Tags=[{Key=Name,Value=forem-igw}]'&lt;/span&gt;

&lt;span class="c"&gt;# Attach internet gateway to VPC&lt;/span&gt;
aws ec2 attach-internet-gateway &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; &amp;lt;vpc-id&amp;gt; &lt;span class="nt"&gt;--internet-gateway-id&lt;/span&gt; &amp;lt;igw-id&amp;gt;

&lt;span class="c"&gt;# Create route table and add route to internet&lt;/span&gt;
aws ec2 create-route-table &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; &amp;lt;vpc-id&amp;gt;
aws ec2 create-route &lt;span class="nt"&gt;--route-table-id&lt;/span&gt; &amp;lt;rtb-id&amp;gt; &lt;span class="nt"&gt;--destination-cidr-block&lt;/span&gt; 0.0.0.0/0 &lt;span class="nt"&gt;--gateway-id&lt;/span&gt; &amp;lt;igw-id&amp;gt;

&lt;span class="c"&gt;# Associate route table with subnet&lt;/span&gt;
aws ec2 associate-route-table &lt;span class="nt"&gt;--subnet-id&lt;/span&gt; &amp;lt;subnet-id&amp;gt; &lt;span class="nt"&gt;--route-table-id&lt;/span&gt; &amp;lt;rtb-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Create Security Group
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 create-security-group &lt;span class="nt"&gt;--group-name&lt;/span&gt; forem-sg &lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"Security group for Forem"&lt;/span&gt; &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; &amp;lt;vpc-id&amp;gt;

&lt;span class="c"&gt;# Allow inbound traffic&lt;/span&gt;
aws ec2 authorize-security-group-ingress &lt;span class="nt"&gt;--group-id&lt;/span&gt; &amp;lt;sg-id&amp;gt; &lt;span class="nt"&gt;--protocol&lt;/span&gt; tcp &lt;span class="nt"&gt;--port&lt;/span&gt; 22 &lt;span class="nt"&gt;--cidr&lt;/span&gt; 0.0.0.0/0
aws ec2 authorize-security-group-ingress &lt;span class="nt"&gt;--group-id&lt;/span&gt; &amp;lt;sg-id&amp;gt; &lt;span class="nt"&gt;--protocol&lt;/span&gt; tcp &lt;span class="nt"&gt;--port&lt;/span&gt; 80 &lt;span class="nt"&gt;--cidr&lt;/span&gt; 0.0.0.0/0
aws ec2 authorize-security-group-ingress &lt;span class="nt"&gt;--group-id&lt;/span&gt; &amp;lt;sg-id&amp;gt; &lt;span class="nt"&gt;--protocol&lt;/span&gt; tcp &lt;span class="nt"&gt;--port&lt;/span&gt; 443 &lt;span class="nt"&gt;--cidr&lt;/span&gt; 0.0.0.0/0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Launch EC2 Instance
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 run-instances &lt;span class="nt"&gt;--image-id&lt;/span&gt; ami-0261755bbcb8c4a84 &lt;span class="nt"&gt;--count&lt;/span&gt; 1 &lt;span class="nt"&gt;--instance-type&lt;/span&gt; t3.large &lt;span class="nt"&gt;--key-name&lt;/span&gt; &amp;lt;your-key-pair&amp;gt; &lt;span class="nt"&gt;--security-group-ids&lt;/span&gt; &amp;lt;sg-id&amp;gt; &lt;span class="nt"&gt;--subnet-id&lt;/span&gt; &amp;lt;subnet-id&amp;gt; &lt;span class="nt"&gt;--associate-public-ip-address&lt;/span&gt; &lt;span class="nt"&gt;--tag-specifications&lt;/span&gt; &lt;span class="s1"&gt;'ResourceType=instance,Tags=[{Key=Name,Value=forem-instance}]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Allocate Elastic IP
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 allocate-address
aws ec2 associate-address &lt;span class="nt"&gt;--instance-id&lt;/span&gt; &amp;lt;instance-id&amp;gt; &lt;span class="nt"&gt;--allocation-id&lt;/span&gt; &amp;lt;eipalloc-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Configure DNS
&lt;/h2&gt;

&lt;p&gt;Add an A record in Route 53 pointing your domain to the Elastic IP address.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. SSH into the Instance
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; &amp;lt;your-key-pair.pem&amp;gt; ubuntu@&amp;lt;public-ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Install Dependencies
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; git curl build-essential pkg-config libssl-dev libz-dev libreadline-dev libcurl4-openssl-dev uuid-dev icu-devtools imagemagick nginx postgresql redis-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Install mise
&lt;/h2&gt;

&lt;p&gt;Follow the mise installation instructions from their official documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Clone Forem Repository
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/forem/forem.git
&lt;span class="nb"&gt;cd &lt;/span&gt;forem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  10. Install Tool Dependencies
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;h2&gt;
  
  
  11. Set Up Database
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; postgres psql
CREATE DATABASE forem_production&lt;span class="p"&gt;;&lt;/span&gt;
CREATE USER forem WITH PASSWORD &lt;span class="s1"&gt;'your_secure_password'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
GRANT ALL PRIVILEGES ON DATABASE forem_production TO forem&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="se"&gt;\q&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  12. Set Up Environment Variables
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;.env.production&lt;/code&gt; file in the Forem directory and add necessary environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RAILS_ENV=production
DATABASE_URL=postgresql://forem:your_secure_password@localhost/forem_production
REDIS_URL=redis://localhost:6379
SECRET_KEY_BASE=&amp;lt;generate_a_secure_key&amp;gt;
FOREM_DOMAIN=your_domain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  13. Set Up Application
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--deployment&lt;/span&gt; &lt;span class="nt"&gt;--without&lt;/span&gt; development &lt;span class="nb"&gt;test
&lt;/span&gt;yarn &lt;span class="nb"&gt;install
&lt;/span&gt;&lt;span class="nv"&gt;RAILS_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;production bundle &lt;span class="nb"&gt;exec &lt;/span&gt;rails assets:precompile
&lt;span class="nv"&gt;RAILS_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;production bundle &lt;span class="nb"&gt;exec &lt;/span&gt;rails db:setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  14. Set Up Nginx as Reverse Proxy
&lt;/h2&gt;

&lt;p&gt;Create an Nginx configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/nginx/sites-available/forem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;your_domain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable the site:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /etc/nginx/sites-available/forem /etc/nginx/sites-enabled/
&lt;span class="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  15. Set Up SSL with Let's Encrypt
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;certbot python3-certbot-nginx &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;certbot &lt;span class="nt"&gt;--nginx&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; your_domain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  16. Set Up Forem as a Service
&lt;/h2&gt;

&lt;p&gt;Create a systemd service file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/systemd/system/forem.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=Forem
After=network.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/forem
ExecStart=/home/ubuntu/forem/bin/rails server -e production
Restart=on-failure

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable and start the service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;forem
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start forem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  17. Set Up Sidekiq as a Service
&lt;/h2&gt;

&lt;p&gt;Create a systemd service file for Sidekiq:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/systemd/system/sidekiq.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=Sidekiq
After=network.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/forem
ExecStart=/home/ubuntu/.mise/shims/bundle exec sidekiq -e production
Restart=on-failure

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable and start the service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;sidekiq
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start sidekiq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  18. Configure Fastly (Optional)
&lt;/h2&gt;

&lt;p&gt;If you want to use Fastly for caching:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sign up for a Fastly account&lt;/li&gt;
&lt;li&gt;Create a new service in Fastly&lt;/li&gt;
&lt;li&gt;Configure your domain in Fastly&lt;/li&gt;
&lt;li&gt;Update your DNS to point to Fastly's CDN&lt;/li&gt;
&lt;li&gt;Add the Fastly API key to your &lt;code&gt;.env.production&lt;/code&gt; file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FASTLY_API_KEY=your_fastly_api_key
FASTLY_SERVICE_ID=your_fastly_service_id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  19. Set Up Email (Optional)
&lt;/h2&gt;

&lt;p&gt;To enable transactional emails, add the following to your &lt;code&gt;.env.production&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SMTP_ADDRESS=smtp.your_email_provider.com
SMTP_PORT=587
SMTP_DOMAIN=your_domain.com
SMTP_USER_NAME=your_username
SMTP_PASSWORD=your_password
SMTP_AUTHENTICATION=plain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  20. Final Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Restart your Forem instance:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart forem
   &lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart sidekiq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Visit your domain in a web browser to complete the setup process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set up an admin account and configure your Forem instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember to regularly update your Forem instance, monitor your AWS resources, and implement proper backup strategies for your database and user-generated content.&lt;/p&gt;

</description>
      <category>forem</category>
      <category>aws</category>
      <category>ubuntu</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Docker's Testcontainers are Great!</title>
      <dc:creator>Tonic</dc:creator>
      <pubDate>Wed, 31 Jul 2024 10:20:06 +0000</pubDate>
      <link>https://dev.to/tonic/dockers-testcontainers-are-great-42cl</link>
      <guid>https://dev.to/tonic/dockers-testcontainers-are-great-42cl</guid>
      <description>&lt;p&gt;🙋🏻‍♂️ Hey there folks , i've really enjoyed using Docker's new opensource startup acquision called test containers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;see below for Links
&lt;/li&gt;
&lt;li&gt;they want you to use it for testing
&lt;/li&gt;
&lt;li&gt;i use it for simple AI/ML serving
&lt;/li&gt;
&lt;li&gt;join me to make more useful and cool testcontainers&lt;/li&gt;
&lt;/ul&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Testcontainers is an open source framework for providing throwaway, lightweight instances of databases, message brokers, web browsers, or just about anything that can run in a Docker container.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;leveraging containers for testing enhances reliability, reduces configuration overhead, and improves the consistency of test environments, ultimately leading to more robust and maintainable code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test Containers&lt;/strong&gt; offer significant benefits across different testing layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Integration Tests:&lt;/strong&gt; Containers provide isolated, reproducible environments for data access tests, ensuring consistency and reducing setup complexity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI/Acceptance Tests:&lt;/strong&gt; Containerized browsers enable consistent, reliable UI testing by eliminating variations caused by local browser setups.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application Integration Tests:&lt;/strong&gt; Using containers for testing applications with all dependencies allows for accurate, end-to-end testing in environments that closely resemble production.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Data Access Layer Integration Tests
&lt;/h4&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Isolation and Consistency:&lt;/strong&gt; Containerizing your database ensures that each test runs against a fresh, known state. This isolation eliminates the variability and inconsistencies associated with differing local database setups or residual data from previous tests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Setup Complexity:&lt;/strong&gt; Developers avoid the hassle of complex database setups on their local machines, which can lead to a more consistent development experience across the team.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability and Reliability:&lt;/strong&gt; Tests can be scaled easily without worrying about local resources, and container orchestration tools can manage test database instances efficiently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
A developer writes integration tests for an application’s data access layer using PostgreSQL. By spinning up a PostgreSQL container for each test, they ensure that each test starts with a clean slate, avoiding conflicts caused by residual data or schema changes from other tests.&lt;/p&gt;
&lt;h4&gt;
  
  
  UI/Acceptance Tests
&lt;/h4&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Consistent Test Environment:&lt;/strong&gt; Using containerized browsers with tools like Selenium guarantees that UI tests run in a consistent environment, reducing the impact of browser-specific issues or variations caused by different versions or plugins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Setup and Maintenance:&lt;/strong&gt; Containers simplify the setup process for UI tests by providing pre-configured, standardized browser instances, eliminating the need to manually manage browser versions or extensions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproducibility:&lt;/strong&gt; Each test execution starts with a fresh browser instance, leading to more reliable and reproducible test outcomes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
An automated UI test suite for a web application is run using containerized Chrome instances. Each test starts with a clean browser, ensuring that issues related to browser cache or extensions do not affect the test results.&lt;/p&gt;
&lt;h4&gt;
  
  
  Application Integration Tests
&lt;/h4&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;End-to-End Testing:&lt;/strong&gt; Containerized environments enable comprehensive testing of the application with all its dependencies (e.g., databases, message queues, web servers) in a single, isolated environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Management:&lt;/strong&gt; Short-lived test containers help manage resources efficiently, avoiding the overhead of long-running services and allowing for quick test execution and teardown.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment Parity:&lt;/strong&gt; Tests can be executed in an environment that closely mimics production, enhancing the accuracy of test results and reducing the risk of discrepancies between test and production environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
A microservices-based application is tested using containers for each microservice, along with associated dependencies like a Redis cache and RabbitMQ message broker. This setup allows for end-to-end tests that validate interactions between services in a controlled, isolated environment.&lt;/p&gt;
&lt;h2&gt;
  
  
  "Very useful , Let's goof off with AI now"
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;that's great and i'm sure it's useful for saving on DevOps pipelines for production builds and so much more, but i love using it for it's Ollama Object !&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Try Testcontainers for AI
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;OllamaContainer&lt;/code&gt; class from the &lt;code&gt;testcontainers&lt;/code&gt; Python library facilitates the setup and management of containerized environments for serving AI models with Ollama. This allows you to run inference tasks in a consistent and isolated environment, making it easier to test and develop AI applications without worrying about local configuration issues.&lt;/p&gt;
&lt;h3&gt;
  
  
  Testcontainers Object for Ollama AI Serving Inference
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;OllamaContainer&lt;/code&gt; class provides a streamlined way to interact with a containerized instance of Ollama, which serves AI models for inference. It simplifies tasks such as starting the Ollama service, listing available models, pulling new models, and querying the service for predictions. Below is a detailed description of how to use the &lt;code&gt;OllamaContainer&lt;/code&gt; class, along with code snippets illustrating typical use cases.&lt;/p&gt;
&lt;h4&gt;
  
  
  Features
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Container Management:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatically handles the lifecycle of the Ollama container.&lt;/li&gt;
&lt;li&gt;Starts the container and ensures it is properly stopped and cleaned up after use.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Model Management:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allows listing available models.&lt;/li&gt;
&lt;li&gt;Supports pulling new models if they are not already available.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Inference Requests:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provides methods to interact with the model for inference tasks via HTTP endpoints.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Code Examples
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;OllamaContainer&lt;/code&gt; class from the &lt;code&gt;testcontainers&lt;/code&gt; library is a powerful tool for developers working with AI models, providing a straightforward way to manage containerized environments for inference tasks. By encapsulating the complexity of setup and teardown, it allows developers to focus on building and testing their applications with reliable and reproducible results.&lt;/p&gt;
&lt;h5&gt;
  
  
  Basic Usage
&lt;/h5&gt;

&lt;p&gt;The following code snippet demonstrates how to use the &lt;code&gt;OllamaContainer&lt;/code&gt; class to set up an environment, list available models, and perform inference tasks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;loads&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RequestException&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;testcontainers.ollama&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OllamaContainer&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;split_by_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;each_item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;each_item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\r\r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
                &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;OllamaContainer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ollama_home&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;home&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.ollama&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ollama&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# List available models
&lt;/span&gt;        &lt;span class="n"&gt;models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ollama&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list_models&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Available models:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Choose a specific model, for example 'yi:6b-v1.5'
&lt;/span&gt;        &lt;span class="n"&gt;model_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;yi:6b-v1.5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;model_name&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Model &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; not found, pulling the model.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;ollama&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pull_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Model &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; has been pulled.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Use the model to generate responses in an interactive chat
&lt;/span&gt;        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ollama&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_endpoint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You can now start chatting with the model. Type &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;exit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; to quit.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;user_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Exiting chat.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="k"&gt;break&lt;/span&gt;

                &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/api/chat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                    &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
                            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_input&lt;/span&gt;
                        &lt;span class="p"&gt;}]&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;split_by_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;iter_content&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;
                    &lt;span class="n"&gt;model_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Model: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model_response&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;RequestException&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An error occurred: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Key Methods and Properties
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;__init__(ollama_home: Path)&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;ollama_home&lt;/code&gt; (Path) - The directory where Ollama configuration and model files are stored.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; Initializes the container with a specified home directory for Ollama.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;list_models()&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Returns:&lt;/strong&gt; A list of available models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; Retrieves a list of models currently available in the container.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;pull_model(model_name: str)&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;model_name&lt;/code&gt; (str) - The name of the model to pull.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; Pulls the specified model if it is not already available.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;get_endpoint()&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Returns:&lt;/strong&gt; A string containing the endpoint URL for accessing the model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; Provides the URL where the model's inference API can be accessed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;__enter__()&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;__exit__()&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; Handle the context management for the container, starting and stopping it as needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Best Part
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Now you can deploy containers directly in your code , remove containers, save on ressources, test with more rigoror , and create your own objects !&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Join US
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;we're pushing our favorite services upstream , and there are a ton of supported languages &lt;strong&gt;not just python !&lt;/strong&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://discord.gg/qdfnvSPcqP" rel="noopener noreferrer"&gt;Join us on our ⚒️builders' discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://git.tonic-ai.com" rel="noopener noreferrer"&gt;Sign up to our gitlab - after saying hi!&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://huggingface.co/multitransformer" rel="noopener noreferrer"&gt;Follow us on 🤗huggingface&lt;/a&gt; and Dev.to 🙏🏻&lt;/li&gt;
&lt;li&gt;Join our docker projects , and more !&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Docker : &lt;a href="https://github.com/docker" rel="noopener noreferrer"&gt;https://github.com/docker&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;testcontainers : &lt;a href="https://github.com/testcontainers/" rel="noopener noreferrer"&gt;https://github.com/testcontainers/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Tonic-AI : &lt;a href="https://www.github.com/Tonic-AI" rel="noopener noreferrer"&gt;https://www.github.com/Tonic-AI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ask Questions Below ! 👇🏻
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;have trouble running this script ? ask a lot of questions below, no problem !&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>docker</category>
      <category>ai</category>
      <category>community</category>
      <category>testcontainers</category>
    </item>
    <item>
      <title>Pitch-Tonic</title>
      <dc:creator>Tonic</dc:creator>
      <pubDate>Sun, 23 Jun 2024 17:17:01 +0000</pubDate>
      <link>https://dev.to/tonic/pitch-tonic-500a</link>
      <guid>https://dev.to/tonic/pitch-tonic-500a</guid>
      <description>&lt;p&gt;we're making a cool app for a hackathon : everyone is welcome to join us !&lt;/p&gt;

&lt;p&gt;🎤 &lt;strong&gt;Pitch Tonic: Your Ultimate Pitch Training App!&lt;/strong&gt; 🎤&lt;/p&gt;

&lt;p&gt;Elevate your pitching game with &lt;strong&gt;Pitch Tonic&lt;/strong&gt;, the open-source app designed to perfect your live pitches and investor Q&amp;amp;A training. Here's how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Interlocutor Recording &amp;amp; Tips&lt;/strong&gt; 📹: Record your interlocutor and get real-time tips to improve your pitch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pitch Deck Training&lt;/strong&gt; 🎓: Record yourself practicing your pitch deck and receive constructive feedback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Knowledge Testing&lt;/strong&gt; 🧠: Test your pitch knowledge by answering questions and get instant feedback. Choose from easy, medium, or hard levels to challenge yourself.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;💡 &lt;strong&gt;We Need You!&lt;/strong&gt; 💡&lt;br&gt;
Pitch Tonic is fully open-source under the MIT license, and we're looking for passionate contributors to help us grow! Whether you're a developer, designer, or pitch enthusiast, join our community and make an impact.&lt;/p&gt;

&lt;p&gt;🤝 &lt;strong&gt;Get Involved&lt;/strong&gt; 🤝&lt;br&gt;
Contribute to the code, suggest new features, or provide feedback. Let's make Pitch Tonic the go-to tool for startups everywhere!&lt;/p&gt;

&lt;p&gt;🚀 &lt;strong&gt;Join Us Today!&lt;/strong&gt; 🚀&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://git.tonic-ai.com/tonic-ai/pitch-tonic"&gt;Contribute on our Gitlab&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👥 &lt;strong&gt;Get in Touch&lt;/strong&gt; 👥&lt;br&gt;
Have questions or ideas? request access!&lt;/p&gt;

&lt;p&gt;💬 &lt;a href="https://discord.gg/ughK8cNF"&gt;Discord&lt;/a&gt;&lt;/p&gt;

</description>
      <category>whisper</category>
      <category>python</category>
      <category>webdev</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>i got followers here a lot and quickly !</title>
      <dc:creator>Tonic</dc:creator>
      <pubDate>Mon, 17 Jun 2024 18:33:04 +0000</pubDate>
      <link>https://dev.to/tonic/i-got-followers-here-a-lot-and-quickly--5b5i</link>
      <guid>https://dev.to/tonic/i-got-followers-here-a-lot-and-quickly--5b5i</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6voqhc2a3oj60bjniggu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6voqhc2a3oj60bjniggu.png" alt="Image description" width="726" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;this is actually so crazy !!!&lt;/p&gt;

&lt;h2&gt;
  
  
  thank you all so much !
&lt;/h2&gt;

&lt;p&gt;i'll try to not let you down and keep the cool oss / ai / enterprise / fintech (not crypto, just normal) projects coming and make life on earth !&lt;/p&gt;

</description>
      <category>community</category>
      <category>devto</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Code the Vote!</title>
      <dc:creator>Tonic</dc:creator>
      <pubDate>Sat, 15 Jun 2024 18:16:04 +0000</pubDate>
      <link>https://dev.to/tonic/code-the-vote-1bif</link>
      <guid>https://dev.to/tonic/code-the-vote-1bif</guid>
      <description>&lt;h3&gt;
  
  
  🙋🏻‍♂️Making a USA-elections app
&lt;/h3&gt;

&lt;p&gt;basically i was gonna drop off, but then i got roped back in !&lt;/p&gt;

&lt;p&gt;we have 24 hours from this post to make it !&lt;/p&gt;

&lt;p&gt;it's for a hackathon on devpost : &lt;a href="https://code-the-vote.devpost.com/"&gt;https://code-the-vote.devpost.com/&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;here's the repo : &lt;a href="https://github.com/Josephrp/oreally.git"&gt;https://github.com/Josephrp/oreally.git&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;here are the open issues : &lt;a href="https://github.com/Josephrp/oreally/issues"&gt;https://github.com/Josephrp/oreally/issues&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;i'd love to link up with some coders that like #llama-index #ai #voice / #audio #python #streamlit all that :-)&lt;/p&gt;

&lt;p&gt;just get in touch :-)&lt;/p&gt;

</description>
      <category>llamaindex</category>
      <category>ai</category>
      <category>python</category>
      <category>news</category>
    </item>
    <item>
      <title>Join our discord builder's server</title>
      <dc:creator>Tonic</dc:creator>
      <pubDate>Fri, 14 Jun 2024 12:45:14 +0000</pubDate>
      <link>https://dev.to/tonic-ai/join-our-discord-builders-server-48m9</link>
      <guid>https://dev.to/tonic-ai/join-our-discord-builders-server-48m9</guid>
      <description>&lt;h3&gt;
  
  
  hey there folks, we're Tonic-AI
&lt;/h3&gt;

&lt;p&gt;We started off as an accidental community , but we're growing and supporting eachother, "building in public" and basically learning and ton and publishing a ton of demos and stuff.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sounds good ?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;** join us! **&lt;/p&gt;

&lt;p&gt;&lt;a href="https://discord.gg/ZbXm7YHsA7"&gt;discord&lt;/a&gt;&lt;/p&gt;

</description>
      <category>community</category>
      <category>ai</category>
      <category>buildinpublic</category>
      <category>programming</category>
    </item>
    <item>
      <title>Hey there Folks - It's my First Post !</title>
      <dc:creator>Tonic</dc:creator>
      <pubDate>Fri, 14 Jun 2024 10:34:18 +0000</pubDate>
      <link>https://dev.to/tonic/hey-there-folks-its-my-first-post--52k</link>
      <guid>https://dev.to/tonic/hey-there-folks-its-my-first-post--52k</guid>
      <description>&lt;h3&gt;
  
  
  Tonic-AI Community
&lt;/h3&gt;

&lt;p&gt;if actually found dev.to through forem, isnt that cool ?&lt;/p&gt;

&lt;p&gt;basically i just started an accidental dev community on discord (i hate discord to be honest) and it kinda took off, we're making like 10 demos a week on good weeks and 2 or 3 on bad weeks, so the volume on code repos is really there :-)&lt;/p&gt;

&lt;p&gt;proud of us &amp;amp; now we have a community organisation on dev.to&lt;/p&gt;

&lt;p&gt;really loving everything i see here so far !&lt;/p&gt;

&lt;p&gt;looking forward to contributing cool posts and learning a ton !&lt;/p&gt;

</description>
      <category>firstpost</category>
      <category>firstyearincode</category>
      <category>community</category>
      <category>devjournal</category>
    </item>
  </channel>
</rss>
