<?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: Rodrigo Gomez Palacio</title>
    <description>The latest articles on DEV Community by Rodrigo Gomez Palacio (@rgomezp).</description>
    <link>https://dev.to/rgomezp</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%2F1167272%2F19035bd6-f255-45e9-9431-a473be02ab59.jpeg</url>
      <title>DEV Community: Rodrigo Gomez Palacio</title>
      <link>https://dev.to/rgomezp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rgomezp"/>
    <language>en</language>
    <item>
      <title>Automate Fine-Tuning Your LLM Models: the ChatGPT Fine-Tuning SDK</title>
      <dc:creator>Rodrigo Gomez Palacio</dc:creator>
      <pubDate>Mon, 17 Feb 2025 21:08:11 +0000</pubDate>
      <link>https://dev.to/rgomezp/fine-tune-your-chatgpt-models-with-chatgpt-fine-tuning-sdk-4ej5</link>
      <guid>https://dev.to/rgomezp/fine-tune-your-chatgpt-models-with-chatgpt-fine-tuning-sdk-4ej5</guid>
      <description>&lt;p&gt;Fine-tuning a ChatGPT model can significantly improve its accuracy and relevance for your specific use case. However, manually preparing datasets for fine-tuning can be tedious. Introducing the &lt;strong&gt;ChatGPT Fine-Tuning SDK&lt;/strong&gt;, an open-source package designed to streamline the process of generating fine-tuning datasets in JSONL format.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Why Use ChatGPT Fine-Tuning SDK?
&lt;/h2&gt;

&lt;p&gt;This SDK simplifies dataset generation by wrapping around the &lt;strong&gt;chatgpt&lt;/strong&gt; npm package. It provides a structured approach to curating training data while allowing programmatic approval, rejection, and correction of AI-generated responses. &lt;/p&gt;

&lt;p&gt;When finished, you will be left with a jsonl file you can upload directly to fine-tune a model.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔧 Installation
&lt;/h2&gt;

&lt;p&gt;You can install the package using &lt;strong&gt;npm&lt;/strong&gt; or &lt;strong&gt;yarn&lt;/strong&gt;:&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="c"&gt;# npm&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;chatgpt-fine-tuning

&lt;span class="c"&gt;# yarn&lt;/span&gt;
yarn add chatgpt-fine-tuning
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ⚙️ Configuration
&lt;/h2&gt;

&lt;p&gt;Before using the SDK, configure it with your OpenAI API key and define a system message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ChatGptFineTuning&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chatgpt-fine-tuning&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;outFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fine-tuning-output.jsonl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// required&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;systemMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Marv is a factual chatbot that is also sarcastic.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// required&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gpt4Api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ChatGptFineTuning&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GPT4_API_KEY&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// required&lt;/span&gt;
    &lt;span class="nx"&gt;systemMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;outFile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Each &lt;code&gt;sendMessage&lt;/code&gt; call returns a &lt;strong&gt;tuner&lt;/strong&gt; object, which enables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Approving the AI response&lt;/li&gt;
