diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index d4c9bbf..9355f07 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -15,6 +15,10 @@ inputs: required: false description: "Node environment" default: "production" + latest: + required: false + description: "Tag latest version" + default: "false" outputs: tags: @@ -56,30 +60,54 @@ runs: id: image shell: bash run: | - echo "image=ghcr.io/mozilla/test-github-features" >> $GITHUB_OUTPUT + registry="ghcr.io" + repository="${{ github.repository_owner }}" + name="${{ github.repository.name }}" + version="${{ inputs.version }}" + + image="$registry/$repository/$name" + tag="$image:$version" + tag_cache="$image:$version-cache" + + echo "registry=$registry" >> $GITHUB_OUTPUT + echo "repository=$repository" >> $GITHUB_OUTPUT + echo "name=$name" >> $GITHUB_OUTPUT + echo "version=$version" >> $GITHUB_OUTPUT + echo "image=$image" >> $GITHUB_OUTPUT + echo "tag=$tag" >> $GITHUB_OUTPUT + echo "tag_cache=$tag_cache" >> $GITHUB_OUTPUT + + cat $GITHUB_OUTPUT - name: Docker meta id: meta uses: docker/metadata-action@v5 with: images: ${{ steps.image.outputs.image }} + flavor: | + suffix=-next,onlatest=true + latest=${{ inputs.latest == 'true' }} tags: | - type=raw,value=latest,enable={{is_default_branch}} - type=raw,value=staging,enable=${{ github.event_name == 'merge_group' }} - type=ref,event=pr - type=sha + # We control the image name based on the input version + type=raw,value=${{ steps.image.outputs.version }} + + - name: Set DOCKER_TAG + id: tag + shell: bash + run: | + tag="${{ steps.image.outputs.image }}:${{ steps.meta.outputs.version }}" + echo "tag=$tag" >> $GITHUB_OUTPUT + echo "tag_cache=$tag-cache" >> $GITHUB_OUTPUT - name: Build Image - uses: docker/build-push-action@v5 + id: build + uses: docker/bake-action@v4 + env: + DOCKER_TAG: ${{ steps.tag.outputs.tag }} with: - context: . - platforms: linux/amd64 - pull: true + targets: app push: ${{ inputs.push }} load: ${{ inputs.push == 'false' }} - tags: ${{ steps.meta.outputs.tags }} - cache-from: type=gha - cache-to: type=gha,mode=max - build-args: | - VERSION=${{ steps.meta.outputs.tags }} - NODE_ENV=${{ inputs.node_env }} + set: | + *.cache-from=type=registry,ref=${{ steps.tag.outputs.tag_cache }} + *.cache-to=type=registry,ref=${{ steps.tag.outputs.tag_cache }},mode=max,compression-level=9,force-compression=true,ignore-error=true diff --git a/.github/actions/context/action.yml b/.github/actions/context/action.yml index 284638f..0b69210 100644 --- a/.github/actions/context/action.yml +++ b/.github/actions/context/action.yml @@ -1,6 +1,30 @@ name: 'Dump Context' description: 'Display context for action run' +outputs: + # All github action outputs are strings, even if set to "true" + # so when using these values always assert against strings or convert from json + # \$\{{ needs.context.outputs.is_fork == 'true' }} // true + # \$\{{ fromJson(needs.context.outputs.is_fork) == false }} // true + # \$\{{ needs.context.outputs.is_fork == true }} // false + # \$\{{ needs.context.outputs.is_fork }} // false + is_fork: + description: "" + value: ${{ steps.context.outputs.is_fork }} + is_default_branch: + description: "" + value: ${{ steps.context.outputs.is_default_branch }} + is_release_master: + description: "" + value: ${{ steps.context.outputs.is_release_master }} + is_release_tag: + description: "" + value: ${{ steps.context.outputs.is_release_tag }} + # Hardcode image name + image_name: + description: "" + value: mozilla/addons-server + runs: using: 'composite' steps: @@ -36,3 +60,59 @@ runs: INPUTS_CONTEXT: ${{ toJson(inputs) }} run: | echo "$INPUTS_CONTEXT" + + - name: Set context + id: context + env: + # The default branch of the repository, in this case "master" + default_branch: ${{ github.event.repository.default_branch }} + shell: bash + run: | + event_name="${{ github.event_name }}" + event_action="${{ github.event.action }}" + + # Stable check for if the workflow is running on the default branch + # https://stackoverflow.com/questions/64781462/github-actions-default-branch-variable + is_default_branch="${{ format('refs/heads/{0}', env.default_branch) == github.ref }}" + + # In most events, the epository refers to the head which would be the fork + is_fork="${{ github.event.repository.fork }}" + + # This is different in a pull_request where we need to check the head explicitly + if [[ "${{ github.event_name }}" == 'pull_request' ]]; then + # repository on a pull request refers to the base which is always mozilla/addons-server + is_head_fork="${{ github.event.pull_request.head.repo.fork }}" + # https://docs.github.com/en/code-security/dependabot/working-with-dependabot/automating-dependabot-with-github-actions + is_dependabot="${{ github.actor == 'dependabot[bot]' }}" + + # If the head repository is a fork or if the PR is opened by dependabot + # we consider the run to be a fork. Dependabot and proper forks are treated + # the same in terms of limited read only github token scope + if [[ "$is_head_fork" == 'true' || "$is_dependabot" == 'true' ]]; then + is_fork="true" + fi + fi + + is_release_master="false" + is_release_tag="false" + + # Releases can only happen if we are NOT on a fork + if [[ "$is_fork" == 'false' ]]; then + # A master release occurs on a push to the default branch of the origin repository + if [[ "$event_name" == 'push' && "$is_default_branch" == 'true' ]]; then + is_release_master="true" + fi + + # A tag release occurs when a release is published + if [[ "$event_name" == 'release' && "$event_action" == 'publish' ]]; then + is_release_tag="true" + fi + fi + + echo "is_default_branch=$is_default_branch" >> $GITHUB_OUTPUT + echo "is_fork=$is_fork" >> $GITHUB_OUTPUT + echo "is_release_master=$is_release_master" >> $GITHUB_OUTPUT + echo "is_release_tag=$is_release_tag" >> $GITHUB_OUTPUT + + echo "event_name: $event_name" + cat $GITHUB_OUTPUT diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml new file mode 100644 index 0000000..596db8f --- /dev/null +++ b/.github/workflows/push.yml @@ -0,0 +1,30 @@ +name: Push + +on: + push: + branches: + - main + pull_request: + +permissions: + packages: write + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - id: context + uses: ./.github/actions/context + + - uses: ./.github/actions/build + with: + push: true + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + node_env: production + latest: ${{ steps.context.outputs.is_release_master }} + + diff --git a/docker-compose.yml b/docker-compose.yml index 633f92d..85f3477 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,7 @@ version: '3.8' services: app: + image: ${DOCKER_TAG:-} build: context: . args: