Skip to content

Commit

Permalink
feat(code): add fetch retries
Browse files Browse the repository at this point in the history
  • Loading branch information
JasonSooter committed Apr 18, 2023
1 parent 5866ff1 commit 98d7914
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 143 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build Destination Function
name: Deploy Destination Function
on:
pull_request:
types: [opened, synchronize, labeled]
Expand All @@ -23,7 +23,7 @@ jobs:
- name: Run tests
run: npm test
- name: Deploy Destination Function
run: GITHUB_JOB=${{ github.job }} FUNCTION_ID=${{ secrets.FUNCTION_ID }} PUBLIC_API_TOKEN=${{ secrets.PUBLIC_API_TOKEN }} node ./scripts/deployDestinationFunction.mjs --unhandled-rejections=strict || { exit 1;}
run: GITHUB_JOB=${{ github.job }} FUNCTION_ID=${{ secrets.FUNCTION_ID }} PUBLIC_API_TOKEN=${{ secrets.PUBLIC_API_TOKEN }} node ./scripts/deployDestinationFunction.js --unhandled-rejections=strict || { exit 1;}
# QA:
# runs-on: ubuntu-latest
# if: github.event.label.name == '!!_RELEASE_TO_QA'
Expand All @@ -38,7 +38,7 @@ jobs:
# - name: Run tests
# run: npm test
# - name: Deploy Destination Function
# run: GITHUB_JOB=${{ github.job }} FUNCTION_ID=${{ secrets.FUNCTION_ID }} PUBLIC_API_TOKEN=${{ secrets.PUBLIC_API_TOKEN }} node ./scripts/deployDestinationFunction.mjs --unhandled-rejections=strict || { exit 1;}
# run: GITHUB_JOB=${{ github.job }} FUNCTION_ID=${{ secrets.FUNCTION_ID }} PUBLIC_API_TOKEN=${{ secrets.PUBLIC_API_TOKEN }} node ./scripts/deployDestinationFunction.js --unhandled-rejections=strict || { exit 1;}
# PROD:
# runs-on: ubuntu-latest
# if: github.ref == 'refs/heads/main'
Expand All @@ -53,4 +53,4 @@ jobs:
# - name: Run tests
# run: npm test
# - name: Deploy Destination Function
# run: GITHUB_JOB=${{ github.job }} FUNCTION_ID=${{ secrets.FUNCTION_ID }} PUBLIC_API_TOKEN=${{ secrets.PUBLIC_API_TOKEN }} node ./scripts/deployDestinationFunction.mjs --unhandled-rejections=strict || { exit 1;}
# run: GITHUB_JOB=${{ github.job }} FUNCTION_ID=${{ secrets.FUNCTION_ID }} PUBLIC_API_TOKEN=${{ secrets.PUBLIC_API_TOKEN }} node ./scripts/deployDestinationFunction.js --unhandled-rejections=strict || { exit 1;}
26 changes: 16 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,41 @@
# Destination Function Template
> Base template to build your next destination function with