&lt;li&gt;Rejecting an incorrect response&lt;/li&gt;
&lt;li&gt;Fixing and correcting AI responses&lt;/li&gt;
&lt;li&gt;Logging actions to maintain a record&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example Workflow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tuner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;gpt4Api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;What is the capital of France?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Programmatic verification&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tuner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Paris&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;tuner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;approve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;tuner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;tuner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You did not provide the correct answer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Paris&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;tuner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Finished run&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📖 API Reference
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;tuner&lt;/strong&gt; Methods
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Parameters&lt;/th&gt;
&lt;th&gt;Return Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;approve()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Promise&amp;lt;void&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Approves the current response for fine-tuning.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;reject()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Promise&amp;lt;void&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rejects the response, marking it with a weight of &lt;code&gt;0&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fix(userText, assistantText, log?)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;string&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;boolean&lt;/code&gt; (optional)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Promise&amp;lt;void&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Submits a correction for the AI response with optional logging.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;log(message)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;void&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Logs a message to the output file.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;ChatMessage Properties&lt;/strong&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unique identifier for the chat message.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;text&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Text content of the message.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;role&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Role&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Role of the message sender (user, assistant, etc.).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;parentMessageId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;string&lt;/code&gt; (optional)&lt;/td&gt;
&lt;td&gt;ID of the parent message in the conversation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;conversationId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;string&lt;/code&gt; (optional)&lt;/td&gt;
&lt;td&gt;ID of the conversation this message belongs to.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The API follows the same structure as the &lt;a href="https://www.npmjs.com/package/chatgpt" rel="noopener noreferrer"&gt;chatgpt npm package&lt;/a&gt;, ensuring familiarity if you've used it before.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤝 Contributing
&lt;/h2&gt;

&lt;p&gt;Contributions, bug reports, and feature requests are welcome! Check out the &lt;a href="https://github.com/your-repo/issues" rel="noopener noreferrer"&gt;issues page&lt;/a&gt; to get involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⭐ Show Your Support
&lt;/h2&gt;

&lt;p&gt;If this SDK has been helpful, consider giving it a &lt;strong&gt;⭐&lt;/strong&gt; on GitHub!&lt;/p&gt;

&lt;h2&gt;
  
  
  📝 License
&lt;/h2&gt;

&lt;p&gt;This project is &lt;strong&gt;MIT licensed&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Get Started Now!
&lt;/h3&gt;

&lt;p&gt;Fine-tune your ChatGPT models effortlessly with &lt;strong&gt;ChatGPT Fine-Tuning SDK&lt;/strong&gt; and take AI customization to the next level!&lt;/p&gt;

</description>
      <category>llm</category>
      <category>chatgpt</category>
      <category>tuning</category>
      <category>ai</category>
    </item>
    <item>
      <title>To Obfuscate or Not Obfuscate (React Native)</title>
      <dc:creator>Rodrigo Gomez Palacio</dc:creator>
      <pubDate>Mon, 05 Aug 2024 04:59:50 +0000</pubDate>
      <link>https://dev.to/rgomezp/to-obfuscate-or-not-obfuscate-react-native-3mkm</link>
      <guid>https://dev.to/rgomezp/to-obfuscate-or-not-obfuscate-react-native-3mkm</guid>
      <description>&lt;h2&gt;
  
  
  Protecting Your React Native App's Intellectual Property: Using Hermes and JavaScript Obfuscation
&lt;/h2&gt;

&lt;p&gt;Let's just jump to the point.&lt;/p&gt;

&lt;p&gt;Code obfuscation is a software development process that makes source or machine code more difficult for humans or computers to understand.&lt;/p&gt;

&lt;p&gt;This does &lt;strong&gt;not&lt;/strong&gt; protect your app from being reverse-engineered. Someone with enough time, resources, or dedication can reverse-engineer your app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NEVER&lt;/strong&gt; include secrets on the client-side app, even if it's obfuscated.&lt;/p&gt;

&lt;p&gt;So in the world of React Native, should you obfuscate your code?&lt;/p&gt;

&lt;p&gt;To answer this question we have to first understand how React Native works. Your Javascript code will contain all your business &amp;amp; app logic. It runs and communicates with the native level through the "bridge." When something changes, the Javascript side sends a message to the native side telling it to update the UI, interact with the camera, etc...&lt;/p&gt;

&lt;h3&gt;
  
  
  Hermes
&lt;/h3&gt;

&lt;p&gt;When it comes to your JS code, should you obfuscate it? If you're running the &lt;strong&gt;hermes&lt;/strong&gt; engine, for most apps this should be enough. This is because hermes inherently obfuscates your code by compiling your JS to optimized bytecode ahead of time. While it can be de-obfuscated, it adds a hurdle that for most attackers may not be worth it -- especially if it's a low-risk app.&lt;/p&gt;

