Skip to content

Commit 8e667c7

Browse files
authored
A GitHub Actions workflow to update the lists of templates and cloud provider actions weekly or manually (DOC-146) (#282)
1 parent eed27d2 commit 8e667c7

File tree

3 files changed

+126
-26
lines changed

3 files changed

+126
-26
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Update Templates And Cloud Provider Actions
2+
3+
on:
4+
schedule:
5+
- cron: '45 15 * * 3'
6+
workflow_dispatch:
7+
8+
jobs:
9+
update-templates-and-actions:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: write
13+
pull-requests: write
14+
15+
steps:
16+
- name: Checkout repository
17+
uses: actions/[email protected]
18+
with:
19+
ref: ${{ github.ref_name }}
20+
21+
- name: Set up Node.js
22+
uses: actions/setup-node@v4
23+
with:
24+
node-version: '20'
25+
26+
- name: Install dependencies
27+
run: npm ci
28+
29+
- name: Generate templates list
30+
run: node scripts/generate-list-of-templates.js
31+
env:
32+
OPENOPS_USERNAME: ${{ secrets.OPENOPS_USERNAME }}
33+
OPENOPS_PASSWORD: ${{ secrets.OPENOPS_PASSWORD }}
34+
35+
- name: Generate cloud provider actions list
36+
run: node scripts/generate-lists-of-cloud-provider-actions.js
37+
38+
- name: Check for changes
39+
id: changes
40+
run: |
41+
if git status --porcelain | grep .; then
42+
echo "changed=true" >> "$GITHUB_OUTPUT"
43+
else
44+
echo "changed=false" >> "$GITHUB_OUTPUT"
45+
echo "No changes detected. Exiting successfully."
46+
fi
47+
48+
- name: Stop if no changes
49+
if: steps.changes.outputs.changed == 'false'
50+
run: exit 0
51+
52+
- name: Create update branch
53+
id: branch
54+
run: |
55+
TS=$(date -u +"%Y-%m-%d-%H-%M")
56+
BRANCH="updated-templates-and-actions-$TS"
57+
echo "branch=$BRANCH" >> "$GITHUB_OUTPUT"
58+
git checkout -b "$BRANCH"
59+
60+
- name: Commit and push changes
61+
run: |
62+
git config user.name "github-actions[bot]"
63+
git config user.email "github-actions[bot]@users.noreply.github.com"
64+
65+
git add .
66+
git commit -m "Templates and cloud provider actions updated as of $(date -u +'%Y-%m-%d')"
67+
git push origin HEAD
68+
69+
- name: Create pull request
70+
env:
71+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
72+
run: |
73+
gh pr create \
74+
--head "${{ steps.branch.outputs.branch }}" \
75+
--base "${{ github.ref_name }}" \
76+
--title "Update templates and cloud provider actions" \
77+
--body "Automated update of templates and cloud provider actions." \
78+
--reviewer gorohoroh

scripts/generate-list-of-templates.js

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
const credentials = require('./credentials.json');
21
const fs = require('fs/promises');
32
const path = require('path');
43

5-
const API_URL = 'https://app.openops.com/api/v1/cloud-templates?version=9999';
4+
const AUTH_URL = 'https://app.openops.com/api/v1/authentication/sign-in';
5+
const TEMPLATES_URL = 'https://app.openops.com/api/v1/flow-templates?version=9999';
66
const OUT_RELATIVE = '../snippets/templates-generated.mdx';
77

88
const caseInsensitive = () => (a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'});
@@ -53,27 +53,56 @@ const writeMarkdownToFile = async (lines, stats) => {
5353
console.log(`Wrote ${stats.categories} categories, ${stats.names} template names to ${outPath}`);
5454
};
5555

56-
const main = async () => {
56+
const getAuthToken = async () => {
57+
let credentialsFile = {};
5758
try {
58-
const res = await fetch(API_URL, {
59-
headers: {
60-
Accept: 'application/json',
61-
Cookie: credentials.cookie
62-
}
59+
credentialsFile = require('./credentials.json');
60+
} catch {
61+
console.log('No credentials.json found. Using environment variables instead.');
62+
}
63+
64+
const username = process.env.OPENOPS_USERNAME || credentialsFile.username;
65+
const password = process.env.OPENOPS_PASSWORD || credentialsFile.password;
66+
67+
const auth = await fetch(AUTH_URL, {
68+
method: "POST",
69+
headers: {
70+
"Content-Type": "application/json"
71+
},
72+
body: JSON.stringify({
73+
"email": username,
74+
"password": password
75+
}
76+
)
6377
});
6478

65-
if (!res.ok) throw new Error(`Fetch failed: ${res.status}`);
79+
if (!auth.ok) throw new Error(`Unable to authenticate with app.openops.com: error ${auth.status}, ${auth.statusText}`);
6680

67-
const templates = await res.json();
68-
if (!Array.isArray(templates)) throw new Error('Unexpected API response: expected array');
81+
return (await auth.json()).token;
82+
};
6983

70-
const categoryMap = groupTemplatesByCategory(templates);
71-
const {lines, stats} = prepareMarkdownLines(categoryMap, caseInsensitive);
72-
await writeMarkdownToFile(lines, stats);
73-
} catch (err) {
74-
console.error('Error:', err?.message ?? err);
75-
process.exitCode = 1;
76-
}
84+
const main = async () => {
85+
try {
86+
const token = await getAuthToken()
87+
const res = await fetch(TEMPLATES_URL, {
88+
headers: {
89+
Accept: 'application/json',
90+
Authorization: `Bearer ${token}`
91+
}
92+
});
93+
94+
if (!res.ok) throw new Error(`Fetch failed: ${res.status}`);
95+
96+
const templates = await res.json();
97+
if (!Array.isArray(templates)) throw new Error('Unexpected API response: expected array');
98+
99+
const categoryMap = groupTemplatesByCategory(templates);
100+
const {lines, stats} = prepareMarkdownLines(categoryMap, caseInsensitive);
101+
await writeMarkdownToFile(lines, stats);
102+
} catch (err) {
103+
console.error('Error:', err?.message ?? err);
104+
process.exitCode = 1;
105+
}
77106
};
78107

79108
main();

scripts/generate-lists-of-cloud-provider-actions.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
const credentials = require('./credentials.json');
21
const fs = require('fs/promises');
32
const path = require('path');
43

@@ -28,13 +27,7 @@ const writeMarkdownToFile = async (lines, cloudProvider, number) => {
2827
const main = async () => {
2928
try {
3029
for (const cloudProvider of CLOUD_PROVIDERS) {
31-
const res = await fetch(API_BASE_URL + cloudProvider.url, {
32-
headers: {
33-
Accept: 'application/json',
34-
Cookie: credentials.cookie
35-
}
36-
});
37-
30+
const res = await fetch(API_BASE_URL + cloudProvider.url);
3831
if (!res.ok) throw new Error(`Fetch failed: ${res.status}`);
3932

4033
const block = await res.json();

0 commit comments

Comments
 (0)