<?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: meddlesome</title>
    <description>The latest articles on DEV Community by meddlesome (@meddlesome).</description>
    <link>https://dev.to/meddlesome</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%2F325502%2F898fd3b9-ad1d-46aa-a2f9-14736a1ce435.jpg</url>
      <title>DEV Community: meddlesome</title>
      <link>https://dev.to/meddlesome</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/meddlesome"/>
    <language>en</language>
    <item>
      <title>AI Agent vs Discord Webhook Message limitation</title>
      <dc:creator>meddlesome</dc:creator>
      <pubDate>Tue, 01 Jul 2025 04:03:19 +0000</pubDate>
      <link>https://dev.to/meddlesome/ai-agent-vs-discord-webhook-message-limitation-nf5</link>
      <guid>https://dev.to/meddlesome/ai-agent-vs-discord-webhook-message-limitation-nf5</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8qx4hxp2bh4q9a7mtjhp.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%2F8qx4hxp2bh4q9a7mtjhp.png" alt="Agent to send message to Discord" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you develop AI Agent, especially with n8n. You want to send message to Discord with Webhook. But it end up with error when LLM produced output more than 2000 characters as a &lt;a href="https://discord.com/developers/docs/resources/webhook#execute-webhook-jsonform-params" rel="noopener noreferrer"&gt;limitation&lt;/a&gt; of Discord Webhook.&lt;/p&gt;

&lt;h2&gt;
  
  
  LLM Limitation
&lt;/h2&gt;

&lt;p&gt;Solving by let LLM trying to split the message is not accurate, since 1 Token != 1 characters. then It will end-up with &lt;strong&gt;Multi-turn&lt;/strong&gt; request which not efficient as possible with many attempt which wasted time and context windows(even with Context windows caching).&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%2F2iixxleo55sry4hrlqw0.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%2F2iixxleo55sry4hrlqw0.png" alt="Multi-turn Agent" width="800" height="735"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tackle the problem with Tools calling
&lt;/h2&gt;

&lt;p&gt;Since LLM is not accurate on counting, e.g. &lt;a href="https://www.reddit.com/r/OpenAI/comments/1e6dl54/why_the_strawberry_problem_is_hard_for_llms/" rel="noopener noreferrer"&gt;strawberry problem&lt;/a&gt;. Using Tools calling. It can help.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple Tools to count string length
&lt;/h3&gt;

&lt;p&gt;Then I start with a simple tools as one liner to return string length to let Agent to split text and try again&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return query.length
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4i12oqe3odo3wkcubnk.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%2Fi4i12oqe3odo3wkcubnk.png" alt="Tools Callihng" width="607" height="317"&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%2Fxj6oofanwwnilqorjgqo.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%2Fxj6oofanwwnilqorjgqo.png" alt="String length check" width="598" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But this is not sufficient enough as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Still Multi-turn effort as time consume. Even LLM know the length, but LLM cannot split perfectly&lt;/li&gt;
&lt;li&gt;Wasted Token (even with LLM context caching)&lt;/li&gt;
&lt;/ul&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%2Fy9vpwnejf1hfhxarg6pp.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%2Fy9vpwnejf1hfhxarg6pp.png" alt="Multi-Turn" width="800" height="735"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Efficient ways
&lt;/h2&gt;

&lt;p&gt;Then I looking forward to create a single tools to let LLM calling tools split string chunks to array and let n8n workflow continue the rest. &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%2Fn1ztabdu4ub1fm6k1a4n.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%2Fn1ztabdu4ub1fm6k1a4n.png" alt="Image description" width="446" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also create a reusable with &lt;code&gt;Executed by another Workflow&lt;/code&gt; Trigger to perform sending Discord Webhook&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%2Fhl7fqhj8m9yh6flpmbyq.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%2Fhl7fqhj8m9yh6flpmbyq.png" alt="Reusable Workflow" width="800" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a JS Snipplet &lt;a href="https://gist.github.com/meddlesome/b1e35ad133c726e0691b89c307245af5" rel="noopener noreferrer"&gt;https://gist.github.com/meddlesome/b1e35ad133c726e0691b89c307245af5&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;// Input: Single string from previous node
const inputText = $input.first().json.text; // Adjust field name as needed

// Configuration
const MAX_LENGTH = 2000;
const SPLIT_PATTERNS = ['\n\n', '\n', '. ', ' ']; // Priority order for splitting