&lt;p&gt;If you're not running the hermes engine and your JS code is included as plaintext in the APK, maybe you should consider switching to hermes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Proguard / R8
&lt;/h3&gt;

&lt;p&gt;Should you enable proguard / R8 to obfuscate the native code? In the React Native world, you shouldn't be worried about IP theft of the native code since there's likely little going on here -- barring some heavy proprietary native customization.&lt;/p&gt;

&lt;p&gt;Now, should you enable proguard / R8 for the minification benefits? Up to you. If your app is big, this might be worth it. Just know that it comes at the cost of making debugging more difficult / viewing crash logs, etc... It also might break your app if you're using 3rd party libraries that may introduce regressions.&lt;/p&gt;

&lt;p&gt;For most React Native apps, the critical logic is in JavaScript, but some native modules might still benefit from obfuscation if they contain sensitive logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sensitive Data
&lt;/h3&gt;

&lt;p&gt;If your app contains important user data such as financial or health data, proper obfuscation is probably worth the overhead just to be on the safe side.&lt;/p&gt;

&lt;h3&gt;
  
  
  TLDR
&lt;/h3&gt;

&lt;p&gt;If you're concerned about IP theft, using the hermes engine should be enough for low-value apps. If you have proprietary native logic, consider using proguard / R8 while understanding the drawbacks. If your app is large, consider proguard / R8 for its minification capabilities. &lt;/p&gt;

&lt;p&gt;Finally please feed the algorithm and give me some feedback if my post helped you 🙏!&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow Me
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/rogomezpalacio/" rel="noopener noreferrer"&gt;&lt;br&gt;
    &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FLinkedIn-blue%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="LinkedIn Badge" width="91" height="28"&gt;&lt;br&gt;
  &lt;/a&gt;&lt;br&gt;
  &lt;a href="https://twitter.com/ro_gmzp" rel="noopener noreferrer"&gt;&lt;br&gt;
    &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FTwitter-blue%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="Twitter Badge" width="83" height="28"&gt;&lt;br&gt;
  &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out my other articles and projects!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgomezp/introducing-expo-pod-pinner-elevate-your-expo-managed-workflow-with-precision-4k67"&gt;Expo Pod Pinner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgomezp/introducing-the-unofficial-perplexity-sdk-for-nodejs-52kp"&gt;Perplexity SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fitnesswolf.app/2024/07/28/the-only-2-routine/" rel="noopener noreferrer"&gt;Fitness Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>reactnative</category>
      <category>expo</category>
      <category>obfuscation</category>
      <category>android</category>
    </item>
    <item>
      <title>Introducing Expo Pod Pinner: Elevate Your Expo Managed Workflow with Precision</title>
      <dc:creator>Rodrigo Gomez Palacio</dc:creator>
      <pubDate>Wed, 27 Mar 2024 20:37:52 +0000</pubDate>
      <link>https://dev.to/rgomezp/introducing-expo-pod-pinner-elevate-your-expo-managed-workflow-with-precision-4k67</link>
      <guid>https://dev.to/rgomezp/introducing-expo-pod-pinner-elevate-your-expo-managed-workflow-with-precision-4k67</guid>
      <description>&lt;p&gt;In the dynamic realm of mobile development, the Expo framework stands as a beacon of efficiency and ease, especially for those favoring a managed workflow. Today, I'm thrilled to unveil an addition to this ecosystem, crafted to further refine and enhance your development experience: Expo Pod Pinner.&lt;/p&gt;

&lt;p&gt;The plugin is designed to bring more control and stability directly to your project's Podfile without stepping outside the managed workflow’s comfort zone.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Glance at Expo Pod Pinner
&lt;/h2&gt;

&lt;p&gt;Expo Pod Pinner enables developers to specify and pin pod versions explicitly, thus ensuring consistent and stable dependency management across all installations and updates.&lt;/p&gt;

