1
+ name : Build and deploy
2
+ run-name : Build and deploy number ${{github.run_number}} started by @${{ github.actor }}
3
+
4
+ on :
5
+ pull_request :
6
+ types : [ closed ]
7
+ branches : [ main ]
8
+
9
+ env :
10
+ REGION : us-east-1
11
+
12
+ jobs :
13
+
14
+ build :
15
+ runs-on : ubuntu-22.04
16
+ outputs :
17
+ REGISTRY : ${{ steps.build-deploy.outputs.REGISTRY }}
18
+ REPOSITORY : ${{ steps.build-deploy.outputs.REPOSITORY }}
19
+ TAG : ${{ steps.bump-version.outputs.NEW_VERSION }}
20
+
21
+ steps :
22
+
23
+ - name : Checkout Files
24
+ uses : actions/checkout@v4
25
+ with :
26
+ token : ${{ secrets.ORG_GITHUB_TOKEN }}
27
+
28
+ - name : Configure AWS Credentials
29
+ uses : aws-actions/configure-aws-credentials@v4
30
+ with :
31
+ aws-region : ${{env.REGION}}
32
+ aws-access-key-id : ${{ secrets.AWS_ACCESS_KEY_ID }}
33
+ aws-secret-access-key : ${{ secrets.AWS_SECRET_ACCESS_KEY }}
34
+
35
+ - name : Login to Amazon ECR
36
+ id : login-ecr
37
+ uses : aws-actions/amazon-ecr-login@v2
38
+
39
+ - name : Determine version bump type
40
+ id : version
41
+ run : |
42
+ commit_message=$(git log -1 --pretty=%B)
43
+ if [[ "$commit_message" == *"[major]"* ]]; then
44
+ echo "type=major" >> "$GITHUB_OUTPUT"
45
+ elif [[ "$commit_message" == *"[minor]"* ]]; then
46
+ echo "type=minor" >> "$GITHUB_OUTPUT"
47
+ else
48
+ echo "type=patch" >> "$GITHUB_OUTPUT"
49
+ fi
50
+
51
+ - name : Bump version and push
52
+ id : bump-version
53
+ run : |
54
+ git config --global user.name 'github-actions[bot]'
55
+ git config --global user.email 'github-actions[bot]@users.noreply.github.com'
56
+ new_version=$(npm version ${{ steps.version.outputs.type }} -m "chore(release): %s [skip ci]")
57
+ echo "NEW_VERSION=${new_version}" >> "$GITHUB_OUTPUT"
58
+
59
+ - name : Build and push docker image to Amazon ECR
60
+ id : build-deploy
61
+ run : |
62
+ REGISTRY=${{ steps.login-ecr.outputs.registry }}
63
+ REPOSITORY=$(echo ${GITHUB_REPOSITORY} | cut -d'/' -f2)
64
+ IMAGE_TAG=${{ steps.bump-version.outputs.NEW_VERSION }}
65
+
66
+ if aws ecr describe-repositories --repository-names $REPOSITORY 2>/dev/null; then
67
+ echo "ECR Repository $REPOSITORY already exists"
68
+ else
69
+ echo "Creating ECR repository $REPOSITORY"
70
+ aws ecr create-repository --repository-name $REPOSITORY
71
+ cat <<EOF > policy.json
72
+ {
73
+ "rules": [
74
+ {
75
+ "rulePriority": 1,
76
+ "description": "Expire images older than 5 days",
77
+ "selection": {
78
+ "tagStatus": "any",
79
+ "countType": "imageCountMoreThan",
80
+ "countNumber": 5
81
+ },
82
+ "action": {
83
+ "type": "expire"
84
+ }
85
+ }
86
+ ]
87
+ }
88
+ EOF
89
+ aws ecr put-lifecycle-policy --repository-name $REPOSITORY --lifecycle-policy-text file://policy.json
90
+ fi
91
+
92
+ echo "${{ secrets.ENV_GLOBAL }}" > .env
93
+ echo "PORT=${{ vars.PORT }}" >> .env
94
+
95
+ docker build --build-arg="PORT=${{ vars.PORT }}" --no-cache -t $REGISTRY/$REPOSITORY:$IMAGE_TAG .
96
+ docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG
97
+ echo "REGISTRY=$REGISTRY" >> "$GITHUB_OUTPUT"
98
+ echo "TAG=$IMAGE_TAG" >> "$GITHUB_OUTPUT"
99
+ echo "REPOSITORY=$REPOSITORY" >> "$GITHUB_OUTPUT"
100
+ git push origin HEAD:$GITHUB_REF_NAME --follow-tags
101
+
102
+ deploy :
103
+
104
+ runs-on : ubuntu-22.04
105
+ needs : build
106
+ if : ${{ success() }}
107
+ env :
108
+ REGISTRY : ${{ needs.build.outputs.REGISTRY }}
109
+ REPOSITORY : ${{ needs.build.outputs.REPOSITORY }}
110
+ TAG : ${{ needs.build.outputs.TAG }}
111
+
112
+ steps :
113
+
114
+ - name : Setup SSH
115
+ uses : webfactory/ssh-agent@v0.9.0
116
+ with :
117
+ ssh-private-key : ${{ secrets.PRIVATE_KEY }}
118
+
119
+ - name : Add server to known hosts
120
+ run : |
121
+ mkdir -p ~/.ssh
122
+ ssh-keyscan -H ${{ secrets.REMOTE_SERVER_ADDRESS }} >> ~/.ssh/known_hosts
123
+
124
+
125
+ - name : Create container from ECR
126
+ if : success()
127
+ run : |
128
+ ssh ${{ secrets.REMOTE_SERVER_USERNAME }}@${{ secrets.REMOTE_SERVER_ADDRESS }} << 'EOF'
129
+
130
+ export AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }}
131
+ export AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}
132
+ export AWS_DEFAULT_REGION=${{ env.REGION }}
133
+ aws ecr get-login-password --region ${{ env.REGION }} | docker login --username AWS --password-stdin ${{ env.REGISTRY }}
134
+
135
+ IMAGE_NAME=${{ env.REGISTRY }}/${{ env.REPOSITORY }}:${{ env.TAG }}
136
+ CONTAINER_NAME=${{ env.REPOSITORY }}
137
+ OLD_CONTAINER_NAME="${{ env.REPOSITORY }}_old"
138
+ OLD_IMAGE_NAME=$(docker ps -a --filter "name=$CONTAINER_NAME" --format "{{.Image}}" | tail -n 1)
139
+
140
+ PORT=${{ vars.PORT }}
141
+
142
+ if [ "$(docker ps -q -f name=$CONTAINER_NAME)" ]; then
143
+ echo "Stopping the existing container..."
144
+ docker stop $CONTAINER_NAME && echo "Container stopped"
145
+ echo "Renaming the existing container..."
146
+ docker rename $CONTAINER_NAME $OLD_CONTAINER_NAME
147
+ else echo "Any container with name: $CONTAINER_NAME"
148
+ fi
149
+
150
+ if netstat -tuln | grep :$PORT; then
151
+ echo "Port $PORT is being used by another process"
152
+ exit 1
153
+ else
154
+ echo "Port $PORT is available"
155
+ fi
156
+
157
+ echo "Starting the new container..."
158
+ docker run --restart unless-stopped --name $CONTAINER_NAME -d -p $PORT:$PORT $IMAGE_NAME
159
+ sleep 10 # Wait for the container to start
160
+
161
+ echo "Testing the new container..."
162
+ if [ "$(docker ps -q -f name=${CONTAINER_NAME})" ]; then
163
+ echo "El contenedor ${CONTAINER_NAME} está en ejecución successfully."
164
+ if [ "$(docker ps -a -q -f name=$OLD_CONTAINER_NAME)" ]; then
165
+ echo "Removing the old container..."
166
+ docker rm -f $OLD_CONTAINER_NAME
167
+ fi
168
+
169
+ if [ ! -z "$OLD_IMAGE_NAME" ] && [ "$OLD_IMAGE_NAME" != "$IMAGE_NAME" ]; then
170
+ echo "Removing the old image..."
171
+ docker image prune -a -f
172
+ fi
173
+ else
174
+ echo "New container failed to start correctly. Reverting to the old container..."
175
+ docker stop $CONTAINER_NAME
176
+ docker rm -f $CONTAINER_NAME
177
+ docker rename $OLD_CONTAINER_NAME $CONTAINER_NAME
178
+ docker start $CONTAINER_NAME
179
+ docker image prune -a -f
180
+ echo "Reversion complete. Please check the logs and fix any issues."
181
+ exit 1
182
+ fi
183
+ echo "Deployment successful!"
184
+ EOF
185
+
186
+ nginx :
187
+ runs-on : ubuntu-22.04
188
+ needs : [build,deploy]
189
+ if : ${{ success() }}
190
+
191
+ steps :
192
+
193
+ - name : Setup SSH
194
+ uses : webfactory/ssh-agent@v0.9.0
195
+ with :
196
+ ssh-private-key : ${{ secrets.PRIVATE_KEY }}
197
+
198
+ - name : Add server to known hosts
199
+ run : |
200
+ mkdir -p ~/.ssh
201
+ ssh-keyscan -H ${{ secrets.REMOTE_SERVER_ADDRESS }} >> ~/.ssh/known_hosts
202
+
203
+ - name : Setup nginx
204
+ if : success()
205
+ run : |
206
+ ssh ${{ secrets.REMOTE_SERVER_USERNAME }}@${{ secrets.REMOTE_SERVER_ADDRESS }} << 'OUTER'
207
+ DOMAIN=${{ vars.NGINX_DOMAIN }}
208
+ PORT=${{ vars.PORT }}
209
+ NGINX_SITES_ENABLED="/etc/nginx/sites-enabled"
210
+ NGINX_SITES_AVAILABLE="/etc/nginx/sites-available"
211
+ CONFIG_FILE="$NGINX_SITES_AVAILABLE/$DOMAIN"
212
+
213
+ if [ -f "$CONFIG_FILE" ] && grep -q "proxy_pass .*:$PORT;" "$CONFIG_FILE"; then
214
+ echo "The file $CONFIG_FILE already exist and forward to port. Without nginx changes!"
215
+ else
216
+ if [ -f "$CONFIG_FILE" ] && ! grep -q "proxy_pass .*:$PORT;" "$CONFIG_FILE"; then
217
+ echo "La configuración de proxy_pass no reenvía al puerto $PORT."
218
+ echo "Eliminando configuracion nginx para el dominio $DOMAIN"
219
+ sudo rm /etc/nginx/sites-enabled/$DOMAIN
220
+ sudo rm /etc/nginx/sites-available/$DOMAIN
221
+ sudo certbot delete --cert-name "$DOMAIN" --non-interactive --quiet
222
+ fi
223
+
224
+ echo "El archivo $CONFIG_FILE no existe."
225
+
226
+ sudo bash -c "cat > $CONFIG_FILE <<'INNER'
227
+ server {
228
+ server_name $DOMAIN;
229
+
230
+ location / {
231
+ proxy_pass http://localhost:$PORT;
232
+ proxy_http_version 1.1;
233
+ proxy_set_header Host \$host;
234
+ proxy_cache_bypass \$http_upgrade;
235
+ }
236
+ }
237
+
238
+ server {
239
+ server_name www.$DOMAIN;
240
+ return 301 https://$DOMAIN$request_uri;
241
+ }
242
+ INNER"
243
+
244
+ sudo ln -s /etc/nginx/sites-available/$DOMAIN /etc/nginx/sites-enabled/
245
+ sudo nginx -t
246
+ sudo service nginx restart
247
+ sudo certbot --nginx -d $DOMAIN -d www.$DOMAIN --non-interactive --agree-tos --redirect --email ${{vars.NGINX_EMAIL}}
248
+ sudo service nginx restart
249
+ fi
250
+ OUTER
251
+
252
+ - name : Notify Success to Slack channel
253
+ id : slack-success
254
+ if : success()
255
+ uses : slackapi/slack-github-action@v1.26.0
256
+ with :
257
+ channel-id : ${{ secrets.SLACK_CHANNEL_ID }}
258
+ slack-message : " GitHub build result: ${{ job.status }}\n Repository Name: ${{ github.repository }}\n ${{ github.event.pull_request.html_url || github.event.head_commit.url }}"
259
+ env :
260
+ SLACK_BOT_TOKEN : ${{ secrets.SLACK_BOT_TOKEN }}
261
+
262
+ - name : Notify error to Slack channel
263
+ id : slack-error
264
+ if : failure()
265
+ uses : slackapi/slack-github-action@v1.26.0
266
+ with :
267
+ channel-id : ${{ secrets.SLACK_CHANNEL_ID }}
268
+ slack-message : " GitHub build result: ${{ job.status }}\n Repository Name: ${{ github.repository }}\n ${{ github.event.pull_request.html_url || github.event.head_commit.url }}"
269
+ env :
270
+ SLACK_BOT_TOKEN : ${{ secrets.SLACK_BOT_TOKEN }}
0 commit comments