function splitText(text, maxLength) {
  if (text.length &amp;lt;= maxLength) {
    return [text];
  }

  const chunks = [];
  let remainingText = text;

  while (remainingText.length &amp;gt; 0) {
    if (remainingText.length &amp;lt;= maxLength) {
      chunks.push(remainingText);
      break;
    }

    let chunk = remainingText.substring(0, maxLength);
    let splitIndex = -1;

    // Find best split point
    for (const pattern of SPLIT_PATTERNS) {
      const lastIndex = chunk.lastIndexOf(pattern);
      if (lastIndex &amp;gt; maxLength * 0.5) { // Don't split too early
        splitIndex = lastIndex + pattern.length;
        break;
      }
    }

    // If no good split point found, force split at max length
    if (splitIndex === -1) {
      splitIndex = maxLength;
    }

    chunks.push(remainingText.substring(0, splitIndex).trim());
    remainingText = remainingText.substring(splitIndex).trim();
  }

  return chunks;
}

// Process the text
const textChunks = splitText(inputText, MAX_LENGTH);

// Return array of chunks
return textChunks.map((chunk, index) =&amp;gt; ({
  json: {
    chunk: chunk,
    index: index,
    totalChunks: textChunks.length,
    length: chunk.length
  }
}));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It end-up with single turn and reducing time over 50% !&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%2Fxeed4m3t7hb960izr2qm.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%2Fxeed4m3t7hb960izr2qm.png" alt="Logs" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>n8n</category>
      <category>discord</category>
      <category>ai</category>
      <category>webhook</category>
    </item>
    <item>
      <title>How to record screen with system sound (Including Microsoft Teams meeting) by QuickTime</title>
      <dc:creator>meddlesome</dc:creator>
      <pubDate>Tue, 03 Dec 2024 14:35:22 +0000</pubDate>
      <link>https://dev.to/meddlesome/how-to-record-screen-with-system-sound-including-ms-team-meeting-by-quicktime-1nin</link>
      <guid>https://dev.to/meddlesome/how-to-record-screen-with-system-sound-including-ms-team-meeting-by-quicktime-1nin</guid>
      <description>&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Installed &lt;a href="https://existential.audio/blackhole/" rel="noopener noreferrer"&gt;Blackhole 2ch&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How to Setup
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open "Audio MIDI Setup" app from &lt;code&gt;Application/Utilities&lt;/code&gt;. If the Blackhole was installed. It should show &lt;code&gt;BlackHole 2ch&lt;/code&gt; on the list&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create "Aggregate Device" &amp;gt; Select &lt;code&gt;BlackHole 2ch&lt;/code&gt; &amp;gt; Rename the new profile to &lt;code&gt;Input for QuickTime Record&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2Fr3anoupw2ispyzeqimhp.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%2Fr3anoupw2ispyzeqimhp.png" alt="Created Profile " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create "Multi-Output Device" &amp;gt; Select &lt;code&gt;BlackHole 2ch&lt;/code&gt; AND your &lt;code&gt;YOUR_CURRENT_SPEAKER_OR_HEADPHONE&lt;/code&gt; &amp;gt; Rename the new profile to  &lt;code&gt;Output for Screen Record&lt;/code&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%2Fi4nlzxxfgul1ndbhqkvu.png" alt="Created Profile " width="800" height="800"&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;blockquote&gt;
&lt;p&gt;ℹ️ Below are also the 📝 checklist before recording, always check.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  When to record
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open “Audio MIDI Setup” to check “Output for Screen Record” that both &lt;code&gt;BlackHole 2ch&lt;/code&gt; AND &lt;code&gt;YOUR_CURRENT_SPEAKER_OR_HEADPHONE&lt;/code&gt; were enabled&lt;/li&gt;
&lt;li&gt;Open “Audio MIDI Setup” to check “Input for QuickTime Record” that &lt;code&gt;BlackHole 2ch&lt;/code&gt; was enabled. If you want your 🎤 microphone sound recorded, you must also enable &lt;code&gt;YOUR_MICROPHONE&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;🚨 Warning !!! when to enable your 🎤 microphone on this profile. It will continue recording unless you have a &lt;strong&gt;hardware muted button&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Screen Record with QuickTime
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;File &amp;gt; New Screen Recording. Then ensure the audio input was correctly set with Option… &amp;gt; Microphone &amp;gt; &lt;code&gt;Input for QuickTime Record&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ This also works with OBS or other streaming applications.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Record from Microsoft Teams
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Choose 🔈 Speaker = &lt;code&gt;Output for Screen Record(Aggregate)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select 🎤 Microphone = &lt;code&gt;YOUR_CURRENT_MICROPHONE&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Record from other applications e.g. Chrome
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Choose Audio Output to &lt;code&gt;Output for Screen Record&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;🔊 While choosing &lt;code&gt;Output for Screen Record&lt;/code&gt;, you cannot adjust the output volume for your speaker or headphones. To adjust the output volume, switch to your output to adjust the volume. Then switch back to &lt;code&gt;Output for Screen Record&lt;/code&gt; again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fowslotqnxekvp86a94cu.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%2Fowslotqnxekvp86a94cu.png" alt="Mac Output Menu" width="304" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Some GKE pods are failing with strange error with Google Auth</title>
      <dc:creator>meddlesome</dc:creator>
      <pubDate>Thu, 01 Jun 2023 12:40:26 +0000</pubDate>
      <link>https://dev.to/meddlesome/some-gke-pod-failing-with-google-auth-error-2k56</link>
      <guid>https://dev.to/meddlesome/some-gke-pod-failing-with-google-auth-error-2k56</guid>
      <description>&lt;p&gt;Recently, I found a strange Pod behavior in Google Kubernetes Engine - GKE&lt;/p&gt;

&lt;p&gt;When Rolling-out deployment. Most pods are healthy and up, but some pod error with CrashLoopBack.&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%2Ftnlmg17ylbyk1rsggbk1.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%2Ftnlmg17ylbyk1rsggbk1.png" alt="Image description" width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Digging down to Pod Event, everything good. Except unhealthy. Going more to The log of unhealthy pod. Some hint is showing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.
    at GoogleAuth.getApplicationDefaultAsync (/usr/src/app/node_modules/google-auth-library/build/src/auth/googleauth.js:183:19)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;We found some &lt;a href="https://github.com/googleapis/google-auth-library-nodejs/issues/1236" rel="noopener noreferrer"&gt;interesting fix&lt;/a&gt; by adding Environment variable to pod.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;🎉🎉🎉 Now pods are fully up without error.&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%2Fcf4wphil31q57csl7pra.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%2Fcf4wphil31q57csl7pra.png" alt="Image description" width="800" height="170"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Cause of this issue is when rolling deployments, multiple pods made request to GCP for authentication, sometime it timeout without retry then fail.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>googlecloud</category>
    </item>
    <item>
      <title>Solving kubectl authentication error on GKE</title>
      <dc:creator>meddlesome</dc:creator>
      <pubDate>Fri, 27 Jan 2023 09:11:32 +0000</pubDate>
      <link>https://dev.to/meddlesome/kubectl-authentication-error-on-gke-v126-58ba</link>
      <guid>https://dev.to/meddlesome/kubectl-authentication-error-on-gke-v126-58ba</guid>
      <description>&lt;p&gt;When you executing &lt;code&gt;kubectl&lt;/code&gt; command to your cluster on GKE. It will thrown some error like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl get namespaces
error: The gcp auth plugin has been removed.
Please use the "gke-gcloud-auth-plugin" kubectl/client-go credential plugin instead.
See https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke for further details
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As GKE change the way to authentication more safely. then we need to upgrade our GKE authentication&lt;/p&gt;

&lt;p&gt;But Even installing &lt;code&gt;gcloud components install gke-gcloud-auth-plugin&lt;/code&gt; and set &lt;code&gt;export USE_GKE_GCLOUD_AUTH_PLUGIN=True&lt;/code&gt;  might be still not working. Since an existing "Kube context" (credentials) still exist. You need to remove and fetch kube context again.&lt;/p&gt;

