diff --git a/.github/workflows/azure-preview-env-deploy.yml b/.github/workflows/azure-preview-env-deploy.yml index 273776088c..85b5595b2d 100644 --- a/.github/workflows/azure-preview-env-deploy.yml +++ b/.github/workflows/azure-preview-env-deploy.yml @@ -187,6 +187,8 @@ jobs: cache-from: type=registry,ref=${{ secrets.NONPROD_REGISTRY_SERVER }}/${{ github.repository }}:main-preview # `main-docker-cache.yml` handles updating the remote cache so we don't pollute it with PR specific code cache-to: '' + build-args: | + BUILD_SHA=${{ github.sha }} # Succeed despite any non-zero exit code (e.g. if there is no deployment to cancel) - name: 'Cancel any existing deployments for this PR' diff --git a/.github/workflows/azure-prod-build-deploy.yml b/.github/workflows/azure-prod-build-deploy.yml index 27bdd28f94..6721af2443 100644 --- a/.github/workflows/azure-prod-build-deploy.yml +++ b/.github/workflows/azure-prod-build-deploy.yml @@ -85,6 +85,8 @@ jobs: tags: ${{ env.DOCKER_IMAGE }}, ${{ env.DOCKER_IMAGE_CACHE_REF }} cache-from: type=registry,ref=${{ env.DOCKER_IMAGE_CACHE_REF }} cache-to: type=registry,mode=max,ref=${{ env.DOCKER_IMAGE_CACHE_REF }} + build-args: | + BUILD_SHA=${{ github.sha }} - name: 'Update docker-compose.prod.yaml template file' run: | diff --git a/Dockerfile b/Dockerfile index 2fef6655a0..c4b3447df0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -78,6 +78,11 @@ ENV PORT 4000 ENV ENABLED_LANGUAGES "en" +# This makes it possible to set `--build-arg BUILD_SHA=abc123` +# and it then becomes available as an environment variable in the docker run. +ARG BUILD_SHA +ENV BUILD_SHA=$BUILD_SHA + # Copy only what's needed to run the server COPY --chown=node:node package.json ./ COPY --chown=node:node assets ./assets diff --git a/middleware/build-info.js b/middleware/build-info.js new file mode 100644 index 0000000000..7fcf168edb --- /dev/null +++ b/middleware/build-info.js @@ -0,0 +1,13 @@ +import { cacheControlFactory } from './cache-control.js' + +const BUILD_SHA = process.env.BUILD_SHA +const noCacheControl = cacheControlFactory(0) + +export default function buildInfo(req, res, next) { + res.type('text/plain') + noCacheControl(res) + if (!BUILD_SHA) { + return res.status(404).send('Not known') + } + return res.send(`${BUILD_SHA}`) +} diff --git a/middleware/index.js b/middleware/index.js index 0fd2236812..ccc340b793 100644 --- a/middleware/index.js +++ b/middleware/index.js @@ -37,6 +37,7 @@ import search from './search.js' import healthz from './healthz.js' import anchorRedirect from './anchor-redirect.js' import remoteIP from './remote-ip.js' +import buildInfo from './build-info.js' import archivedEnterpriseVersions from './archived-enterprise-versions.js' import robots from './robots.js' import earlyAccessLinks from './contextualizers/early-access-links.js' @@ -266,6 +267,7 @@ export default function (app) { app.use('/healthz', asyncMiddleware(instrument(healthz, './healthz'))) app.use('/anchor-redirect', asyncMiddleware(instrument(anchorRedirect, './anchor-redirect'))) app.get('/_ip', asyncMiddleware(instrument(remoteIP, './remoteIP'))) + app.get('/_build', asyncMiddleware(instrument(buildInfo, './buildInfo'))) // Check for a dropped connection before proceeding (again) app.use(haltOnDroppedConnection)