&lt;p&gt;This plugin not only fortifies project stability but also elevates the overall development workflow by allowing direct modifications to the Podfile—a feature that aligns seamlessly with the expectations of modern mobile development.&lt;/p&gt;

&lt;p&gt;Developers can also work around native regressions by pinning pods to working versions.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Embark with Expo Pod Pinner
&lt;/h2&gt;

&lt;p&gt;Setting sail with Expo Pod Pinner is straightforward. Simply integrate the plugin into your project with a one-liner command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx expo install expo-pod-pinner&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;To weave this plugin into the fabric of your project, add it to the plugin array in your app's configuration file (either app.json or app.config.js). Here’s how you can do it:&lt;br&gt;
&lt;/p&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;"plugins"&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;span class="s2"&gt;"expo-pod-pinner"&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;"targetName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YourTargetName"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"pods"&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;span class="nl"&gt;"PodName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.0.0"&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;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;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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;plugins&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;expo-pod-pinner&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;targetName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YourTargetName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pods&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PodName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuration Props
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;targetName&lt;/code&gt;: Specify the target in your Podfile where the pods should be added.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pods&lt;/code&gt;: Define an array of objects with the pod names and their versions to pin.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Join the Expo Pod Pinner Community
&lt;/h2&gt;

&lt;p&gt;I'm on a mission to make your Expo development journey as seamless and enjoyable as possible. Contributions, issues, and feature requests are warmly welcomed. Dive into the &lt;a href="https://github.com/rgomezp/expo-pod-pinner/issues"&gt;issues page&lt;/a&gt; to join the conversation or suggest enhancements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show Your Support
&lt;/h2&gt;

&lt;p&gt;Has Expo Pod Pinner enriched your development experience? A star on our GitHub page is much appreciated and fuels further innovation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow Me
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/rogomezpalacio/"&gt;&lt;br&gt;
    &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JoJYkENP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/LinkedIn-blue%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="LinkedIn Badge" width="111" height="28"&gt;&lt;br&gt;
  &lt;/a&gt;&lt;br&gt;
  &lt;a href="https://twitter.com/ro_gmzp"&gt;&lt;br&gt;
    &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s9ZtOEe1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Twitter-blue%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="Twitter Badge" width="104" height="28"&gt;&lt;br&gt;
  &lt;/a&gt;&lt;/p&gt;

</description>
      <category>expo</category>
      <category>reactnative</category>
      <category>eas</category>
      <category>ios</category>
    </item>
    <item>
      <title>Don't Pay for EAS! How to Set Up an EAS Local Build on GitHub Actions</title>
      <dc:creator>Rodrigo Gomez Palacio</dc:creator>
      <pubDate>Wed, 14 Feb 2024 21:56:24 +0000</pubDate>
      <link>https://dev.to/rgomezp/how-to-set-up-an-eas-local-build-on-github-actions-1l0i</link>
      <guid>https://dev.to/rgomezp/how-to-set-up-an-eas-local-build-on-github-actions-1l0i</guid>
      <description>&lt;p&gt;You're out of credits!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Should you pay for EAS?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you're a React Native developer using Expo, you might be familiar with the convenience of Expo Application Services (EAS). EAS provides a suite of tools that streamline the process of developing and deploying your React Native apps. &lt;/p&gt;

&lt;p&gt;One drawback of EAS is the price, which at $1-$4 per build may quickly add up for a developer just getting started on a project.&lt;/p&gt;

&lt;p&gt;Luckily, one of the great features of the EAS CLI is the ability to perform local builds, and integrating this with GitHub Actions can significantly automate your development workflow and save you money!&lt;/p&gt;

&lt;p&gt;In this post, we'll walk through the steps to set up an EAS local build on GitHub Actions.&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%2Fuuau25zy6tzzzrzanwwm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuuau25zy6tzzzrzanwwm.jpg" alt="EAS CLI + Github" width="750" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing &amp;amp; Build Times
&lt;/h2&gt;

