Skip to content
Merged
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
73 changes: 73 additions & 0 deletions .github/workflows/deploy-functions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Deploy Azure Functions

on:
push:
branches: ["main"]

concurrency:
group: functions-prod
cancel-in-progress: true

jobs:
build-and-deploy:
runs-on: ubuntu-latest

steps:
# Checkout repository code
- name: Checkout
uses: actions/checkout@v4

# Setup Node.js runtime
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "22"
cache: "npm"

# Install dependencies for the whole monorepo (npm workspaces)
- name: Install dependencies
run: npm ci

# Build ONLY the functions workspace (tsc output to functions/dist)
- name: Build functions workspace
run: npm run -w functions ci

# Prepare a deploy folder that contains:
# - host.json at the root
# - dist/ at the root
# - a package.json that references the internal db package via "file:"
# - the internal package code under ./packages/db
- name: Prepare deploy folder
run: |
rm -rf deploy
mkdir -p deploy/packages

# Copy runtime files expected by Azure Functions
cp functions/host.json deploy/host.json
cp -R functions/dist deploy/dist

# Copy the internal workspace package so it can be installed with "file:"
cp -R packages/db deploy/packages/db

# Generate a deploy-specific package.json
node -e "
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('functions/package.json','utf8'));
pkg.name = 'functions-deploy';
pkg.main = 'dist/index.js';
pkg.dependencies = pkg.dependencies || {};
pkg.dependencies['@embalse-info/db'] = 'file:./packages/db';
fs.writeFileSync('deploy/package.json', JSON.stringify(pkg, null, 2));
"

# Generate a deploy-specific package-lock.json by installing in deploy/
cd deploy
npm install --omit=dev

# Deploy the deploy/ folder (it is now a complete Functions app root)
- name: Deploy to Azure Functions
uses: Azure/functions-action@v1
with:
app-name: fn-info-embalse-prod
package: deploy
publish-profile: ${{ secrets.AZURE_FUNCTIONAPP_PUBLISH_PROFILE }}
19 changes: 5 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,10 @@ docker run -d --name azurite -p 10000:10000 -p 10001:10001 -p 10002:10002 mcr.mi

### Añadir las variables de entorno

Dentro de la carpeta `functions`, crear un archivo `local.settings.json` con las siguientes variables de entorno:

_/functions/local.settings.json_

```json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "node",
"MONGODB_CONNECTION_STRING": "mongodb://localhost:27017/embalse-info"
}
}
Dentro de la carpeta `functions`, vamos crear un archivo `local.settings.json` a partir del de plantilla, ejecuta este comando desde el terminal (bash), desde el raiz del repo.

```bash
cp functions/local.settings.template.json functions/local.settings.json
```

### Arrancar las funciones de Azure
Expand Down Expand Up @@ -134,4 +125,4 @@ Está pendiente conectar typeahead con el detalle del embalse. De momento, se pu
http://localhost:3000/embalse/vinuela-la

http://localhost:3000/embalse/villagudin
```
```
8 changes: 7 additions & 1 deletion functions/host.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
{
"version": "2.0",
"logging": {
"logLevel": {
"default": "Warning",
"Function": "Information",
"Host.Results": "Information",
"Host.Aggregator": "Warning"
},
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
Expand All @@ -12,4 +18,4 @@
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.*, 5.0.0)"
}
}
}
11 changes: 11 additions & 0 deletions functions/local.settings.template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "node",
"MONGODB_CONNECTION_STRING": "mongodb://localhost:27017/embalse-info",
"APPLICATIONINSIGHTS_CONNECTION_STRING": "",
"SCRAPING_SCHEDULE": "0 * * * * *",
"ARCGIS_SCHEDULE": "40 * * * * *"
}
}
9 changes: 5 additions & 4 deletions functions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
"version": "0.0.1",
"type": "module",
"scripts": {
"prestart": "run-p clean type-check build",
"start": "func start",
"watch": "tsc -w",
"build": "tsc",
"clean": "rimraf dist",
"prestart": "run-p clean type-check build",
"type-check": "tsc --noEmit --preserveWatchOutput"
"type-check": "tsc --noEmit --preserveWatchOutput",
"build": "tsc",
"ci": "npm run clean && npm run type-check && npm run build",
"watch": "tsc -w"
},
"dependencies": {
"@azure/functions": "^4.0.0",
Expand Down
6 changes: 4 additions & 2 deletions functions/src/functions/arcgis-function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { dbServer, embalsesRepository } from "@embalse-info/db";

export async function arcgisFunction(
myTimer: Timer,
context: InvocationContext
context: InvocationContext,
): Promise<void> {
await dbServer.connect(process.env.MONGODB_CONNECTION_STRING as string);
context.log("ArcGIS function executed at:", new Date().toISOString());
Expand All @@ -19,13 +19,15 @@ export async function arcgisFunction(
}

app.timer("arcgis-function", {
// Run once immediately when the Function App instance starts (deploy/restart/scale-out)
runOnStartup: true,
retry: {
strategy: "fixedDelay",
delayInterval: {
seconds: 10,
},
maxRetryCount: 4,
},
schedule: "0 * * * * *",
schedule: process.env.ARCGIS_SCHEDULE ?? "0 0 3 * * Mon,Thu", // Twice per week
handler: arcgisFunction,
});
6 changes: 3 additions & 3 deletions functions/src/functions/scraping-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { dbServer, embalsesRepository } from "@embalse-info/db";

export async function scrapingsFunction(
myTimer: Timer,
context: InvocationContext
context: InvocationContext,
): Promise<void> {
await dbServer.connect(process.env.MONGODB_CONNECTION_STRING as string);
context.log("Scrapings function executed at:", new Date().toISOString());
Expand All @@ -15,7 +15,7 @@ export async function scrapingsFunction(
context.log(`Se han actualizado los embalses de la cuenca Mediterránea`);
} else {
context.log(
"No se han podido actualizar los embalses de la cuenca Mediterránea"
"No se han podido actualizar los embalses de la cuenca Mediterránea",
);
}
await dbServer.disconnect();
Expand All @@ -29,6 +29,6 @@ app.timer("scrapings-function", {
},
maxRetryCount: 4,
},
schedule: "40 * * * * *",
schedule: process.env.SCRAPING_SCHEDULE ?? "0 0 */4 * * *", // Every 4 hours
handler: scrapingsFunction,
});
67 changes: 25 additions & 42 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.