&lt;p&gt;Here is overall trick to solve the problem&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ gcloud components install gke-gcloud-auth-plugin
$ echo 'export USE_GKE_GCLOUD_AUTH_PLUGIN=True' &amp;gt;&amp;gt; ~/.bashrc
$ source ~/.bashrc
$ gcloud components update
$ cp ~/.kube/config ~/.kube/config.backup &amp;amp;&amp;amp; rm ~/.kube/config
$ gcloud container clusters get-credentials {{GKE_CLUSTER_NAME}} --region {{GKE-REGION}} --project {{GCP_PROJECT_NAME}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>devops</category>
      <category>googlecloud</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>How to access Google Cloud Storage Bucket with Service account JSON</title>
      <dc:creator>meddlesome</dc:creator>
      <pubDate>Tue, 20 Dec 2022 16:27:44 +0000</pubDate>
      <link>https://dev.to/meddlesome/how-to-access-google-cloud-storage-bucket-with-service-account-json-5645</link>
      <guid>https://dev.to/meddlesome/how-to-access-google-cloud-storage-bucket-with-service-account-json-5645</guid>
      <description>&lt;p&gt;This method for &lt;code&gt;gsutil&lt;/code&gt; to access Google Cloud Storage bucket with shared Service account with private key as JSON&lt;/p&gt;

&lt;p&gt;Sample JSON Structure&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "type": "service_account",
  "project_id": "xxx",
  "private_key_id": "xxx",
  "private_key": "-----BEGIN PRIVATE KEY-----\name-----END PRIVATE KEY-----\n",
  "client_email": "xxx@xxx.iam.gserviceaccount.com",
  "client_id": "xxx",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/xxx.iam.gserviceaccount.com"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Using &lt;code&gt;gsutil config -e&lt;/code&gt; to set method to authentication&lt;/li&gt;
&lt;li&gt;Choose &lt;code&gt;oAuth2&lt;/code&gt; and provided full path of service account JSON file&lt;/li&gt;
&lt;li&gt;Then you can access with &lt;code&gt;gsutil ls gs://{bucket-name}&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>googlecloud</category>
    </item>
    <item>
      <title>Safe to interact with Kubernetes CLI</title>
      <dc:creator>meddlesome</dc:creator>
      <pubDate>Wed, 20 Apr 2022 16:28:10 +0000</pubDate>
      <link>https://dev.to/meddlesome/safe-to-interact-with-kubectl-5a6i</link>
      <guid>https://dev.to/meddlesome/safe-to-interact-with-kubectl-5a6i</guid>
      <description>&lt;p&gt;When you interacting with Kubernetes CLI like &lt;code&gt;kubectl&lt;/code&gt; or any related commands. It normally interact with current context of &lt;code&gt;kubeconfig&lt;/code&gt; file with Project, Cluster, Namespace.&lt;/p&gt;

&lt;p&gt;It will mess you up when interacting with &lt;strong&gt;multiple&lt;/strong&gt; projects, clusters, namespaces. Since you cannot sure what is context that you will pull a trigger. And quite error-prone when interact with that.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current Context Prompt
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Ensure on your current context of kubectl by showing current context prompt on your screen when typing related Kubernetes commands.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fehs3kzkkgqe3tjrbssuq.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%2Fehs3kzkkgqe3tjrbssuq.png" alt="Context Prompt in your zsh shell" width="800" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/tools/" rel="noopener noreferrer"&gt;Kubernetes CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ohmyz.sh" rel="noopener noreferrer"&gt;Shell: zsh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/romkatv/powerlevel10k" rel="noopener noreferrer"&gt;Theme: romkatv/powerlevel10k&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you using &lt;a href="https://ohmyz.sh" rel="noopener noreferrer"&gt;zsh&lt;/a&gt; with &lt;a href="https://github.com/romkatv/powerlevel10k" rel="noopener noreferrer"&gt;romkatv/powerlevel10k&lt;/a&gt; theme. It feature "Show in Command" which support &lt;code&gt;kubecontext&lt;/code&gt; which can show current context at right hand side of each prompt and always show when you run related Kubernetes commands.&lt;/p&gt;




&lt;p&gt;Here is a sample guide to customize on &lt;a href="https://github.com/romkatv/powerlevel10k" rel="noopener noreferrer"&gt;romkatv/powerlevel10k&lt;/a&gt; configuration file &lt;code&gt;~/.p10k.zsh&lt;/code&gt; which you can open on any text editor, then edit and reload your shell session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Show on Command
&lt;/h3&gt;

&lt;p&gt;This will specific a list of command that will trigger to show current context while you typing-in, feel free to adding more if you have more related Kubernetes tools.&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;typeset&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nv"&gt;POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'kubectl|helm|kubens|kubectx|oc|istioctl|kogito|k9s|helmfile|fluxctl|stern|ytt'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Customize context detail
&lt;/h3&gt;

&lt;p&gt;You can specific on what Kubernetes context information to show on the prompt when you typing-in any related Kubernetes commands&lt;/p&gt;

&lt;p&gt;Many options are available and already commented on &lt;code&gt;~./p10k.zsh&lt;/code&gt; file, but here is my recommended pattern that quite clear when you working with multiple contexts.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;CLOUD_PROVIDER/PROJECT_NAME/CLUSTER_NAME/NAMESPACE&lt;/code&gt;&lt;br&gt;
Same as above sample images&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;typeset&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nv"&gt;POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'${${P9K_KUBECONTEXT_CLOUD_NAME:+/$P9K_KUBECONTEXT_CLOUD_NAME/$P9K_KUBECONTEXT_CLOUD_ACCOUNT/$P9K_KUBECONTEXT_CLOUD_CLUSTER}:-$P9K_KUBECONTEXT_NAME}${${:-/$P9K_KUBECONTEXT_NAMESPACE}:#/default'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>kubernetes</category>
      <category>bash</category>
      <category>unix</category>
      <category>shell</category>
    </item>
    <item>
      <title>Parsing JSON on Jenkins , a problem with sh</title>
      <dc:creator>meddlesome</dc:creator>
      <pubDate>Mon, 07 Feb 2022 07:07:10 +0000</pubDate>
      <link>https://dev.to/meddlesome/parsing-json-on-jenkins-problem-111o</link>
      <guid>https://dev.to/meddlesome/parsing-json-on-jenkins-problem-111o</guid>
      <description>&lt;p&gt;When you want to process a JSON file in Jenkins pipeline, you can do in various ways&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.jenkins.io/doc/pipeline/steps/pipeline-utility-steps/#readjson-read-json-from-files-in-the-workspace" rel="noopener noreferrer"&gt;Pipeline Utility Steps&lt;/a&gt; &lt;code&gt;readJSON&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stedolan.github.io/jq/" rel="noopener noreferrer"&gt;jq&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;JSON Parser in Python, NodeJS. etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article will focus on the problem with jq vs Jenkins &lt;code&gt;sh&lt;/code&gt; since it introducing some interesting problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sample Data&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;file.json&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lorem"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lorem Ipsum"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"dash-key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lorem Ipsum"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"underscore_key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lorem Ipsum"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;In the jq, a syntax to get the JSON value from a key is&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;file.json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; .lorem.key
Lorem Ipsum
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;file.json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; .lorem.underscore_key
Lorem Ipsum
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But, it will have a problem when your JSON key contains "-" dash.&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;file.json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; .lorem.dash-key
jq: error: key/0 is not defined at &amp;lt;top-level&amp;gt;, line 1:
.lorem.dash-key
jq: 1 compile error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With some limitation with jq, a key string contains dash &lt;code&gt;-&lt;/code&gt; have to combine pattern with single-quote and double-quote when query. Possible in many pattern to get a value.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Dash Issue with jq &lt;a href="https://github.com/stedolan/jq/issues/38#issuecomment-9770240" rel="noopener noreferrer"&gt;Github Issue&lt;/a&gt;, &lt;a href="https://stackoverflow.com/questions/37344329/jq-not-working-on-tag-name-with-dashes-and-numbers" rel="noopener noreferrer"&gt;Stack Overflow&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$cat&lt;/span&gt; file.json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.lorem."dash-key"'&lt;/span&gt;
Lorem Ipsum

&lt;span class="nv"&gt;$cat&lt;/span&gt; file.json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; .lorem.&lt;span class="s1"&gt;'"dash-key"'&lt;/span&gt;
Lorem Ipsum

&lt;span class="nv"&gt;$cat&lt;/span&gt; file.json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.lorem["dash-key"]'&lt;/span&gt;
Lorem Ipsum

&lt;span class="nv"&gt;$cat&lt;/span&gt; file.json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; .lorem.&lt;span class="se"&gt;\"&lt;/span&gt;dash-key&lt;span class="se"&gt;\"&lt;/span&gt;
Lorem Ipsum

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

&lt;/div&gt;






&lt;p&gt;When we bring the jq query into Jenkins with a key name as a  variable. It will lead to next problem, as Jenkins have some weird way to manipulating string with single-quote and double-quote in &lt;code&gt;sh&lt;/code&gt; function.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fun read &lt;a href="https://gerg.dev/2021/03/adventures-with-escaping-quotes-in-jenkins-pipelines/" rel="noopener noreferrer"&gt;Adventures with escaping quotes in Jenkins&lt;/a&gt; and &lt;a href="https://gist.github.com/Faheetah/e11bd0315c34ed32e681616e41279ef4" rel="noopener noreferrer"&gt;Gist of weird escape on Jenkins&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then, we need to escape double-quote with Jenkins &lt;code&gt;sh&lt;/code&gt; and &lt;code&gt;jq&lt;/code&gt; with this pattern &lt;code&gt;\\\"&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;SOME_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dash-key"&lt;/span&gt;
&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;returnStdout:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;script:&lt;/span&gt; &lt;span class="s2"&gt;"cat file.json | jq -r .lorem.\\\"${SOME_KEY}\\\""&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;trim&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>jenkins</category>
      <category>json</category>
      <category>bash</category>
      <category>devops</category>
    </item>
    <item>
      <title>NextJS APIs validator with Middleware</title>
      <dc:creator>meddlesome</dc:creator>
      <pubDate>Tue, 26 May 2020 11:46:05 +0000</pubDate>
      <link>https://dev.to/meddlesome/nextjs-apis-validator-with-middleware-3njl</link>
      <guid>https://dev.to/meddlesome/nextjs-apis-validator-with-middleware-3njl</guid>
      <description>&lt;p&gt;Validate the &lt;code&gt;request.body&lt;/code&gt; is a must for every APIs development. NextJS is able to use &lt;a href="https://github.com/senchalabs/connect" rel="noopener noreferrer"&gt;Connect&lt;/a&gt; compatible Middlewares for an extendable feature on top of each request/response like ExpressJS.&lt;/p&gt;

&lt;p&gt;Here is a guide to integrating the &lt;code&gt;express-validator&lt;/code&gt;, a wrapper of &lt;code&gt;validator.js&lt;/code&gt; inside your NextJS application.&lt;/p&gt;

&lt;p&gt;First, Install &lt;code&gt;express-validator&lt;/code&gt; in NextJS project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add express-validator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, Create NextJS Middleware Helper Method as &lt;code&gt;/lib/init-middleware.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function initMiddleware(middleware) {
    return (req, res) =&amp;gt;
      new Promise((resolve, reject) =&amp;gt; {
        middleware(req, res, (result) =&amp;gt; {
          if (result instanceof Error) {
            return reject(result)
          }
          return resolve(result)
        })
      })
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, Create NextJS Validator Middleware to handle error and response out as &lt;code&gt;/lib/validate-middleware.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function validateMiddleware(validations, validationResult) {
  return async (req, res, next) =&amp;gt; {
    await Promise.all(validations.map((validation) =&amp;gt; validation.run(req)))

    const errors = validationResult(req)
    if (errors.isEmpty()) {
      return next()
    }

    res.status(422).json({ errors: errors.array() })
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it's time to integrate validate rules and middleware into your NextJS API Routes. You can use any validator.js's &lt;a href="https://github.com/validatorjs/validator.js#validators" rel="noopener noreferrer"&gt;validator functions&lt;/a&gt; as sample below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import initMiddleware from '../../../lib/init-middleware'
import validateMiddleware from '../../../lib/validate-middleware'
import { check, validationResult } from 'express-validator'

const validateBody = initMiddleware(
    validateMiddleware([
        check('first_name').isLength({min:1, max: 40}),
        check('day').isInt({ min: 1, max: 31}),
        check('gender').isIn(['male','female']),
        check('mobile_phone').isMobilePhone(['th-TH']),
        check('boolean').isBoolean(),
    ], validationResult)
)

export default async (req, res) =&amp;gt; {
  switch (req.method) {
    case "POST":
      await validateBody(req, res)

      const errors = validationResult(req)
      if (!errors.isEmpty()) {
        return res.status(422).json({ errors: errors.array() })
      }

      nextFunction(req, res)

      break;
    default:
      res.status(404).json({ message: "Request HTTP Method Incorrect." })
      break;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the &lt;code&gt;express-validator&lt;/code&gt; will be working on top of each HTTP Request to validate your &lt;code&gt;request.body&lt;/code&gt; in NextJS API Route :)&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>express</category>
      <category>middleware</category>
      <category>api</category>
    </item>
  </channel>
</rss>
