This repository has been archived by the owner on Jul 19, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathaction.js
270 lines (218 loc) · 7.9 KB
/
action.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
'use strict'
const { join } = require('node:path')
const core = require('@actions/core')
const github = require('@actions/github')
const { deploy } = require('@platformatic/deploy-client')
const PLT_MESSAGE_REGEXP = /\*\*Your application was successfully deployed.*!\*\* :rocket:\nApplication url: (.*).*/
// TODO: move port and database_url to secrets
const PLATFORMATIC_VARIABLES = ['PORT', 'DATABASE_URL']
const PLATFORMATIC_SECRETS = []
const PROD_DEPLOY_SERVICE_HOST = 'https://plt-production-deploy-service.fly.dev'
function getRepositoryMetadata () {
const context = github.context.payload
return {
name: context.repository.name,
url: context.repository.html_url,
githubRepoId: context.repository.id
}
}
function getBranchMetadata () {
const headRef = process.env.GITHUB_HEAD_REF
const refName = process.env.GITHUB_REF_NAME
const branchName = headRef || refName
return { name: branchName }
}
async function getHeadCommitMetadata (octokit, commitSha) {
const context = github.context.payload
const { data: commitDetails } = await octokit.rest.repos.getCommit({
owner: context.repository.owner.login,
repo: context.repository.name,
ref: commitSha
})
return {
sha: commitSha,
username: commitDetails.author?.login || null,
additions: commitDetails.stats.additions,
deletions: commitDetails.stats.deletions
}
}
async function getPullRequestMetadata (octokit) {
const context = github.context.payload
const { data: pullRequestDetails } = await octokit.rest.pulls.get({
owner: context.repository.owner.login,
repo: context.repository.name,
pull_number: context.pull_request.number
})
return {
title: pullRequestDetails.title,
number: pullRequestDetails.number
}
}
async function getGithubMetadata (octokit, isPullRequest) {
const repositoryMetadata = getRepositoryMetadata()
const branchMetadata = getBranchMetadata()
const commitSha = isPullRequest
? github.context.payload.pull_request.head.sha
: (github.context.payload.head_commit?.id || github.context.payload.sha)
const commitMetadata = await getHeadCommitMetadata(octokit, commitSha)
const githubMetadata = {
repository: repositoryMetadata,
branch: branchMetadata,
commit: commitMetadata
}
if (isPullRequest) {
const pullRequestMetadata = await getPullRequestMetadata(octokit)
githubMetadata.pullRequest = pullRequestMetadata
}
return githubMetadata
}
function getGithubEnvVariables (variablesNames) {
const upperCasedVariablesNames = []
for (const variableName of variablesNames) {
upperCasedVariablesNames.push(variableName.toUpperCase().trim())
}
const userEnvVars = {}
for (const key in process.env) {
const upperCaseKey = key.toUpperCase().trim()
if (
PLATFORMATIC_VARIABLES.includes(upperCaseKey) ||
upperCasedVariablesNames.includes(upperCaseKey) ||
upperCaseKey.startsWith('PLT_')
) {
userEnvVars[upperCaseKey] = process.env[key]
}
}
return userEnvVars
}
function getGithubSecrets (secretsNames) {
const upperCasedSecretsNames = []
for (const secretName of secretsNames) {
upperCasedSecretsNames.push(secretName.toUpperCase().trim())
}
const secrets = {}
for (const key in process.env) {
const upperCaseKey = key.toUpperCase().trim()
if (
PLATFORMATIC_SECRETS.includes(upperCaseKey) ||
upperCasedSecretsNames.includes(upperCaseKey)
) {
secrets[upperCaseKey] = process.env[key]
}
}
return secrets
}
/* istanbul ignore next */
async function findLastPlatformaticComment (octokit) {
const context = github.context.payload
const { data: comments } = await octokit.rest.issues.listComments({
owner: context.repository.owner.login,
repo: context.repository.name,
issue_number: context.pull_request.number
})
const platformaticComments = comments
.filter(comment =>
comment.user.login === 'github-actions[bot]' &&
PLT_MESSAGE_REGEXP.test(comment.body)
)
.sort((a, b) => new Date(a.updated_at) - new Date(b.updated_at))
if (platformaticComments.length === 0) {
return null
}
const lastComment = platformaticComments[platformaticComments.length - 1]
return lastComment.id
}
function createPlatformaticComment (applicationUrl, commitHash, commitUrl) {
return [
'**Your application was successfully deployed by [Plaformatic](https://platformatic.dev)!** :rocket:',
`Application url: ${applicationUrl}`,
`Built from the commit: [${commitHash.slice(0, 7)}](${commitUrl})`
].join('\n')
}
async function postPlatformaticComment (octokit, comment) {
const context = github.context.payload
await octokit.rest.issues.createComment({
owner: context.repository.owner.login,
repo: context.repository.name,
issue_number: context.pull_request.number,
body: comment
})
}
/* istanbul ignore next */
async function updatePlatformaticComment (octokit, commentId, comment) {
await octokit.rest.issues.updateComment({
...github.context.repo,
comment_id: commentId,
body: comment
})
}
const allowedEvents = ['push', 'pull_request', 'workflow_dispatch']
async function run () {
try {
const eventName = process.env.GITHUB_EVENT_NAME
if (!allowedEvents.includes(eventName)) {
throw new Error('The action only works on push, pull_request and workflow_dispatch events')
}
const workspaceId = core.getInput('platformatic_workspace_id')
const workspaceKey = core.getInput('platformatic_workspace_key')
const pathToConfig = core.getInput('platformatic_config_path')
const pathToEnvFile = core.getInput('platformatic_env_path')
const subfolderPath = core.getInput('platformatic_project_path') || ''
const pathToProject = join(process.env.GITHUB_WORKSPACE, subfolderPath)
const deployServiceHost = process.env.DEPLOY_SERVICE_HOST ||
PROD_DEPLOY_SERVICE_HOST
const githubToken = core.getInput('github_token')
const octokit = github.getOctokit(githubToken)
const isPullRequest = github.context.eventName === 'pull_request'
const githubMetadata = await getGithubMetadata(octokit, isPullRequest)
core.info('Getting environment secrets')
const secretsParam = core.getInput('secrets') || ''
const secretsNames = secretsParam.split(',')
const secrets = getGithubSecrets(secretsNames)
core.info('Getting environment variables')
const envVariablesParam = core.getInput('variables') || ''
const envVariablesNames = envVariablesParam.split(',')
const envVariables = getGithubEnvVariables(envVariablesNames)
const label = isPullRequest
? `github-pr:${githubMetadata.pullRequest.number}`
: (core.getInput('label') || null)
const logger = {
trace: () => {},
info: core.info,
warn: core.warning,
error: core.error
}
logger.child = () => logger
const { deploymentId, entryPointUrl } = await deploy({
deployServiceHost,
workspaceId,
workspaceKey,
pathToProject,
pathToConfig,
pathToEnvFile,
secrets,
variables: envVariables,
label,
githubMetadata,
logger
})
const postPrComment = core.getInput('post_pr_comment') === 'true'
if (isPullRequest && postPrComment) {
const commitHash = githubMetadata.commit.sha
const commitUrl = githubMetadata.repository.url + '/commit/' + commitHash
const platformaticComment = createPlatformaticComment(entryPointUrl, commitHash, commitUrl)
const lastCommentId = await findLastPlatformaticComment(octokit)
/* istanbul ignore next */
if (lastCommentId === null) {
await postPlatformaticComment(octokit, platformaticComment)
} else {
await updatePlatformaticComment(octokit, lastCommentId, platformaticComment)
}
}
core.setOutput('deployment_id', deploymentId)
core.setOutput('platformatic_app_url', entryPointUrl)
} catch (error) {
console.error(error)
core.setFailed(error.message)
}
}
module.exports = run