Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test-fork #72

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 88 additions & 44 deletions .github/actions/build/action.yml
Original file line number Diff line number Diff line change
@@ -1,85 +1,129 @@
name: 'Docker Build'
description: 'Builds docker image'
inputs:
push:
required: true
description: "Build and push image to registry (cannot be used together with load)"
default: "false"
password:
required: false
description: "Password for the registry"
username:
required: false
description: "Username for the registry"
node_env:
required: false
description: "Node environment"
default: "production"
latest:
required: false
description: "Tag latest version"
default: "false"
target:
required: false
description: "Docker stage to target"
default: "final"
push:
required: false
description: "Should image be pushed to registries"
default: "false"

outputs:
tags:
description: "The Docker tags for the image"
value: ${{ steps.meta.outputs.tags }}
version:
description: "The version for the image"
value: ${{ steps.meta.outputs.version }}
image:
description: "The Docker image"
value: ${{ steps.image.outputs.image }}
image_version:
version:
description: "The version for the image"
value: ${{ steps.meta.outputs.version }}
digest:
description: "The build digest for the image"
value: ${{ steps.build.outputs.digest }}
tag:
description: "Combines image and version to a valid image tag"
value: ${{ steps.image.outputs.image }}:${{ steps.meta.outputs.version }}
value: ${{ steps.tag.outputs.tag }}

runs:
using: "composite"
steps:
# Setup docker to build for multiple architectures
- 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: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
with:
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
echo "image=${{ github.repository }}" >> $GITHUB_OUTPUT
cat $GITHUB_OUTPUT

- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ steps.image.outputs.image }}
images: |
ghcr.io/${{ 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 <<EOF > meta.json
${{ steps.meta.outputs.json }}
EOF

echo "tag=$(cat meta.json | jq -r '.tags[0]')" >> $GITHUB_OUTPUT
cat $GITHUB_OUTPUT

- name: Tar file
id: tar
shell: bash
# image.tar is the name of the compressed image file
# This should be kept in sync with ./.github/actions/run/action.yml
# That loads the image from this file
run: |
echo "path=/tmp/image.tar" >> $GITHUB_OUTPUT

- name: Build Image
uses: docker/build-push-action@v5
id: build
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64
pull: true
push: ${{ inputs.push }}
load: ${{ inputs.push == 'false' }}
# Inject metadata produced earlier
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 }}
labels: ${{ steps.meta.outputs.labels }}
annotations: ${{ steps.meta.outputs.annotations }}
# Output image to a local tar file to be uploaded
# Also push to registry when appropriate
outputs: |
type=docker,dest=${{ steps.tar.outputs.path }}
type=image,name=${{ steps.tag.outputs.tag }},push=${{ inputs.push }}
# Target a specified stage
target: ${{ inputs.target }}

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
# The artifact name should be kept in sync with
# ./.github/actions/run/action.yml which downloads the artifact
name: docker-image
path: ${{ steps.tar.outputs.path }}
retention-days: 1
compression-level: 9
overwrite: true

- name: Load Docker image
shell: bash
run: |
# Load the Docker image
docker load -i /tmp/image.tar
80 changes: 80 additions & 0 deletions .github/actions/context/action.yml
Original file line number Diff line number Diff line change
@@ -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:
Expand Down Expand Up @@ -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
32 changes: 32 additions & 0 deletions .github/actions/push/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: 'Docker Push image to registry'
description: 'Pushes build docker image to registry'
inputs:
tag:
required: true
description: "The full docker tag to push"
password:
required: false
description: "Password for the registry"
username:
required: false
description: "Username for the registry"
registry:
required: false
description: "The registry to push to"
default: "ghcr.io"

runs:
using: "composite"
steps:
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ inputs.registry }}
username: ${{ inputs.username }}
password: ${{ inputs.password }}

- name: Push Image
shell: bash
run: |
docker image ls
docker image push ${{ inputs.registry }}/${{ inputs.tag }}
66 changes: 25 additions & 41 deletions .github/actions/run/action.yml
Original file line number Diff line number Diff line change
@@ -1,58 +1,42 @@
name: 'Docker Run Action'
description: 'Run a command in a new container'
inputs:
image:
description: "The Docker image to run"
tag:
description: 'The docker image tag to run.'
required: true
options:
description: 'Options'
required: false
run:
description: 'Run command in container'
required: true
runs:
using: 'composite'
steps:
- name: Validate inputs
- uses: actions/download-artifact@v4
with:
# The artifact name should be kept in sync with
# ./.github/actions/build/action.yml which uploads the artifact
name: docker-image
path: /tmp/

# image.tar is the name of the compressed image file
# This should be kept in sync with ./.github/actions/build/action.yml
- name: Load image
shell: bash
run: |
if [[ -z "${{ inputs.image }}" ]]; then
echo "Image is required"
exit 1
fi
if [[ -z "${{ inputs.run }}" ]]; then
echo "Run is required"
exit 1
fi
docker load < /tmp/image.tar
docker image ls

- name: Run Docker Container
shell: bash
env:
DOCKER_TAG: ${{ inputs.tag }}
run: |
cat <<EOF > exec.sh
#!/bin/bash
whoami
${{ inputs.run }}
EOF
# Start the specified services
make up

cat <<EOF > root.sh
#!/bin/bash
whoami
su -s /bin/bash -c './exec.sh' root
# Exec the run command in the container
# quoted 'EOF' to prevent variable expansion
cat <<'EOF' | docker compose exec --user root app sh
#!/bin/bash
whoami
${{ inputs.run }}
EOF

# Make both files executable
chmod +x exec.sh
chmod +x root.sh

# Debug info
echo "############"
cat root.sh
echo "############"
echo "############"
cat exec.sh
echo "############"

# Execute inside docker container
cat root.sh | docker run ${{ inputs.options }} \
-i --rm -u 0 \
-v $(pwd):/app \
${{ inputs.image }} bash
Loading
Loading