fix(ci): use plain docker build instead of buildx (runner /dev/null issue)
CI/CD Pipeline / Build & Deploy (push) Failing after 17s
CI/CD Pipeline / Build & Deploy (push) Failing after 17s
This commit is contained in:
@@ -11,23 +11,11 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Build and push Docker image
|
||||||
uses: docker/setup-buildx-action@v3
|
run: |
|
||||||
|
docker login gitlab.impresion3d.pro -u "${{ secrets.DOCKER_USERNAME }}" -p "${{ secrets.DOCKER_PASSWORD }}"
|
||||||
- name: Login to registry
|
docker build -t gitlab.impresion3d.pro/root/davidaragon-portfolio:latest .
|
||||||
uses: docker/login-action@v3
|
docker push gitlab.impresion3d.pro/root/davidaragon-portfolio:latest
|
||||||
with:
|
|
||||||
registry: gitlab.impresion3d.pro
|
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Build and push
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ./Dockerfile
|
|
||||||
push: true
|
|
||||||
tags: gitlab.impresion3d.pro/root/davidaragon-portfolio:latest
|
|
||||||
|
|
||||||
- name: Deploy to Portainer
|
- name: Deploy to Portainer
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
---
|
|
||||||
title: "De Orfebre a Builder: Por Qué Empiezo a Construir en Público"
|
|
||||||
description: "No empecé como developer. Empecé trabajando metal con mis manos. Hoy construyo software. Esta es mi historia."
|
|
||||||
publishDate: 2026-05-11
|
|
||||||
author: "David Aragón"
|
|
||||||
tags: ["build-in-public", "introduccion", "background"]
|
|
||||||
category: "personal"
|
|
||||||
featured: true
|
|
||||||
draft: false
|
|
||||||
---
|
|
||||||
|
|
||||||
# De Orfebre a Builder: Por Qué Empiezo a Construir en Público
|
|
||||||
|
|
||||||
No empecé en tech. Empecé trabajando metal con mis manos.
|
|
||||||
|
|
||||||
Fui orfebre de profesión. Luego fotógrafo profesional durante 13 años. Después formador para LinkedIn Learning, donde enseñaba sobre servidores NAS y almacenamiento. Más tarde developer Python en NTT Data. Y ahora trabajo en KEO Connectivity con protocolos IoT para sistemas de energía.
|
|
||||||
|
|
||||||
Caminos extraños. Pero todos conectados por lo mismo: **obsesión por entender cómo funcionan las cosas, y luego hacerlas funcionar mejor**.
|
|
||||||
|
|
||||||
## El Patrón
|
|
||||||
|
|
||||||
Cuando era fotógrafo, no podía permitirme el equipo que necesitaba. Así que lo improvisaba. Construía soportes, modificaba accesorios, hacía funcionar lo que tenía.
|
|
||||||
|
|
||||||
Ese mismo impulso me llevó a montar mi propia impresora 3D desde cero. A trastear con Arduino. A aprender Python para automatizar flujos de trabajo en Qloudea mientras gestionaba redes sociales y daba soporte técnico.
|
|
||||||
|
|
||||||
**El patrón siempre es el mismo: identificar un problema, obsesionarse con resolverlo, aprender lo que haga falta para solucionarlo.**
|
|
||||||
|
|
||||||
## Por Qué Ahora
|
|
||||||
|
|
||||||
Después de años resolviendo problemas para otros, decidí resolver problemas para mí. Construir mis propios productos.
|
|
||||||
|
|
||||||
No tengo MBA. No tengo funding. No tengo equipo. Solo tengo experiencia construyendo cosas, enseñando lo que aprendo, y una tolerancia anormalmente alta a no saber qué estoy haciendo.
|
|
||||||
|
|
||||||
Y decidí hacerlo en público porque:
|
|
||||||
|
|
||||||
1. **Responsabilidad**: Es más difícil abandonar cuando compartes progreso públicamente
|
|
||||||
2. **Enseñar**: Siempre he sido formador. Compartir lo que aprendo es parte de quién soy
|
|
||||||
3. **Comunidad**: Quiero conectar con otros builders españoles que están en el mismo viaje
|
|
||||||
|
|
||||||
## En Qué Estoy Trabajando
|
|
||||||
|
|
||||||
Actualmente estoy enfocado en **WarrantyHub**, una plataforma digital para que usuarios finales gestionen las garantías de sus productos del hogar desde un solo lugar.
|
|
||||||
|
|
||||||
¿Por qué garantías? Porque es un problema que todos tenemos: papeles perdidos, tickets desorganizados, no saber dónde está la garantía cuando la necesitas. Y cuando algo se rompe, el proceso de reclamar es un caos.
|
|
||||||
|
|
||||||
Estoy usando IA agresivamente para acelerar desarrollo. No porque sea trendy. Porque cuando eres solo developer, solo marketer, solo product manager, solo support, necesitas cada ventaja que puedas conseguir.
|
|
||||||
|
|
||||||
## Qué Esperar
|
|
||||||
|
|
||||||
Voy a compartir lanzamientos, aprendizajes técnicos, decisiones de producto, y fracasos (porque enseñan más que los éxitos).
|
|
||||||
|
|
||||||
No esperes posts motivacionales genéricos ni hilos de X reciclados. Esto es documentación de un viaje real.
|
|
||||||
|
|
||||||
Si eres builder, esto es también para ti.
|
|
||||||
|
|
||||||
Nos vemos en el próximo post. 🚀
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
_Sígueme en [X](https://twitter.com/davidaragon) para updates más frecuentes._
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
title: "From Goldsmith to Builder: Why I'm Building in Public"
|
||||||
|
description: "I didn't start as a developer. I started working metal with my hands. Today I build software. This is my story."
|
||||||
|
publishDate: 2026-05-11
|
||||||
|
author: "David Aragón"
|
||||||
|
tags: ["build-in-public", "introduction", "background"]
|
||||||
|
category: "personal"
|
||||||
|
featured: true
|
||||||
|
draft: false
|
||||||
|
---
|
||||||
|
|
||||||
|
# From Goldsmith to Builder: Why I'm Building in Public
|
||||||
|
|
||||||
|
I didn't start in tech. I started working metal with my hands.
|
||||||
|
|
||||||
|
I was a goldsmith by trade. Then a professional photographer for 13 years. Later a trainer for LinkedIn Learning, teaching about NAS servers and storage. Then a Python developer at NTT Data. And now I work at KEO Connectivity with IoT protocols for energy systems.
|
||||||
|
|
||||||
|
Strange paths. But all connected by the same thing: **obsession with understanding how things work, and then making them work better**.
|
||||||
|
|
||||||
|
## The Pattern
|
||||||
|
|
||||||
|
When I was a photographer, I couldn't afford the equipment I needed. So I improvised. Built supports, modified accessories, made what I had work.
|
||||||
|
|
||||||
|
That same impulse led me to build my own 3D printer from scratch. To tinker with Arduino. To learn Python to automate workflows at Qloudea while managing social media and providing technical support.
|
||||||
|
|
||||||
|
**The pattern is always the same: identify a problem, obsess over solving it, learn whatever it takes to fix it.**
|
||||||
|
|
||||||
|
## Why Now
|
||||||
|
|
||||||
|
After years solving problems for others, I decided to solve problems for myself. Build my own products.
|
||||||
|
|
||||||
|
I don't have an MBA. I don't have funding. I don't have a team. I just have experience building things, teaching what I learn, and an abnormally high tolerance for not knowing what I'm doing.
|
||||||
|
|
||||||
|
And I decided to do it in public because:
|
||||||
|
|
||||||
|
1. **Accountability**: It's harder to quit when you share progress publicly
|
||||||
|
2. **Teaching**: I've always been a trainer. Sharing what I learn is part of who I am
|
||||||
|
3. **Community**: I want to connect with other Spanish builders on the same journey
|
||||||
|
|
||||||
|
## What I'm Working On
|
||||||
|
|
||||||
|
Currently focused on **WarrantyHub**, a digital warranty management platform for home users.
|
||||||
|
|
||||||
|
Why warranties? Because I saw the problem in real life: chaotic management with papers, Excel, lost emails. And because there's room for a Spanish solution that understands the local market.
|
||||||
|
|
||||||
|
I'm using AI aggressively to accelerate development. Not because it's trendy. Because when you're sole developer, sole marketer, sole product manager, sole support, you need every advantage you can get.
|
||||||
|
|
||||||
|
## What to Expect
|
||||||
|
|
||||||
|
I'll share launches, technical learnings, product decisions, and failures (because they teach more than successes).
|
||||||
|
|
||||||
|
Don't expect generic motivational posts or recycled X threads. This is documentation of a real journey.
|
||||||
|
|
||||||
|
If you're a builder, this is also for you.
|
||||||
|
|
||||||
|
See you in the next post. 🚀
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_Follow me on [X](https://twitter.com/davidaragon) for more frequent updates._
|
||||||
+66
-49
@@ -19,8 +19,8 @@ const blogPosts = (await getCollection('blog'))
|
|||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout
|
<BaseLayout
|
||||||
title="Inicio"
|
title="Home"
|
||||||
description="Portfolio personal de David Aragón - Builder construyendo productos y compartiendo el viaje"
|
description="David Aragón's portfolio - Builder creating products and sharing the journey"
|
||||||
>
|
>
|
||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
@@ -37,15 +37,15 @@ const blogPosts = (await getCollection('blog'))
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex-1 text-center md:text-left">
|
<div class="flex-1 text-center md:text-left">
|
||||||
<h1 class="text-4xl md:text-5xl font-bold mb-6">
|
<h1 class="text-4xl md:text-5xl font-bold mb-6">
|
||||||
Hola, soy <span class="text-primary">David Aragón</span>
|
Hi, I'm <span class="text-primary">David Aragón</span>
|
||||||
</h1>
|
</h1>
|
||||||
<p class="text-xl text-text-secondary mb-6 leading-relaxed">
|
<p class="text-xl text-text-secondary mb-6 leading-relaxed">
|
||||||
Builder construyendo productos que resuelven problemas reales.
|
Builder creating products that solve real problems.
|
||||||
De orfebre a fotógrafo a developer. Ahora construyendo en público.
|
From goldsmith to photographer to developer. Now building in public.
|
||||||
</p>
|
</p>
|
||||||
<p class="text-lg text-text-secondary mb-8">
|
<p class="text-lg text-text-secondary mb-8">
|
||||||
Actualmente trabajando en <strong class="text-primary">WarrantyHub</strong> -
|
Currently working on <strong class="text-primary">WarrantyHub</strong> -
|
||||||
gestión digital de garantías para hogares.
|
digital warranty management for home users.
|
||||||
</p>
|
</p>
|
||||||
<div class="flex flex-wrap justify-center md:justify-start gap-4">
|
<div class="flex flex-wrap justify-center md:justify-start gap-4">
|
||||||
<a
|
<a
|
||||||
@@ -53,14 +53,14 @@ const blogPosts = (await getCollection('blog'))
|
|||||||
class="bg-primary hover:bg-primary/80 text-background px-8 py-3 rounded-lg
|
class="bg-primary hover:bg-primary/80 text-background px-8 py-3 rounded-lg
|
||||||
font-semibold transition-colors"
|
font-semibold transition-colors"
|
||||||
>
|
>
|
||||||
Leer Blog
|
Read Blog
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="/about"
|
href="/about"
|
||||||
class="bg-surface hover:bg-surface/80 text-text-primary px-8 py-3 rounded-lg
|
class="bg-surface hover:bg-surface/80 text-text-primary px-8 py-3 rounded-lg
|
||||||
font-semibold border border-text-tertiary/20 transition-colors"
|
font-semibold border border-text-tertiary/20 transition-colors"
|
||||||
>
|
>
|
||||||
Sobre Mí
|
About Me
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -70,36 +70,44 @@ const blogPosts = (await getCollection('blog'))
|
|||||||
<!-- Latest Blog Posts -->
|
<!-- Latest Blog Posts -->
|
||||||
<section class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
|
<section class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
|
||||||
<div class="flex items-center justify-between mb-8">
|
<div class="flex items-center justify-between mb-8">
|
||||||
<h2 class="text-3xl font-bold">Últimas Publicaciones</h2>
|
<h2 class="text-3xl font-bold">Latest Posts</h2>
|
||||||
<a
|
<a
|
||||||
href="/blog"
|
href="/blog"
|
||||||
class="text-primary hover:text-secondary transition-colors font-medium"
|
class="text-primary hover:text-secondary transition-colors font-medium"
|
||||||
>
|
>
|
||||||
Ver todas →
|
View all →
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{blogPosts.length > 0 ? (
|
{blogPosts.length > 0 ? (
|
||||||
blogPosts.map(post => (
|
blogPosts.map((post) => (
|
||||||
<Card href={`/blog/${post.slug}`}>
|
<Card href={`/blog/${post.slug}`}>
|
||||||
<div class="mb-3">
|
<div class="mb-4">
|
||||||
<Tag label={post.data.category} variant="secondary" />
|
<time class="text-sm text-text-tertiary">
|
||||||
</div>
|
|
||||||
<h3 class="text-xl font-semibold mb-2 text-text-primary">{post.data.title}</h3>
|
|
||||||
<p class="text-text-secondary mb-4">{post.data.description}</p>
|
|
||||||
<div class="flex items-center justify-between text-sm text-text-tertiary">
|
|
||||||
<time datetime={post.data.publishDate.toISOString()}>
|
|
||||||
{formatDate(post.data.publishDate)}
|
{formatDate(post.data.publishDate)}
|
||||||
</time>
|
</time>
|
||||||
<span class="text-primary font-medium">Leer más →</span>
|
</div>
|
||||||
|
<h3 class="text-xl font-semibold mb-3 text-text-primary group-hover:text-primary transition-colors">
|
||||||
|
{post.data.title}
|
||||||
|
</h3>
|
||||||
|
<p class="text-text-secondary mb-4 line-clamp-3">
|
||||||
|
{post.data.description}
|
||||||
|
</p>
|
||||||
|
<div class="flex flex-wrap gap-2 mb-4">
|
||||||
|
{post.data.tags?.slice(0, 3).map((tag: string) => (
|
||||||
|
<Tag>{tag}</Tag>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div class="text-sm">
|
||||||
|
<span class="text-primary font-medium">Read more →</span>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<div class="col-span-full text-center py-12">
|
<div class="col-span-full text-center py-12">
|
||||||
<p class="text-text-secondary">
|
<p class="text-text-secondary">
|
||||||
Publicaciones próximamente. Suscríbete para recibir actualizaciones.
|
Posts coming soon. Subscribe to receive updates.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -110,28 +118,33 @@ const blogPosts = (await getCollection('blog'))
|
|||||||
{projects.length > 0 && (
|
{projects.length > 0 && (
|
||||||
<section class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
|
<section class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
|
||||||
<div class="flex items-center justify-between mb-8">
|
<div class="flex items-center justify-between mb-8">
|
||||||
<h2 class="text-3xl font-bold">Proyectos</h2>
|
<h2 class="text-3xl font-bold">Projects</h2>
|
||||||
<a
|
<a
|
||||||
href="/projects"
|
href="/projects"
|
||||||
class="text-primary hover:text-secondary transition-colors font-medium"
|
class="text-primary hover:text-secondary transition-colors font-medium"
|
||||||
>
|
>
|
||||||
Ver todos →
|
View all →
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{projects.map(project => (
|
{projects.map((project) => (
|
||||||
<Card href={`/projects/${project.slug}`}>
|
<Card href={`/projects/${project.slug}`}>
|
||||||
<h3 class="text-xl font-semibold mb-2 text-text-primary">{project.data.title}</h3>
|
<div class="mb-4">
|
||||||
<p class="text-text-secondary mb-4">{project.data.description}</p>
|
<span class="text-sm text-text-tertiary capitalize">
|
||||||
<div class="flex flex-wrap gap-2 mb-4">
|
{project.data.status}
|
||||||
{project.data.tags.slice(0, 3).map(tag => (
|
</span>
|
||||||
<Tag label={tag} variant="primary" />
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-between">
|
<h3 class="text-xl font-semibold mb-3 text-text-primary group-hover:text-primary transition-colors">
|
||||||
<span class="text-sm text-text-tertiary capitalize">{project.data.status}</span>
|
{project.data.title}
|
||||||
<span class="text-primary text-sm font-medium">Ver proyecto →</span>
|
</h3>
|
||||||
|
<p class="text-text-secondary mb-4">
|
||||||
|
{project.data.description}
|
||||||
|
</p>
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
{project.data.tags?.slice(0, 4).map((tag: string) => (
|
||||||
|
<Tag>{tag}</Tag>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
))}
|
||||||
@@ -141,31 +154,35 @@ const blogPosts = (await getCollection('blog'))
|
|||||||
|
|
||||||
<!-- Newsletter CTA -->
|
<!-- Newsletter CTA -->
|
||||||
<section class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
|
<section class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
|
||||||
<div class="bg-gradient-to-r from-primary/10 to-secondary/10 rounded-2xl p-8 md:p-12 text-center border border-primary/20">
|
<div class="bg-gradient-to-r from-primary/10 to-secondary/10 border border-primary/20
|
||||||
<h2 class="text-3xl font-bold mb-4">Construyendo en Público</h2>
|
rounded-2xl p-8 md:p-12 text-center">
|
||||||
<p class="text-text-secondary mb-6 max-w-2xl mx-auto">
|
<h2 class="text-3xl font-bold mb-4">Stay Updated</h2>
|
||||||
Suscríbete para recibir actualizaciones sobre lanzamientos, aprendizajes técnicos,
|
<p class="text-text-secondary text-lg mb-8 max-w-2xl mx-auto">
|
||||||
y el viaje de construcción de productos.
|
Get occasional updates about launches, learnings, and technical decisions.
|
||||||
|
No spam, no BS - just real builder content.
|
||||||
</p>
|
</p>
|
||||||
<form class="flex flex-col sm:flex-row gap-3 max-w-md mx-auto">
|
<form
|
||||||
|
class="max-w-md mx-auto flex flex-col sm:flex-row gap-4"
|
||||||
|
method="POST"
|
||||||
|
action="/api/subscribe"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
placeholder="tu@email.com"
|
name="email"
|
||||||
|
placeholder="your@email.com"
|
||||||
required
|
required
|
||||||
class="flex-1 px-4 py-3 rounded-lg bg-background border border-text-tertiary/20
|
class="flex-1 px-6 py-3 rounded-lg bg-surface border border-text-tertiary/20
|
||||||
text-text-primary placeholder-text-tertiary focus:outline-none focus:border-primary"
|
text-text-primary placeholder-text-tertiary focus:outline-none
|
||||||
|
focus:border-primary transition-colors"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
class="bg-primary hover:bg-primary/80 text-background px-6 py-3 rounded-lg
|
class="bg-primary hover:bg-primary/80 text-background px-8 py-3 rounded-lg
|
||||||
font-semibold transition-colors whitespace-nowrap"
|
font-semibold transition-colors whitespace-nowrap"
|
||||||
>
|
>
|
||||||
Suscribirse
|
Subscribe
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<p class="text-xs text-text-tertiary mt-4">
|
|
||||||
Sin spam. Cancela cuando quieras.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
Reference in New Issue
Block a user