<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: victorargento</title>
    <description>The latest articles on Forem by victorargento (@victorargento).</description>
    <link>https://forem.com/victorargento</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%2F678122%2Ffc56d42f-297c-4ff7-993a-7fb2108932ce.jpeg</url>
      <title>Forem: victorargento</title>
      <link>https://forem.com/victorargento</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/victorargento"/>
    <language>en</language>
    <item>
      <title>¡Como utilizar javascript en Github Actions y hacer un cocktail!</title>
      <dc:creator>victorargento</dc:creator>
      <pubDate>Thu, 15 Sep 2022 18:51:15 +0000</pubDate>
      <link>https://forem.com/victorargento/como-utilizar-javascript-en-github-actions-y-hacer-un-cocktail-3pbn</link>
      <guid>https://forem.com/victorargento/como-utilizar-javascript-en-github-actions-y-hacer-un-cocktail-3pbn</guid>
      <description>&lt;p&gt;Hace tiempo que venía pensado en como podría ejecutar un bloque de código de Javascript en un step de Github Actions, ya que muchas veces se me hace incómodo tratar datos con comandos de Bash. Cuando me veo en estos casos, siempre digo: ¡Qué fácil sería hacer esto con Javascript! Una tarde me puse a ver si esto era capaz, tras varias pruebas me di cuenta de que sí que era posible.&lt;/p&gt;

&lt;p&gt;Gracias a que los Runners de Github nativamente contienen Node.js podemos ejecutar los scripts sin problema, e incluso si utilizamos la versión v18 de Node.js podremos hacer uso de node-fetch para hacer peticiones dentro de nuestros scripts. &lt;/p&gt;

&lt;p&gt;Para llamar a las variables que tenemos dentro del script desde otro step, deberemos hacer console.logs de los valores de la siguiente forma:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;console.log(::set-output name=NOMBRE_VARIABLE_GITHUB_ACTION::${nombreVariableJavascript})&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Después añadiremos al mismo step un campo llamado id con el valor que identifique al script. El valor lo podremos llamar tal que así.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;echo ${{ steps.id_step.outputs.NOMBRE_VARIABLE_GITHUB_ACTION }}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Para pasar inputs al script de Javascript, deberá ser a base de variables de entorno dentro del step, ya que pasárselas como argumentos no funciona correctamente.&lt;/p&gt;

&lt;p&gt;Aquí se puede ver un breve ejemplo de como se haría.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Greet myself
on:
  push:
jobs:
  greet:
    runs-on: ubuntu-latest
    steps:
      - name: Get name
        run: |
          console.log(`::set-output name=name::${process.env.ENV_NAME}`)
        shell: node {0}
        id: greet
        env:
          ENV_NAME: victor

      - name: Hello Victor
        run: echo hello ${{ steps.greet.outputs.name }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En &lt;a href="https://github.com/victorargento/victorargento" rel="noopener noreferrer"&gt;mi repositorio&lt;/a&gt; de Github he subido una action que nos devuelve la receta para hacer un cocktail y hacemos uso de un script de Javascript.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fnrepfiyj19m4fah5ghgf.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fnrepfiyj19m4fah5ghgf.PNG" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>github</category>
      <category>devops</category>
      <category>node</category>
    </item>
    <item>
      <title>Despliega tu aplicación NodeJS o Typescript con PM2</title>
      <dc:creator>victorargento</dc:creator>
      <pubDate>Thu, 02 Jun 2022 17:39:27 +0000</pubDate>
      <link>https://forem.com/victorargento/despliega-tu-aplicacion-nodejs-o-typescript-con-pm2-5fno</link>
      <guid>https://forem.com/victorargento/despliega-tu-aplicacion-nodejs-o-typescript-con-pm2-5fno</guid>
      <description>&lt;h2&gt;
  
  
  ¿Qué es PM2?
&lt;/h2&gt;

&lt;p&gt;PM2 es un &lt;strong&gt;gestor de procesos&lt;/strong&gt; que te ayuda a gestionar y mantener tu aplicación en línea y con Github Actions podremos desplegar nuestra aplicación totalmente gratis y manera sencilla.&lt;/p&gt;

&lt;p&gt;Uniendo estas dos herramientas crearemos una pipeline con la cual desplegaremos nuestra aplicación. Para ello, tendremos que configurar nuestro repositorio con los siguientes pasos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creamos la carpeta &lt;em&gt;github/workflows&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Dentro generaremos el archivo action.yml (El nombre no tiene importancia). A continuación, dejaré una muestra de una action en la que comprobamos primero nuestro código con la ejecución de unos test unitarios, y si hemos tenido éxito desplegaremos nuestro código en el servidor.&lt;/li&gt;
&lt;li&gt;Lo más seguro es que tengamos que generar unos secrets en Github para no comprometer información vulnerable como pueden ser usuario o contraseñas.
&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="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test &amp;amp; Deploy&lt;/span&gt;
  &lt;span class="s"&gt;push&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&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;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&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@v3&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="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;16'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run test&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy app&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;victorargento/pm2-deployment@main&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;remote-path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/deployment/api"&lt;/span&gt;
          &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;12.34.56.78&lt;/span&gt;
          &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.prod-user }}&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2080&lt;/span&gt;
          &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.prod-password }}&lt;/span&gt;
          &lt;span class="na"&gt;pm2-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api"&lt;/span&gt;
          &lt;span class="na"&gt;build &lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  PM2 Deployment