> Base template to deploy your next destination function with
1. Click `Use This Template` above (If Segment PS, add to `Segment Services Engineering` Organization

## Setup Steps
## Setup Steps

1. `nvm use` (to get the right version of NodeJS)
- As of 2023/02/22, Segment Source & Destination Functions require NodeJS 14.19.3
- [If needed, install `nvm`](https://github.com/nvm-sh/nvm#install--update-script)
- As of 2023/02/22, Segment Source & Destination Functions require NodeJS 14.19.3
- [If needed, install `nvm`](https://github.com/nvm-sh/nvm#install--update-script)
2. `npm install` (to install npm dependencies)


## To Test

`npm run test`

- GitHub Actions workflow also runs tests before deploying
- Tests are created in `src/index.test.js`

## To Deploy via GitHub Actions

1. Create GitHub Environments [here](https://github.com/segment-services-eng/destination-function-template/settings/environments) (DEV, QA, PROD, etc)
- *`DEV` is enabled by default in the [buildDestinationFunction.yml](https://github.com/segment-services-eng/destination-function-template/blob/main/.github/workflows/buildDestinationFunction.yml) file*
- _`DEV` is enabled by default in the [deployDestinationFunction.yml](https://github.com/segment-services-eng/destination-function-template/blob/main/.github/workflows/deployDestinationFunction.yml) file_
2. Create Function in Segment Workspace
3. Create Public API Token to allow for deploying
3. Add the following Environment Secrets
- `FUNCTION_ID`
- `PUBLIC_API_TOKEN`
4. Add the following Environment Secrets
- `FUNCTION_ID`
- `PUBLIC_API_TOKEN`

## Deploying to multiple environments
1. Once changes look good in the DEV environment, uncomment the QA section from the buildDestinationFunction.yml file.

1. Once changes look good in the DEV environment, uncomment the QA section from the deployDestinationFunction.yml file.
2. Push changes to your branch
3. Add the label `!!_RELEASE_TO_QA` to the PR to deploy it to QA

## Tooling Included

1. [Jest for code testing](https://jestjs.io/docs/expect)
2. [Prettier for code formatting](https://prettier.io/)
3. [ESLint for code linting](https://eslint.org/)
Expand Down
84 changes: 19 additions & 65 deletions package-lock.json

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

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
},
"dependencies": {
"btoa": "^1.2.1",
"moment-timezone": "^0.5.31"
"fetch-retry": "^5.0.4",
"moment-timezone": "^0.5.31",
"node-fetch": "^2.6.0"
},
"devDependencies": {
"eslint": "^8.19.0",
Expand All @@ -33,7 +35,6 @@
"jest": "^28.1.3",
"jest-fetch-mock": "^3.0.3",
"lint-staged": "^13.0.3",
"node-fetch-retry": "^2.0.1",
"prettier": "^2.7.1",
"prettier-eslint": "^15.0.1",
"semver": "^7.3.7"
Expand Down
80 changes: 80 additions & 0 deletions scripts/deployDestinationFunction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
const fs = require('fs');
const path = require('path');
const vm = require('vm');
const { GITHUB_JOB, FUNCTION_ID, PUBLIC_API_TOKEN } = process.env;

/**
* Implement Fetch w/ Retries
*/
const nodeFetch = require('node-fetch');
const fetch = require('fetch-retry')(nodeFetch);
const fetchRetryOptions = {
retries: 12,
retryDelay: attempt => Math.pow(2, attempt) * 1000, // 1000, 2000, 4000
retryOn: (attempt, error, response) => {
const { status, statusText } = response;
// retry on any network error, or 4xx or 5xx status codes
if (error !== null || status >= 400) {
console.log(`Response ${status} ${statusText}. Retry, ${attempt + 1}/12`);
return true;
}
}
};

async function run() {
const functionCode = fs.readFileSync(
path.resolve('./src', 'index.js'),
'utf8'
);
const code = `/**
* Output from GITHUB ${GITHUB_JOB} Environment
*/
${functionCode}
`;
/**
* Ensure `code` is valid JavaScript
*/
try {
new vm.Script(code);
} catch (error) {
throw new Error('JavaScript Is Not Valid, Exiting', error);
}
/**
* Push to Function Instance
*/

try {
const headers = {
Authorization: `Bearer ${PUBLIC_API_TOKEN}`,
'Content-Type': 'application/json'
};
const response = await fetch(
`https://api.segmentapis.com/functions/${FUNCTION_ID}`,
{
method: 'PATCH',
headers,
body: JSON.stringify({ code }),
...fetchRetryOptions
}
);
console.log(`Response: ${response.status} ${response.statusText}`);

if (response.status === 200) {
const result = await response.json();
if (result.errors) {
console.log(result);
throw new Error(result.errors);
}
if (result.data.function.deployedAt) {
const { deployedAt } = result.data.function;
console.log(`Successfully Pushed Function Code: ${deployedAt}`);
}
} else {
throw new Error(`Error: ${response.status} ${response.statusText}`);
}
} catch (error) {
throw new Error(error);
}
}
run();
62 changes: 0 additions & 62 deletions scripts/deployDestinationFunction.mjs

This file was deleted.

0 comments on commit 98d7914

Please sign in to comment.