Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions 03-github-actions/Ejercicios.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Laboratorio GitHub Actions

En este laboratorio practicarás conceptos básicos de **CI/CD con GitHub Actions**.

Trabajarás sobre el proyecto **Hangman** utilizado en clase.

En los ejercicios propuestos tendrás que crear workflows para:

- Hacer la build de un proyecto
- Ejecutar tests unitarios
- Construir imágenes Docker
- Publicar imágenes Docker en un registry
- Ejecutar tests end‑to‑end

## Entrega del laboratorio

Este laboratorio debe entregarse mediante un **repositorio público en GitHub**.

El repositorio debe contener:

```
.github/workflows/
<el código fuente proporcionado>
README.md
```

En el `README.md` deberás documentar los workflows entregados:

- Qué eventos disparan cada workflow.
- Los pasos que lo componen.
- Las actions usadas.
- Cualquier comentario adicional que consideres oportuno.

El objetivo es que cualquier persona pueda **entender los workflows**.

Ejemplo de entrega:

```
https://github.com/usuario/github-actions-lab
```

## Criterios de evaluación

El laboratorio se divide en:

- **Parte obligatoria (necesaria para aprobar)**
- **Parte opcional (para subir nota)**

### Parte obligatoria (mínimo para aprobar)

Debes completar correctamente los siguientes ejercicios:

- Ejercicio 1 --- Workflow CI
- Ejercicio 2 --- Workflow CD

Si los workflows **no funcionan**, el laboratorio **no se considerará aprobado**.

### Parte opcional (para subir nota)

Puedes realizar el ejercicio adicional:

- Ejercicio 3 --- Workflow de tests end‑to‑end

## 1. Workflow CI para el proyecto de frontend

En la clase hemos estado trabajando con el proyecto de la [API](./code/hangman-api/), pero en este ejercicio trabajarás sobre el proyecto de [frontend](./code/hangman-front/).

Debes crear un nuevo workflow que se dispare cuando haya cambios en el proyecto `hangman-front` y exista una nueva pull request (deben darse las dos condiciones a la vez). El workflow ejecutará las siguientes operaciones:

- Build del proyecto
- Ejecución de los test unitarios

> Nota: muy parecido a la primera demo, pero en este caso sobre el proyecto del frontend

## 2. Workflow CD para el proyecto de frontend

Crea un nuevo workflow que se dispare manualmente y haga lo siguiente:

- Crear una nueva imagen de Docker
- Publicar dicha imagen en el [container registry de GitHub](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry)

> Nota: intenta usar las actions de Docker vistas en clase

## 3. Workflow para ejecutar tests E2E (opcional)