&lt;/h2&gt;

&lt;p&gt;La action que utilizamos para desplegar es un fork de &lt;a href="https://github.com/marketplace/actions/node-vps-deployment"&gt;Node VPS Deployment&lt;/a&gt;, a la cual he añadido funcionalidades para que se pueda hacer una build de Typescript y utilice reload en vez de restart.&lt;/p&gt;

&lt;p&gt;Emplear &lt;strong&gt;reload&lt;/strong&gt; en vez de &lt;strong&gt;restart&lt;/strong&gt; en una aplicación que es un servidor web, es mucho mejor, ya que &lt;strong&gt;restart&lt;/strong&gt; es una forma más agresiva de reiniciar nuestra aplicación. Aquí puedes consultar más información acerca de &lt;a href="https://stackoverflow.com/questions/44883269/what-is-the-difference-between-pm2-restart-and-pm2-reload#:~:text=The%20difference%20is%20documented%20here,at%20least%20one%20process%20running."&gt;ello&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Puedes darle una estrella a mi proyecto &lt;a href="https://github.com/victorargento/pm2-deployment"&gt;aquí&lt;/a&gt; ✌.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>devops</category>
      <category>node</category>
    </item>
    <item>
      <title>Como crear imágenes Distroless para Node.js y Go</title>
      <dc:creator>victorargento</dc:creator>
      <pubDate>Tue, 11 Jan 2022 21:56:55 +0000</pubDate>
      <link>https://forem.com/victorargento/como-crear-imagenes-distroless-para-nodejs-y-go-b4m</link>
      <guid>https://forem.com/victorargento/como-crear-imagenes-distroless-para-nodejs-y-go-b4m</guid>
      <description>&lt;h2&gt;
  
  
  ¿Qué es una imagen Distroless?
&lt;/h2&gt;

&lt;p&gt;Las imágenes distroless están basadas en imágenes Debian, pero son muy diferentes a las de Ubuntu. En primer lugar, Google gestiona estos contenedores, y nos da la confianza de que van a estar preparadas para no tener ningún problema.&lt;/p&gt;

&lt;p&gt;La segunda diferencia es que hay contenedores específicos para lenguajes concretos. ¿Por qué tener contenedores específicos para imágenes específicas? ¿Por qué no instalarlos todos en un solo contenedor? Además del problema del tamaño, Google ha eliminado el 90% del contenedor y ha mantenido únicamente lo que se requiere para ejecutar el lenguaje específico. Esto elimina en gran medida la cantidad de vulnerabilidades que se pueden encontrar en el contenedor. Por ejemplo, digamos que alguien es capaz y quiere ejecutar un comando en el contenedor dentro de tu cluster. ¿Sabes que pasaría? Nada, ya que estos contenedores no contienen ninguna shell. Pongamos que se ha encontrado una vulnerabilidad en un paquete de Debian. Lo más probable es que el paquete no exista en la imagen y no tengamos dicha vulnerabilidad.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué lenguajes se pueden utilizar?
&lt;/h2&gt;

&lt;p&gt;A día hoy solo se pueden utilizar estos lenguajes y versiones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Base&lt;/li&gt;
&lt;li&gt;Static&lt;/li&gt;
&lt;li&gt;Dotnet&lt;/li&gt;
&lt;li&gt;CC&lt;/li&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;Python 2.7&lt;/li&gt;
&lt;li&gt;Python 3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;También puedes consultarlas en el repositorio de imágenes de Google en &lt;a href="https://console.cloud.google.com/gcr/images/distroless/GLOBAL"&gt;este enlace&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diferencias entre la imagen static y base:
&lt;/h3&gt;