&lt;p&gt;It's important to compare prices and build times, to see when this implementation makes sense.&lt;/p&gt;

&lt;p&gt;Let's start with GitHub Actions. If you're trying to optimize for cost, you're likely on the free GitHub plan or the basic $4 Github Teams/Pro plan. You're going to need to run iOS builds on a macOS while Ubuntu should work just fine for Android.&lt;/p&gt;

&lt;p&gt;While build times vary, for simplicity, an average build takes about 35 minutes. At &lt;strong&gt;$0.008 PPM&lt;/strong&gt; (price per minute) for Ubuntu 2-core and &lt;strong&gt;$0.08 PPM&lt;/strong&gt; for macOS 3-core, that comes out to &lt;strong&gt;$0.28 per build for Android&lt;/strong&gt; and &lt;strong&gt;$2.80 for iOS.&lt;/strong&gt; That's an expensive iOS build.&lt;/p&gt;

&lt;p&gt;Now let's look at EAS pricing. Depending on your choice of resources, your potential EAS build will use more cores and thus run a lot faster than on GitHub Actions. That may be worth paying for depending on your needs.&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%2Fp25a2o0e4b3n41ig59sl.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%2Fp25a2o0e4b3n41ig59sl.png" alt="EAS Pricing" width="568" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see above, however, builds are pricy on EAS as well. That said, if build time is not a priority, you can find big savings on the Android side by going with GitHub Actions given the low cost of running Ubuntu.&lt;/p&gt;

&lt;p&gt;Thus, your choice between EAS or GitHub Actions depends largely on a) how fast you need the build to run, and b) the frequency of your builds since running lots of builds will quickly add up.&lt;/p&gt;

&lt;p&gt;For iOS builds, I think EAS comes out slightly ahead at a flat $2 per build if you go with the iOS medium worker size.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Step 1: Understanding the Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before diving into the setup, ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A React Native project managed by Expo.&lt;/li&gt;
&lt;li&gt;A GitHub repository for your project.&lt;/li&gt;
&lt;li&gt;Basic knowledge of GitHub Actions and workflows.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Setting Up Your GitHub Actions Workflow
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Create a Workflow File&lt;/strong&gt;:&lt;br&gt;
In your project repository, create a new file in the &lt;code&gt;.github/workflows&lt;/code&gt; directory. You can name it something like &lt;code&gt;build.yml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build App&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;os&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;choice&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;OS to build on. Ubuntu is faster, MacOS supports iOS builds&lt;/span&gt;
        &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;macos-latest&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
      &lt;span class="na"&gt;platform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;choice&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Platform to build for&lt;/span&gt;
        &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;android&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ios&lt;/span&gt;
      &lt;span class="na"&gt;profile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;choice&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build profile to use&lt;/span&gt;
        &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;development&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;preview&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
      &lt;span class="na"&gt;should_submit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boolean&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Whether to perform the submit step&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event.inputs.os }}&lt;/span&gt;
    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;18.x&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;🏗 Setup repo&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;🏗 Setup Node&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v2&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.node }}&lt;/span&gt;
        &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;🏗 Setup Expo and EAS&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;expo/expo-github-action@v7&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.EXPO_TOKEN }}&lt;/span&gt;
        &lt;span class="na"&gt;expo-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;latest&lt;/span&gt;
        &lt;span class="na"&gt;eas-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;latest&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;📦 Install dependencies&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;📋 Test project&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn test&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;👷 Build app&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;eas build --local \&lt;/span&gt;
          &lt;span class="s"&gt;--non-interactive \&lt;/span&gt;
          &lt;span class="s"&gt;--output=./app-build \&lt;/span&gt;
          &lt;span class="s"&gt;--platform=${{ github.event.inputs.platform }} \&lt;/span&gt;
          &lt;span class="s"&gt;--profile=${{ github.event.inputs.profile }}&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;🚢 Submit&lt;/span&gt;
      &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event.inputs.should_submit }}&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;eas submit -p ${{ github.event.inputs.platform }} --profile ${{ github.event.inputs.profile }} --path app-build&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add Required Secrets&lt;/strong&gt;:&lt;br&gt;
For EAS to work, you need to add your Expo credentials as secrets in your GitHub repository. Go to your repository Settings -&amp;gt; Secrets and variables -&amp;gt; Actions. This is where you will paste in your &lt;a href="https://docs.expo.dev/accounts/programmatic-access/" rel="noopener noreferrer"&gt;access token&lt;/a&gt;. Double-check that you are creating the robot token at the right level (e.g. wherever your app is).&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%2Faakw62k2o322xjv97zy0.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%2Faakw62k2o322xjv97zy0.png" alt="Github Secrets" width="800" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, add any other required secrets you may need. A common example is the Google Services files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google Services Files&lt;/strong&gt;&lt;br&gt;
If you are not using Google Services files, skip ahead.&lt;/p&gt;

&lt;p&gt;Problem: consider the scenario where your project needs these files, but you don't want to commit them. If that's the case, Github Actions wouldn't have access to their contents.&lt;/p&gt;

&lt;p&gt;Solution: base64-encode the files, add them as secrets to Github, and then use a &lt;a href="https://docs.expo.dev/build-reference/npm-hooks/" rel="noopener noreferrer"&gt;pre-install hook&lt;/a&gt; to re-create the files in Github Actions' cloud environment.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;$ base64 -i googleServices/google-services.json&lt;/code&gt; (repeat for Plist, other files)&lt;/li&gt;
&lt;li&gt;Add encoded strings as secrets to Github Actions&lt;/li&gt;
&lt;li&gt;Write a script to decode them into their original files:
&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="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# Create the directory if it doesn't exist&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ./googleServices

&lt;span class="c"&gt;# Decode the base64 strings and create the files&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$GOOGLE_SERVICES_JSON_BASE64&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;--decode&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ./googleServices/google-services.json
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$GOOGLE_SERVICES_PLIST_BASE64&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;--decode&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ./googleServices/GoogleService-Info.plist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Call that script from the &lt;code&gt;eas-build-pre-install&lt;/code&gt; hook in your package.json.&lt;/li&gt;
&lt;li&gt;Make the variables accessible via our build YML:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;👷 Build app&lt;/span&gt;
      &lt;span class="s"&gt;env&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;GOOGLE_SERVICES_JSON_BASE64&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GOOGLE_SERVICES_JSON_BASE64 }}&lt;/span&gt;
        &lt;span class="na"&gt;GOOGLE_SERVICES_PLIST_BASE64&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GOOGLE_SERVICES_PLIST_BASE64 }}&lt;/span&gt;
        &lt;span class="na"&gt;GOOGLE_SERVICES_JSON&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.GOOGLE_SERVICES_JSON }}&lt;/span&gt;
        &lt;span class="na"&gt;GOOGLE_SERVICES_PLIST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.GOOGLE_SERVICES_PLIST }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Note that in this example, I am using &lt;code&gt;GOOGLE_SERVICES_JSON&lt;/code&gt; and &lt;code&gt;GOOGLE_SERVICES_PLIST&lt;/code&gt; as well. These contain the paths to the files.&lt;/p&gt;

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

&lt;p&gt;This is applicable if you don't have a hard-coded path in your app.json / app.config.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ios: {
    googleServicesFile: process.env.GOOGLE_SERVICES_PLIST,
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Testing the Workflow
&lt;/h3&gt;