Crea un workflow que se lance de la manera que elijas y ejecute los tests e2e que encontrarás en [este enlace](https://github.com/Lemoncode/bootcamp-devops-lemoncode/tree/master/03-cd/03-github-actions/.start-code/hangman-e2e/e2e). Puedes usar [Docker Compose](https://docs.docker.com/compose/gettingstarted/) o [Cypress action](https://github.com/cypress-io/github-action) para ejecutar los tests.

## Resumen de evaluación

| Nivel | Requisitos |
|---------------|--------------------------------------------------------------------------------------------|
| Aprobado | Workflows CI y CD funcionando |
| Notable | Todos los workflows funcionando o los workflows de CI y CD funcionando y bien documentados |
| Sobresaliente | Todos los workflows funcionando y bien documentados |
97 changes: 97 additions & 0 deletions 03-github-actions/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# GitHub Actions

## Demos starting point

You will find the needed code for the demos in [code](./code) folder.

## What is Github Actions?

GitHub Actions is a continuous integration and continuous delivery (CI/CD) platform that allows you to automate your build, test, and deployment pipeline. You can create workflows that build and test every pull request to your repository, or deploy merged pull requests to production.

GitHub provides Linux, Windows, and macOS virtual machines to run your workflows, or you can host your own self-hosted runners in your own data center or cloud infrastructure.

### Components

- **Workflows**: a workflow is a configurable automated process that will run one or more jobs. Workflows are defined by a YAML file stored in the `.github/workflows` directory in a repository. It will run when triggered by an event in your repository, or they can be triggered manually, or at a defined schedule.
- **Events**: an event is a specific activity in a repositoru that triggers a workflow run. For example, when someone creates a PR, opens an issue or pushes a commit.
- **Jobs**: a job is a set of steps in a workflow that is executed on the same runner. Each step is either a shell script that will be executed or an action that will be run. Jobs may have dependencies with other jobs (or not) and run in parallel with others.
- **Actions**: an action is a custom application for the GitHub Actions platform that performs a complex but frequently repeated task. It helps you to reduce repetitive code in your workflow files. An action can pull your git repository from GitHub or set up the authentication to your cloud provider. You can write your own actions, or you can find actions to use in your workflows in the GitHub Marketplace.
- **Runners**: a runner is a server that runs your workflows when they're triggered. Each runner can run a single job at a time. GitHub provides Ubuntu Linux, Microsoft Windows, and macOS runners to run your workflows.

## An example workflow

```yaml
# Optional - The name of the workflow as it will appear in the "Actions" tab of the GitHub repository. If this field is omitted, the name of the workflow file will be used instead.
name: CI

# Specifies the trigger for this workflow. In this case, the workflow will be trigger when a PR is opened to main or when commits are pushed into main.
on:
push:
branches:
- "main"
pull_request:
branches: [ main ]

# Groups together all the jobs that run in this workflow.
jobs:
# Defines a job named 'audit'
audit:
# Configures the job to run on the latest version of an Ubuntu Linux runner. Jobs can be run in self-hosted runners too.
runs-on: ubuntu-latest

# Groups together all the steps that run in the 'audit' job. Each item nested under this section is a separate action (uses) or shell script (run).
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Inspect machine
run: | # This '|' symbol allows to write several commands
ls -al
whoami
pwd
node -v
```

## About billing for GitHub Actions

GitHub Actions is free for public repositories. For private repositories, each GitHub account receives a certain amount of free minutes and storage for use with GitHub-hosted runners, depending on the account's plan.

### Included storage and minutes

| **Plan** | **Storage** | **Minutes (per month)** |
|------------------|-------------|-------------------------|
| Free | 500 MB | 2000 |
| Pro | 1 GB | 3000 |
| Team | 2 GB | 3000 |
| Enterprise Cloud | 50 GB | 50000 |

Jobs that run on Windows and macOS runners that GitHub hosts consume minutes at 2 and 10 times the rate that jobs on Linux runners consume. For example, using 1,000 Windows minutes would consume 2,000 of the minutes included in your account. Using 1,000 macOS minutes, would consume 10,000 minutes included in your account.

### Per-minute rates

| **vCPUs (on Linux machine)** | **Per-minute rate (USD)** |
|------------------------------|---------------------------|
| 2 | $0.008 |
| 4 | $0.016 |
| 8 | $0.032 |
| 16 | $0.064 |
| 32 | $0.128 |
| 64 | $0.256 |

### Usage limits

There are some limits whe using GitHub-hosted runners.

| **Plan** | **Total concurrent jobs** | **Maximum concurrent macOs jobs** |
|------------------|---------------------------|-----------------------------------|
| Free | 20 | 5 |
| Pro | 40 | 5 |
| Team | 60 | 5 |
| Enterprise Cloud | 1000 | 50 |

## References

- [Understanding Github Actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions)
- [Workflow syntax](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions)
- [About self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners)
- [About billing for GitHub Actions](https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions)
- [Pricing calculator for GitHub Actions](https://github.com/pricing/calculator?feature=actions)
12 changes: 12 additions & 0 deletions 03-github-actions/code/hangman-api/.env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# DATA_BASE
DATA_BASE_ACTIVE=false
DATABASE_PORT=5432
DATABASE_HOST=localhost
DATABASE_NAME=hangman_db
DATABASE_USER=postgres
DATABASE_PASSWORD=postgres
DATABASE_POOL_MIN=2
DATABASE_POOL_MAX=10
# HTTP_SERVER
PORT=3000
HOST=0.0.0.0
6 changes: 6 additions & 0 deletions 03-github-actions/code/hangman-api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules

.env
.env.test

dist
8 changes: 8 additions & 0 deletions 03-github-actions/code/hangman-api/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"printWidth": 120,
"tabWidth": 2,
"endOfLine": "lf",
"trailingComma": "all",
"singleQuote": true,
"arrowParens": "always"
}
27 changes: 27 additions & 0 deletions 03-github-actions/code/hangman-api/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#------------------------------------------------------------------------------
# -- builder
#------------------------------------------------------------------------------
FROM node:lts-alpine as builder

WORKDIR /app
COPY . .

RUN npm ci
RUN npm run build

#------------------------------------------------------------------------------
# -- app
#------------------------------------------------------------------------------
FROM node:lts-alpine as app

WORKDIR /app
COPY --from=builder /app/dist .
COPY package.json .
COPY package-lock.json .

ENV NODE_ENV=production

RUN npm install


CMD ["npm", "start"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.up = function (knex) {
return knex.schema
.createTable('players', function (table) {
table.increments();
table.string('name').notNullable();
table.timestamp('created_at').defaultTo(knex.fn.now());
table.timestamp('updated_at').defaultTo(knex.fn.now());
})
.createTable('words', function (table) {
table.increments();
table.string('entry').notNullable();
table.enu('word_category', ['clothes', 'sports', 'vehicles'], { useNative: true, enumName: 'category' });
table.timestamp('created_at').defaultTo(knex.fn.now());
table.timestamp('updated_at').defaultTo(knex.fn.now());
})
.createTable('games', function (table) {
table.increments();
table.integer('player_id').references('id').inTable('players');
table.integer('word_id').references('id').inTable('words');
table.enu('game_state', ['not_started', 'started', 'finished'], { useNative: true, enumName: 'progress' });
table.timestamp('created_at').defaultTo(knex.fn.now());
table.timestamp('updated_at').defaultTo(knex.fn.now());
});
};

/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.down = function (knex) {

};
12 changes: 12 additions & 0 deletions 03-github-actions/code/hangman-api/jest.config.integration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require('dotenv').config({
path: '.env.test'
});

module.exports = {
testEnvironment: 'node',
roots: ['<rootDir>/src'],
testMatch: ['**/?(*.)+(test).+(ts|js)'],
transform: {
'^.+\\.ts$': 'ts-jest',
},
};
12 changes: 12 additions & 0 deletions 03-github-actions/code/hangman-api/jest.config.specification.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require('dotenv').config({
path: '.env.test'
});

module.exports = {
testEnvironment: 'node',
roots: ['<rootDir>/src'],
testMatch: ['**/?(*.)+(spec).+(ts|js)'],
transform: {
'^.+\\.ts$': 'ts-jest',
},
};
43 changes: 43 additions & 0 deletions 03-github-actions/code/hangman-api/knexfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
require('dotenv').config();

module.exports = {

development: {
client: 'postgresql',
connection: {
port: process.env.DATABASE_PORT,
host: process.env.DATABASE_HOST,
database: process.env.DATABASE_NAME,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD
},
pool: {
min: +process.env.DATABASE_POOL_MIN,
max: +process.env.DATABASE_POOL_MAX
},
migrations: {
directory: './db/migrations',
tableName: 'knex_migrations'
},
seeds: {
directory: './db/seeds'
}
},

production: {
client: 'postgresql',
connection: {
database: 'my_db',
user: 'username',
password: 'password'
},
pool: {
min: 2,
max: 10
},
migrations: {
tableName: 'knex_migrations'
}
}

};
6 changes: 6 additions & 0 deletions 03-github-actions/code/hangman-api/nodemon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"watch": ["src", ".env"],
"ext": "ts",
"ignore": ["src/**/*.test.ts"],
"exec": "ts-node ./src/app.ts"
}
Loading