&lt;p&gt;La imagen static contiene un sistema Linux basado en glibc que contiene certificados CA, tzdata, un directorio en /etc/passwd para un usuario root y un directorio temporal en /tmp.&lt;/p&gt;

&lt;p&gt;La imagen base contiene los paquetes glibc, libssl, openssl y todo lo nombrado anteriormente en la imagen static. La mayoría de aplicaciones deberían usar base.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ventajas de Distroless
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;En la imagen no hay nada más que tu aplicación, con lo cual si alguien tiene acceso a tu cluster no podrá ejecutar ningún tipo de programa en el contenedor.&lt;/li&gt;
&lt;li&gt;Las imágenes tienden a ser más livianas.&lt;/li&gt;
&lt;li&gt;A menos paquetes, menos posibilidades de tener vulnerabilidades.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Desventajas de Distroless
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No es recomendable para desarrollar, ya que no puedes entrar al contenedor para debuggear el código.&lt;/li&gt;
&lt;li&gt;Algunas veces tu aplicación necesitará alguna dependencia del sistema, esta al no tener shell no podremos lanzar ningún comando para instalar dependencias.&lt;/li&gt;
&lt;li&gt;Solo puedes emplear un lenguaje en cada imagen.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;A continuación explicaré como construir la imagen de un servidor web tanto en Node.js como en Go. También optimizaremos las imágenes haciendo uso de multi-stage.&lt;/p&gt;

&lt;p&gt;Para ello clonaremos mi repositorio y nos situaremos en el directorio distroless:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/victorargento/victorargento.git &amp;amp;&amp;amp; cd victorargento/distroless
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Node.js
&lt;/h3&gt;

&lt;p&gt;La imagen de Node.js tiene 3 fases: construcción de la aplicación para poder ser compilada, instalación solamente de las dependencias de producción y por último transferir la aplicación a la imagen distroless.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Construimos la aplicación con las dependencias de desarrollo.
FROM node:16-alpine3.14 AS pre-build-env
WORKDIR /app
COPY package*.json ./

RUN npm install --only=development

COPY . .
RUN npm run build

# Instalamos solamente las dependencias necesarias para la ejecución de la aplicación.
FROM node:16-alpine3.14 AS build-env
WORKDIR /app
COPY package*.json ./

RUN npm install --only=production

# Copiamos la carpeta dist construida en la imagen PRE-BUILD-ENV.
COPY --from=pre-build-env /app/dist ./dist
# Este paso podemos omitirlo, ya que solamente necesitas la carpeta dist para ejecutar la aplicación,
# pero tal vez tu aplicación necesite algunos archivos que tienes en la raíz del proyecto, si ese es el caso, copia solamente archivos necesarios.
COPY . . 

# Volvemos a copiar la aplicación, pero esta vez en la imagen Distroless.
FROM gcr.io/distroless/nodejs:16
USER nonroot:nonroot
WORKDIR /app
COPY --from=build-env --chown=nonroot:nonroot /app /app
CMD ["dist/index.js"]

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

&lt;/div&gt;



&lt;p&gt;Para construir la imagen ejecutaremos el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t hello-app:node ./hello-app-node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Go
&lt;/h3&gt;

&lt;p&gt;La imagen de Go solamente tiene 2 fases: construcción del binario y transferir la aplicación a la imagen distroless.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Construimos el binario en la imagen que contiene Go.
FROM golang:1.17 as build-env

WORKDIR /go/src/app
COPY *.go ./

RUN go mod init
RUN go get -d -v ./...
RUN go vet -v
RUN go test -v

RUN CGO_ENABLED=0 go build -o /go/bin/app

# Copiamos el binario desde BUILD-ENV a la imagen Distroless.
# En este caso utilizaremos la imagen static, que contiene las dependencias mínimas,
# si nuestra aplicación depende de paquetes como glibc, libssl o openssl utilizaremos la imagen base
# FROM gcr.io/distroless/base
FROM gcr.io/distroless/static
USER nonroot:nonroot

COPY --from=build-env --chown=nonroot:nonroot /go/bin/app /
CMD ["/app"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para construir la imagen ejecutaremos el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t hello-app:go ./hello-app-go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>devops</category>
      <category>docker</category>
      <category>go</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