&lt;p&gt;Once you've set up the workflow file:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Commit and Push&lt;/strong&gt;: Commit the changes and push them to your repository.&lt;/li&gt;
&lt;li&gt;Trigger the build via the Github Actions tab.&lt;/li&gt;
&lt;li&gt;Click on the build to monitor it. &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 4: Debugging and Optimization
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If the build fails, check the logs in the Actions tab for errors.&lt;/li&gt;
&lt;li&gt;Optimize your workflow by caching dependencies or splitting jobs.&lt;/li&gt;
&lt;li&gt;If you know your tests pass, exclude that step and others to iterate more quickly until your build is stable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Integrating EAS local builds into GitHub Actions can greatly enhance your CI/CD pipeline and save you some of the green. Remember, this setup might vary slightly depending on your project's specific needs, so feel free to adjust it as necessary.&lt;/p&gt;

&lt;p&gt;And finally please feed the algorithm and give me some feedback if my post helped you 🙏!&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow Me
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/rogomezpalacio/" rel="noopener noreferrer"&gt;&lt;br&gt;
    &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FLinkedIn-blue%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="LinkedIn Badge" width="111" height="28"&gt;&lt;br&gt;
  &lt;/a&gt;&lt;br&gt;
  &lt;a href="https://twitter.com/ro_gmzp" rel="noopener noreferrer"&gt;&lt;br&gt;
    &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FTwitter-blue%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="Twitter Badge" width="83" height="28"&gt;&lt;br&gt;
  &lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Check out my other articles and projects!
&lt;/h2&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%2Fpbmyq53in8bvoyjtl1hn.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%2Fpbmyq53in8bvoyjtl1hn.png" alt="Image description" width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://fitnesswolf.app" rel="noopener noreferrer"&gt;FitnessWolf App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgomezp/introducing-expo-pod-pinner-elevate-your-expo-managed-workflow-with-precision-4k67"&gt;Expo Pod Pinner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgomezp/introducing-the-unofficial-perplexity-sdk-for-nodejs-52kp"&gt;Perplexity SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fitnesswolf.app/2024/07/28/the-only-2-routine/" rel="noopener noreferrer"&gt;Fitness Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>expo</category>
      <category>reactnative</category>
      <category>eas</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>Introducing the Unofficial Perplexity SDK for Node.js</title>
      <dc:creator>Rodrigo Gomez Palacio</dc:creator>
      <pubDate>Wed, 07 Feb 2024 08:33:17 +0000</pubDate>
      <link>https://dev.to/rgomezp/introducing-the-unofficial-perplexity-sdk-for-nodejs-52kp</link>
      <guid>https://dev.to/rgomezp/introducing-the-unofficial-perplexity-sdk-for-nodejs-52kp</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;In today's ever-evolving tech landscape, innovative tools and frameworks are pivotal in shaping how we interact with technology. One such groundbreaking addition is the Perplexity.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/rgomezp/perplexity-sdk"&gt;Unofficial Perplexity SDK for Node.js&lt;/a&gt; is a tool designed to bring you access to Perplexity.ai on Node.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it was made
&lt;/h2&gt;

&lt;p&gt;I built this project using &lt;a href="https://www.openapis.org/"&gt;OpenAPI&lt;/a&gt;. OpenAPI, an open-source format, played a crucial role in easily generating the SDK and will allow for simple updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&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;# npm&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;perplexity-sdk

&lt;span class="c"&gt;# yarn&lt;/span&gt;
yarn add perplexity-sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Perplexity&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;perplexity-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ChatCompletionsPostRequestModelEnum&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;perplexity-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PERPLEXITY_API_KEY&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;YOUR_API_KEY&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;perplexity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Perplexity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;perplexity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chatCompletionsPost&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ChatCompletionsPostRequestModelEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Mistral7bInstruct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;role&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Your prompt here&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Show your support
&lt;/h2&gt;

&lt;p&gt;Please give a ⭐️ if this &lt;a href="https://github.com/rgomezp/perplexity-sdk"&gt;project&lt;/a&gt; helped you! That's all I ask.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
