diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index d4c9bbf..7410fc1 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: @@ -42,44 +46,94 @@ runs: version: latest buildkitd-flags: --debug - # Login to a registry to push the image - - name: Login to Container Registry - # Only login if we are pushing the image - if: ${{ inputs.push == 'true' }} - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ inputs.username }} - password: ${{ inputs.password }} - - name: Docker Image id: image shell: bash run: | - echo "image=ghcr.io/mozilla/test-github-features" >> $GITHUB_OUTPUT + registry="ghcr.io" + repository="${{ github.repository }}" + image="$registry/$repository" + + echo "registry=$registry" >> $GITHUB_OUTPUT + echo "repository=$repository" >> $GITHUB_OUTPUT + echo "image=$image" >> $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 + type=ref,event=branch + type=ref,event=tag + + - name: Docker tag + id: tag + shell: bash + run: | + # Extract metadata output json + cat < meta.json + ${{ steps.meta.outputs.json }} + EOF + + tag=$(cat meta.json | jq -r '.tags[0]') + tag_cache="$tag-cache" + + echo "tag=$tag" >> $GITHUB_OUTPUT + echo "tag_cache=$tag_cache" >> $GITHUB_OUTPUT + + cat $GITHUB_OUTPUT + + - name: Tar file + id: tar + shell: bash + run: | + echo "path=/tmp/${{ steps.meta.outputs.version }}" >> $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 - 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 }} + targets: app + set: | + *.output=type=docker,dest=${{ steps.tar.outputs.path }} + + - name: Get image digest + id: digest + shell: bash + run: | + echo '${{ steps.build.outputs.metadata }}' > metadata.json + echo "digest=$(cat metadata.json | jq -r '.app."containerimage.digest"')" >> $GITHUB_OUTPUT + cat $GITHUB_OUTPUT + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ steps.meta.outputs.version }} + path: ${{ steps.tar.outputs.path }} + retention-days: 1 + compression-level: 9 + overwrite: true + + - name: Login to Container Registry + if: inputs.push == 'true' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ inputs.username }} + password: ${{ inputs.password }} + + - name: Push Image + if: inputs.push == 'true' + shell: bash + run: | + docker load < ${{ steps.tar.outputs.path }} + docker image push --all-tags ${{ steps.image.outputs.image }} 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..c93a0e4 --- /dev/null +++ b/.github/workflows/push.yml @@ -0,0 +1,53 @@ +name: Push + +on: + push: + branches: + - main + pull_request: + +permissions: + packages: write + +jobs: + build: + runs-on: ubuntu-latest + + outputs: + version: ${{ steps.build.outputs.version }} + + steps: + - uses: actions/checkout@v4 + + - id: context + uses: ./.github/actions/context + + - uses: ./.github/actions/build + id: build + with: + push: ${{ steps.context.outputs.is_fork == 'false' }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + node_env: production + latest: ${{ steps.context.outputs.is_release_master }} + + download: + runs-on: ubuntu-latest + needs: [build] + + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + name: ${{ needs.build.outputs.version }} + path: /tmp/ + + - name: Load image + shell: bash + run: | + docker load < /tmp/${{ needs.build.outputs.version }} + docker image ls + + + diff --git a/.github/workflows/worker.yml b/.github/workflows/worker.yml index c60151b..47f25ef 100644 --- a/.github/workflows/worker.yml +++ b/.github/workflows/worker.yml @@ -1,4 +1,4 @@ -name: Worker +name: Worker (fork) on: workflow_call: 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: