fix: fix OPF PR labelling (#11154) #3551
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Container Image Deployment CI | |
on: | |
push: | |
branches: | |
- main | |
- deploy-* | |
tags: | |
- v*.*.* | |
# Note on secrets used for connection | |
# SSH_PRIVATE_KEY is the private key (shared between VM and host) | |
jobs: | |
deploy: | |
runs-on: ubuntu-latest | |
strategy: | |
matrix: | |
env: | |
- ${{ startsWith(github.ref, 'refs/tags/v') && 'off-org' || 'off-net' }} | |
environment: ${{ matrix.env }} | |
concurrency: ${{ matrix.env }} | |
steps: | |
# Put here non secret variables that change according to environment | |
- name: Set various variable for staging (net) deployment | |
if: matrix.env == 'off-net' | |
run: | | |
# direct container access | |
echo "REDIS_URL=redis:6379" >> $GITHUB_ENV | |
echo "RATE_LIMITER_BLOCKING_ENABLED=0" >> $GITHUB_ENV | |
echo "MONGODB_HOST=10.1.0.200" >> $GITHUB_ENV | |
echo "ROBOTOFF_URL=https://robotoff.openfoodfacts.net" >> $GITHUB_ENV | |
echo "QUERY_URL=http://10.1.0.200:5511" >> $GITHUB_ENV | |
echo "PRODUCT_OPENER_DOMAIN=openfoodfacts.net" >> $GITHUB_ENV | |
echo "PRODUCT_OPENER_FLAVOR=openfoodfacts" >> $GITHUB_ENV | |
echo "PRODUCT_OPENER_FLAVOR_SHORT=off" >> $GITHUB_ENV | |
echo "POSTGRES_USER=postgres" >> $GITHUB_ENV | |
echo "CROWDIN_PROJECT_IDENTIFIER=openfoodfacts" >> $GITHUB_ENV | |
echo "GEOLITE2_PATH=/usr/local/share/GeoLite2-Country/GeoLite2-Country.mmdb" >> $GITHUB_ENV | |
echo "INFLUXDB_HOST=10.1.0.200" >> $GITHUB_ENV | |
echo "FACETS_KP_URL=https://facets-kp.openfoodfacts.net/render-to-html" >> $GITHUB_ENV | |
echo "NUTRIPATROL_URL=nutripatrol.openfoodfacts.net" >> $GITHUB_ENV | |
# deploy target | |
echo "SSH_HOST=10.1.0.200" >> $GITHUB_ENV | |
echo "SSH_PROXY_HOST=ovh1.openfoodfacts.org" >> $GITHUB_ENV | |
echo "SSH_USERNAME=off" >> $GITHUB_ENV | |
- name: Set various variable for prod (org) deployment | |
if: matrix.env == 'off-org' | |
run: | | |
# FIXME: we do not deploy to prod currently | |
false | |
- name: Check for an eventual NO_DEPLOY file to put deployment on hold | |
uses: appleboy/ssh-action@master | |
with: | |
host: ${{ env.SSH_HOST }} | |
username: ${{ env.SSH_USERNAME }} | |
key: ${{ secrets.SSH_PRIVATE_KEY }} | |
proxy_host: ${{ env.SSH_PROXY_HOST }} | |
proxy_username: ${{ env.SSH_USERNAME }} | |
proxy_key: ${{ secrets.SSH_PRIVATE_KEY }} | |
script: | | |
if [[ -f /home/off/${{ matrix.env }}/NO_DEPLOY ]] | |
then | |
>&2 echo "A NO_DEPLOY file exists (in /home/off/${{ matrix.env }}), failing !" | |
exit 1 | |
fi | |
- name: Wait for frontend container build workflow | |
uses: tomchv/wait-my-workflow@v1.1.0 | |
id: wait-build | |
with: | |
token: ${{ secrets.GITHUB_TOKEN }} | |
checkName: build (frontend) | |
ref: ${{ github.event.pull_request.head.sha || github.sha }} | |
intervalSeconds: 10 | |
timeoutSeconds: 600 # 10m | |
- name: Wait for backend container build workflow | |
uses: tomchv/wait-my-workflow@v1.1.0 | |
id: wait-build2 | |
with: | |
token: ${{ secrets.GITHUB_TOKEN }} | |
checkName: build (backend) | |
ref: ${{ github.event.pull_request.head.sha || github.sha }} | |
intervalSeconds: 10 | |
timeoutSeconds: 600 # 10m | |
- name: Do something if build isn't launch | |
if: steps.wait-build.outputs.conclusion == 'does not exist' || steps.wait-build2.outputs.conclusion == 'does not exist' | |
run: echo job does not exist && true | |
- name: Do something if build fail | |
if: steps.wait-build.outputs.conclusion == 'failure' || steps.wait-build2.outputs.conclusion == 'failure' | |
run: echo fail && false # fail if build fail | |
- name: Do something if build timeout | |
if: steps.wait-build.outputs.conclusion == 'timed_out' || steps.wait-build2.outputs.conclusion == 'timed_out' | |
run: echo Timeout && false # fail if build time out | |
- name: Checkout git repository | |
uses: appleboy/ssh-action@master | |
with: | |
host: ${{ env.SSH_HOST }} | |
username: ${{ env.SSH_USERNAME }} | |
key: ${{ secrets.SSH_PRIVATE_KEY }} | |
proxy_host: ${{ env.SSH_PROXY_HOST }} | |
proxy_username: ${{ env.SSH_USERNAME }} | |
proxy_key: ${{ secrets.SSH_PRIVATE_KEY }} | |
script_stop: false | |
script: | | |
# while we would use shallow clone on a normal repo, | |
# comparison is too costly for this project and takes too much time, so we use a regular clone | |
# Clone Git repository if not already there | |
[ ! -d '${{ matrix.env }}' ] && git clone https://github.com/${{ github.repository }} ${{ matrix.env }} 2>&1 | |
# Go to repository directory | |
cd ${{ matrix.env }} | |
# Fetch newest commits (in case it wasn't freshly cloned) | |
# here again we use full depth instead of usual --depth 1, because of perf problems | |
git fetch | |
# Checkout current commit SHA | |
git checkout -qf ${{ github.sha }} | |
- name: Set environment variables | |
uses: appleboy/ssh-action@master | |
with: | |
host: ${{ env.SSH_HOST }} | |
username: ${{ env.SSH_USERNAME }} | |
key: ${{ secrets.SSH_PRIVATE_KEY }} | |
proxy_host: ${{ env.SSH_PROXY_HOST }} | |
proxy_username: ${{ env.SSH_USERNAME }} | |
proxy_key: ${{ secrets.SSH_PRIVATE_KEY }} | |
script_stop: false | |
script: | | |
# Go to repository directory | |
cd ${{ matrix.env }} | |
# init .env | |
echo "# Env file generated by container-deploy action"> .env | |
# Set Docker Compose variables | |
echo "DOCKER_CLIENT_TIMEOUT=360" >> .env | |
echo "COMPOSE_HTTP_TIMEOUT=360" >> .env | |
echo "COMPOSE_PROJECT_NAME=po" >> .env | |
echo "COMPOSE_PATH_SEPARATOR=;" >> .env | |
echo "COMPOSE_FILE=docker-compose.yml;docker/prod.yml;docker/geolite2.yml;docker/monitor.yml" >> .env | |
echo "COMPOSE_FILE_BUILD=docker-compose.yml;docker/prod.yml" >> .env | |
echo "COMPOSE_PROFILES=off" >> .env | |
echo "PRODUCT_OPENER_EXPOSE=" >> .env | |
echo "ADMIN_EXPOSE=" >> .env | |
# Set App variables | |
echo "TAG=sha-${{ github.sha }}" >> .env | |
echo "WEB_RESOURCES_PATH=../off-web-net/" >> .env | |
echo "PRODUCERS_PLATFORM=0" >> .env | |
echo "PRODUCT_OPENER_PORT=80" >> .env | |
echo "PRODUCT_OPENER_DOMAIN=${{ env.PRODUCT_OPENER_DOMAIN }}" >> .env | |
echo "PRODUCT_OPENER_FLAVOR=${{ env.PRODUCT_OPENER_FLAVOR }}" >> .env | |
echo "PRODUCT_OPENER_FLAVOR_SHORT=${{ env.PRODUCT_OPENER_FLAVOR_SHORT }}" >> .env | |
echo "MINION_MODE=production" >> .env | |
echo "MINION_QUEUE=${{ env.PRODUCT_OPENER_DOMAIN }}" >> .env | |
echo "MONGODB_HOST=${{ env.MONGODB_HOST }}" >> .env | |
echo "POSTGRES_USER=${{ env.POSTGRES_USER }}" >> .env | |
echo "POSTGRES_PASSWORD=${{ secrets.POSTGRES_PASSWORD }}" >> .env | |
echo "ROBOTOFF_URL=${{ env.ROBOTOFF_URL }}" >> .env | |
echo "QUERY_URL=${{ env.QUERY_URL }}" >> .env | |
echo "REDIS_URL=${{ env.REDIS_URL }}" >> .env | |
echo "FACETS_KP_URL=${{ env.FACETS_KP_URL }}" >> .env | |
echo "NUTRIPATROL_URL=${{ env.NUTRIPATROL_URL }}" >> .env | |
echo "GOOGLE_CLOUD_VISION_API_KEY=${{ secrets.GOOGLE_CLOUD_VISION_API_KEY }}" >> .env | |
echo "CROWDIN_PROJECT_IDENTIFIER=${{ env.CROWDIN_PROJECT_IDENTIFIER }}" >> .env | |
echo "CROWDIN_PROJECT_KEY=${{ secrets.CROWDIN_PROJECT_KEY }}" >> .env | |
echo "GEOLITE2_PATH=${{ env.GEOLITE2_PATH }}" >> .env | |
echo "GEOLITE2_LICENSE_KEY=${{ secrets.GEOLITE2_LICENSE_KEY }}" >> .env | |
echo "GEOLITE2_ACCOUNT_ID=${{ secrets.GEOLITE2_ACCOUNT_ID }}" >> .env | |
echo "INFLUXDB_HOST=${{ env.INFLUXDB_HOST }}" >> .env | |
echo "LOG_LEVEL_ROOT=ERROR" >> .env | |
echo "LOG_LEVEL_MONGODB=ERROR" >> .env | |
echo "LOG_LEVEL_RATE_LIMITER=INFO" >> .env | |
echo "BUILD_CACHE_REPO=openfoodfacts/openfoodfacts-build-cache" >> .env | |
# Override domain name in nginx.conf | |
sed -i.bak "s/productopener.localhost/${{ env.PRODUCT_OPENER_DOMAIN }}/g" ./conf/nginx-docker/nginx.conf | |
- name: Create Docker volumes and network | |
uses: appleboy/ssh-action@master | |
with: | |
host: ${{ env.SSH_HOST }} | |
username: ${{ env.SSH_USERNAME }} | |
key: ${{ secrets.SSH_PRIVATE_KEY }} | |
proxy_host: ${{ env.SSH_PROXY_HOST }} | |
proxy_username: ${{ env.SSH_USERNAME }} | |
proxy_key: ${{ secrets.SSH_PRIVATE_KEY }} | |
script_stop: false | |
script: | | |
cd ${{ matrix.env }} && \ | |
make create_external_volumes && \ | |
make create_external_networks | |
- name: wait for docker images to be available | |
# we sometimes have the images not ready immediately after build, so we prefer to wait for it | |
uses: appleboy/ssh-action@master | |
with: | |
host: ${{ env.SSH_HOST }} | |
username: ${{ env.SSH_USERNAME }} | |
key: ${{ secrets.SSH_PRIVATE_KEY }} | |
proxy_host: ${{ env.SSH_PROXY_HOST }} | |
proxy_username: ${{ env.SSH_USERNAME }} | |
proxy_key: ${{ secrets.SSH_PRIVATE_KEY }} | |
command_timeout: 25m | |
script_stop: false | |
script: | | |
waited=0 | |
for IMAGE_TYPE in frontend backend | |
do | |
image_name=ghcr.io/${{ github.repository }}/$IMAGE_TYPE:sha-${{ github.sha }} | |
# pull image, eventually waiting for it to be available in ghcr.io | |
while ! (docker pull $image_name); do | |
sleep 30 | |
waited=$((waited+30)) | |
# timeout after 6 minutes (gloablly) | |
if [[ $waited -gt 360 ]]; then | |
echo "Timeout waiting for image $image_name" | |
# Abort the job | |
exit 1 | |
fi | |
done | |
done | |
- name: initialize the backend | |
uses: appleboy/ssh-action@master | |
with: | |
host: ${{ env.SSH_HOST }} | |
username: ${{ env.SSH_USERNAME }} | |
key: ${{ secrets.SSH_PRIVATE_KEY }} | |
proxy_host: ${{ env.SSH_PROXY_HOST }} | |
proxy_username: ${{ env.SSH_USERNAME }} | |
proxy_key: ${{ secrets.SSH_PRIVATE_KEY }} | |
command_timeout: 25m | |
script_stop: false | |
script: | | |
cd ${{ matrix.env }} && \ | |
make init_backend | |
- name: Start services | |
uses: appleboy/ssh-action@master | |
with: | |
host: ${{ env.SSH_HOST }} | |
username: ${{ env.SSH_USERNAME }} | |
key: ${{ secrets.SSH_PRIVATE_KEY }} | |
proxy_host: ${{ env.SSH_PROXY_HOST }} | |
proxy_username: ${{ env.SSH_USERNAME }} | |
proxy_key: ${{ secrets.SSH_PRIVATE_KEY }} | |
command_timeout: 15m | |
script_stop: false | |
script: | | |
cd ${{ matrix.env }} && \ | |
make hdown && \ | |
make build_lang && \ | |
make prod_up | |
- name: Check services are up | |
uses: appleboy/ssh-action@master | |
if: ${{ always() }} | |
with: | |
host: ${{ env.SSH_HOST }} | |
username: ${{ env.SSH_USERNAME }} | |
key: ${{ secrets.SSH_PRIVATE_KEY }} | |
proxy_host: ${{ env.SSH_PROXY_HOST }} | |
proxy_username: ${{ env.SSH_USERNAME }} | |
proxy_key: ${{ secrets.SSH_PRIVATE_KEY }} | |
script_stop: false | |
script: | | |
cd ${{ matrix.env }} && \ | |
make livecheck | |
- name: Cleanup obsolete Docker objects | |
uses: appleboy/ssh-action@master | |
if: ${{ always() }} | |
with: | |
host: ${{ env.SSH_HOST }} | |
username: ${{ env.SSH_USERNAME }} | |
key: ${{ secrets.SSH_PRIVATE_KEY }} | |
proxy_host: ${{ env.SSH_PROXY_HOST }} | |
proxy_username: ${{ env.SSH_USERNAME }} | |
proxy_key: ${{ secrets.SSH_PRIVATE_KEY }} | |
script_stop: false | |
script: | | |
cd ${{ matrix.env }} && \ | |
make prune | |
- uses: basos9/grafana-annotation-action@v1.0.3 | |
if: ${{ always() }} | |
with: | |
apiHost: https://grafana.openfoodfacts.org | |
apiToken: ${{ secrets.GRAFANA_API_TOKEN }} | |
text: <a href="https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}">Deployment ${{ steps.livecheck.outcome }} on ${{ matrix.env }}</a> | |
tags: type:deployment,origin:github,status:${{ steps.livecheck.outcome }},repo:${{ github.repository }},sha:${{ github.sha }},app:robotoff,env:${{ matrix.env }} |