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
8 changes: 8 additions & 0 deletions functions/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Firebase Functions Environment Variables

# Slack API Token
SLACK_TOKEN=xoxb-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# AWS Credentials for S3 and DynamoDB
AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXXXX
AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3 changes: 2 additions & 1 deletion functions/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ typings/

node_modules/

.runtimeconfig.json
.runtimeconfig.json
.env
1 change: 1 addition & 0 deletions functions/.runtimeconfig.example.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"_comment": "DEPRECATED: This file is deprecated. Use .env file instead. See .env.example for the new format.",
"slack": {
"token": "xoxb-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
Expand Down
72 changes: 72 additions & 0 deletions functions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Firebase Functions

This directory contains Firebase Cloud Functions for the TSG Slackbot.

## Setup

### Environment Variables

This project uses environment variables for configuration instead of the deprecated `functions.config()` API.

1. Copy the example environment file:
```bash
cp .env.example .env
```

2. Fill in the required values in `.env`:
- `SLACK_TOKEN`: Slack Bot User OAuth Token (starts with `xoxb-`)
- `AWS_ACCESS_KEY_ID`: AWS access key ID for S3 and DynamoDB access
- `AWS_SECRET_ACCESS_KEY`: AWS secret access key for S3 and DynamoDB access

### Legacy Configuration (Deprecated)

The `.runtimeconfig.json` file and `functions.config()` API are deprecated and will be removed in March 2026. If you have existing configuration in `.runtimeconfig.json`, migrate it to `.env` file format as shown above.

## Development

### Build

```bash
npm run build
```

### Deploy

```bash
npm run deploy
```

### Testing

Tests are run from the parent directory:

```bash
cd ..
npm test -- functions/
```

## Functions

### `slackFileArchiveCronJob`

A scheduled function that runs every 60 minutes to archive Slack files to AWS S3.

**Environment Variables:**
- `SLACK_TOKEN`: Used to authenticate with Slack API
- `AWS_ACCESS_KEY_ID`: AWS credentials for S3 storage
- `AWS_SECRET_ACCESS_KEY`: AWS credentials for S3 storage

**Configuration:**
- Timeout: 300 seconds
- Memory: 1GB
- Schedule: Every 60 minutes

## Migration from functions.config()

This project has been migrated from `functions.config()` to environment variables using `firebase-functions/params`. The migration was necessary because:

1. The Cloud Runtime Configuration API (used by `functions.config()`) will be shut down in March 2026
2. Firebase CLI commands for managing configuration (`functions:config:set`, `get`, `unset`, `clone`, `export`) are deprecated
3. Deployments using `functions.config()` will fail after March 2026

For more information, see: https://firebase.google.com/docs/functions/config-env#migrate-to-dotenv
2 changes: 0 additions & 2 deletions functions/package-lock.json

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

14 changes: 5 additions & 9 deletions functions/src/jobs/slackFileArchiveCronJeb.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@

import firebaseFunctionsTest from 'firebase-functions-test';

// Set environment variables for the test
process.env.SLACK_TOKEN = 'xoxb-slacktoken';
process.env.AWS_SECRET_ACCESS_KEY = 'SECRET-ACCESS-KEY';
process.env.AWS_ACCESS_KEY_ID = 'ACCESS-KEY-ID';

const test = firebaseFunctionsTest();
test.mockConfig({
slack: {
token: 'xoxb-slacktoken',
},
aws: {
secret_access_key: 'SECRET-ACCESS-KEY',
access_key_id: 'ACCESS-KEY-ID',
},
});

const filesListMock = jest.fn();

Expand Down
21 changes: 12 additions & 9 deletions functions/src/jobs/slackFileArchiveCronJob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,28 @@ import {WebClient} from '@slack/web-api';
import {DynamoDB, S3} from 'aws-sdk';
import axios from 'axios';
import {chunk} from 'lodash';
import {runWith, config as getConfig, logger} from 'firebase-functions/v1';
import {runWith, logger} from 'firebase-functions/v1';
import {defineString} from 'firebase-functions/params';

const cronJob = async () => {
const config = getConfig();
const slackToken = defineString('SLACK_TOKEN');
const awsAccessKeyId = defineString('AWS_ACCESS_KEY_ID');
const awsSecretAccessKey = defineString('AWS_SECRET_ACCESS_KEY');

const slack = new WebClient(config.slack.token);
const cronJob = async () => {
const slack = new WebClient(slackToken.value());

const db = new DynamoDB.DocumentClient({
region: 'ap-northeast-1',
credentials: {
secretAccessKey: config.aws.secret_access_key,
accessKeyId: config.aws.access_key_id,
secretAccessKey: awsSecretAccessKey.value(),
accessKeyId: awsAccessKeyId.value(),
},
});

const s3 = new S3({
credentials: {
secretAccessKey: config.aws.secret_access_key,
accessKeyId: config.aws.access_key_id,
secretAccessKey: awsSecretAccessKey.value(),
accessKeyId: awsAccessKeyId.value(),
},
});

Expand Down Expand Up @@ -87,7 +90,7 @@ const cronJob = async () => {
url: file.url_private_download,
responseType: 'arraybuffer',
headers: {
Authorization: `Bearer ${config.slack.token}`,
Authorization: `Bearer ${slackToken.value()}`,
},
validateStatus: () => true,
});
Expand Down