-
Notifications
You must be signed in to change notification settings - Fork 1
178 lines (160 loc) · 6.09 KB
/
heroku-container.yml
File metadata and controls
178 lines (160 loc) · 6.09 KB
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
name: Heroku container deploy
on:
workflow_call:
inputs:
heroku-app:
description: "The Heroku app name"
default: ${{ github.event.repository.name }}
required: false
type: string
branch:
description: "The branch to deploy"
default: ${{ github.event.repository.default_branch }}
required: false
type: string
targets:
description: "Space-separated Dockerfile targets to build and push (e.g. 'web worker release')"
required: true
type: string
create-release:
description: "Create a GitHub Release after successful deploy"
default: true
required: false
type: boolean
build-args:
description: "Docker build args (newline-separated KEY=VALUE pairs, for non-secret values like version overrides)"
required: false
type: string
secrets:
heroku-key:
description: "Heroku API key (OAuth token)"
required: true
build-secrets:
description: "Docker build secrets (newline-separated KEY=VALUE pairs, mounted via --secret in the Dockerfile)"
required: false
jobs:
deploy:
if: |
(github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.head_branch == inputs.branch) ||
(github.event_name == 'workflow_dispatch' && github.ref_name == inputs.branch)
concurrency: ${{ inputs.heroku-app || github.event.repository.name }}
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: write
deployments: write
steps:
- name: Create deployment in GitHub
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: ${{ inputs.branch }}
APP: ${{ inputs.heroku-app || github.event.repository.name }}
REPO: ${{ github.repository }}
run: |
deploymentId=$(jq -n \
--arg ref "$BRANCH" \
--arg env "$APP" \
'{ref: $ref, auto_merge: false, environment: $env,
description: "Heroku container deploy from GitHub Actions",
required_contexts: []}' \
| gh api "repos/$REPO/deployments" \
--method POST \
--header "Accept: application/vnd.github.v3+json" \
--input - \
--jq '.id')
echo "DEPLOYMENT_ID=$deploymentId" >> "$GITHUB_ENV"
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.branch }}
fetch-depth: 5
persist-credentials: false
- name: Log in to Heroku Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: registry.heroku.com
username: _
password: ${{ secrets.heroku-key }}
- uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Build and push per target
env:
APP: ${{ inputs.heroku-app || github.event.repository.name }}
TARGETS: ${{ inputs.targets }}
BUILD_ARGS: ${{ inputs.build-args }}
BUILD_SECRETS: ${{ secrets.build-secrets }}
run: |
args=()
while IFS= read -r line; do
[[ -n "$line" ]] && args+=(--build-arg "$line")
done <<< "$BUILD_ARGS"
for vfile in .*-version; do
[[ -f "$vfile" ]] || continue
name="${vfile#.}"; name="${name%-version}"
args+=(--build-arg "$(echo "$name" | tr '[:lower:]-' '[:upper:]_')_VERSION=$(tr -d '[:space:]' < "$vfile")")
done
secrets=()
while IFS='=' read -r key value; do
[[ -z "$key" ]] && continue
export "$key=$value"
secrets+=(--secret "id=$key,env=$key")
done <<< "$BUILD_SECRETS"
for target in $TARGETS; do
docker buildx build \
--target "$target" \
--tag "registry.heroku.com/$APP/$target" \
--cache-from type=gha \
--cache-to type=gha,mode=max \
--provenance=false \
--push \
"${args[@]}" \
"${secrets[@]}" \
.
done
- name: Install Heroku CLI
run: curl -fsSL https://cli-assets.heroku.com/install.sh | sh
- name: Release
env:
HEROKU_API_KEY: ${{ secrets.heroku-key }}
APP: ${{ inputs.heroku-app || github.event.repository.name }}
TARGETS: ${{ inputs.targets }}
run: heroku container:release $TARGETS -a "$APP"
- name: Create GitHub Release
if: inputs['create-release']
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="v$(date -u +'%Y.%m.%d-%H%M%S')"
COMMIT_SHA=$(git rev-parse HEAD)
COMMIT_MSG=$(git log -1 --pretty=%B)
RECENT=$(git log --oneline -5 --pretty="- %s (%h)")
NOTES=$(cat <<EOF
## Deployed to Production
**Commit:** ${COMMIT_SHA:0:7}
**Time:** $(date -u +'%Y-%m-%d %H:%M:%S UTC')
### Latest Changes
${COMMIT_MSG}
### Recent Commits
${RECENT}
EOF
)
gh release create "$VERSION" \
--title "Release $VERSION" \
--target "$COMMIT_SHA" \
--notes "$NOTES"
- name: Create deployment status in GitHub
if: always() && env.DEPLOYMENT_ID
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
RUN_ID: ${{ github.run_id }}
APP: ${{ inputs.heroku-app || github.event.repository.name }}
JOB_STATUS: ${{ job.status }}
run: |
state="$JOB_STATUS"
[ "$state" = "cancelled" ] && state="error"
gh api "repos/$REPO/deployments/$DEPLOYMENT_ID/statuses" \
--method POST \
--header "Accept: application/vnd.github.v3+json" \
--field "state=$state" \
--field "log_url=https://github.com/$REPO/actions/runs/$RUN_ID" \
--field "environment_url=https://$APP.herokuapp.com/"