diff --git a/.github/workflows/update_version.yaml b/.github/workflows/update_version.yaml index 80e5369..9cb907f 100644 --- a/.github/workflows/update_version.yaml +++ b/.github/workflows/update_version.yaml @@ -4,18 +4,20 @@ on: workflow_dispatch: schedule: - cron: "0 10 * * *" + pull_request: + branches: + - main jobs: generator: - runs-on: ubuntu-latest - outputs: - tags: ${{ steps.fetch-upstream.outputs.tags }} + name: Generate Step for new CoreDNS versions + runs-on: ubuntu-24.04 steps: - name: Checkout rock repository uses: actions/checkout@v4 with: path: coredns-rock - ref: main + ref: ${{ github.head_ref || 'main' }} - name: Checkout coredns repository uses: actions/checkout@v4 @@ -25,70 +27,22 @@ jobs: fetch-tags: true fetch-depth: 0 - - name: Get current version from rockcraft.yaml - id: currentRockVersion - uses: mikefarah/yq@master - with: - cmd: yq '.version' 'coredns-rock/rockcraft.yaml' - - - name: Fetch and filter upstream tags - id: fetch-upstream + - name: Craft using Make target + id: emit-rockcraft run: | - export DEBIAN_FRONTEND=noninteractive - sudo apt-get -qq update - sudo apt-get -qq install -y jq - - min_tag="v${{ steps.currentRockVersion.outputs.result }}" - - coredns_tags=( $(git -C coredns tag --sort=-v:refname) ) - pr_tags=() - - for coredns_tag in "${coredns_tags[@]}" - do - if [ "$min_tag" = "$coredns_tag" ]; then - break - fi - - pr_tags+=( "${coredns_tag:1}" ) - done - - if [ ${#pr_tags[@]} -eq 0 ]; then - tags='[]' - else - tags=$(printf '%s\n' "${pr_tags[@]}" | jq -R . | jq --compact-output -s .) - fi - - echo $tags - echo "tags=$tags" >> $GITHUB_OUTPUT - - update: - runs-on: ubuntu-latest - needs: generator - if: ${{ needs.generator.outputs.tags != '[]' }} - strategy: - matrix: - version: ${{ fromJSON(needs.generator.outputs.tags) }} - steps: - - name: Checkout - uses: actions/checkout@v4 + pushd coredns-rock + make COREDNS_GIT_DIR=../coredns update-component + popd + + - name: Commit and push new rockcraft.yaml + id: commit-rockcraft + if: ${{ steps.emit-rockcraft.outputs.tags != '[]' }} + uses: peter-evans/create-pull-request@v7 with: - ref: main - - - name: Update ROCK's source tag - uses: mikefarah/yq@master - with: - cmd: yq -i '.parts.coredns.source-tag = "v${{ matrix.version }}"' 'rockcraft.yaml' - - - name: Update ROCK's version - uses: mikefarah/yq@master - with: - cmd: yq -i '.version = "${{ matrix.version }}"' 'rockcraft.yaml' - - - name: Create pull request - uses: peter-evans/create-pull-request@v6 - with: - commit-message: Update CoreDNS version to ${{ matrix.version }} - title: "[${{ matrix.version }}] Update CoreDNS version" - body: Update CoreDNS version to ${{ matrix.version }} - branch: v${{ matrix.version }} + commit-message: Update CoreDNS versions with ${{ join(fromJSON(steps.emit-rockcraft.outputs.tags), ', ') }} + title: "Update CoreDNS versions" + body: Update CoreDNS versions with ${{ join(fromJSON(steps.emit-rockcraft.outputs.tags), ', ') }} + path: coredns-rock + branch: autoupdate/sync/coredns + delete-branch: true base: main diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..59095d5 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,26 @@ +# Contributing + +To make contributions to this rock, the only significant changes to be made are in the `Makefile` and the `build/` directory + +## Upgrading the components + +To Upgrade the rocks for new releases of coredns run the following make target: + +```shell +make update-component +``` + +* if `jq` or `yq` are not installed on the system, they will be when the target for those items runs +* this will clone the upstream coredns/coredns repo only for listing tags +* it will create a new rockcraft yaml based on the tags missing from this repo +* Raise a PR from a branch with the new rockcraft.yaml files + + +## Testing + +To test the rocks, run the pytest sanity check test + +```shell +cd tests +tox -e sanity +``` diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a31054c --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# Makefile for CoreDNS Rock +# Description: This Makefile installs necessary tools and updates components. + +which_jq = $(shell which jq) +which_yq = $(shell which yq) +COREDNS_GIT_DIR = /tmp/coredns.git + +.PHONY: JQ +JQ: + @if [ -z "${which_jq}" ]; then \ + echo "Installing jq..."; \ + sudo apt-get update && sudo apt-get install -y jq; \ + else \ + echo "jq is installed @ ${which_jq}"; \ + fi + +.PHONY: YQ +YQ: + @if [ -z "$(which_yq)" ]; then \ + echo "Installing yq..."; \ + sudo snap install yq; \ + else \ + echo "yq is installed @ ${which_yq}"; \ + fi + +.PHONY: install-tools +install-tools: JQ YQ + @echo "Tools installed." + +.PHONY: clone-CoreDNS +clone-CoreDNS: + @echo "Cloning CoreDNS..." + @if [ -d $(COREDNS_GIT_DIR) ]; then \ + echo "CoreDNS already cloned."; \ + else \ + mkdir -p $(COREDNS_GIT_DIR); \ + git clone --bare --filter=blob:none --no-checkout https://github.com/coredns/coredns.git $(COREDNS_GIT_DIR); \ + fi + +.PHONY: update-component +update-component: install-tools clone-CoreDNS + @echo "Updating component..." + @COREDNS_GIT_DIR=$(COREDNS_GIT_DIR) build/craft_release.sh + +# Target to remove the temporary directory +clean: + @rm -rf $(COREDNS_GIT_DIR) + @echo "Temporary directory removed: $(COREDNS_GIT_DIR)" \ No newline at end of file diff --git a/build/craft_release.sh b/build/craft_release.sh new file mode 100755 index 0000000..85635e0 --- /dev/null +++ b/build/craft_release.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +# This script is used to create a new release rock image from the included template +set -eu + +RO_SCRIPT_DIR="$( dirname "${BASH_SOURCE[0]}")" +RO_REPO_DIR=$(dirname ${RO_SCRIPT_DIR}) +RO_VERSIONS=${RO_SCRIPT_DIR}/../versions.txt + +function usage() { + if [[ -z ${COREDNS_GIT_DIR+x} ]]; then + echo "COREDNS_GIT_DIR is not set" > /dev/stderr + echo " Clone with 'git clone --bare --filter=blob:none --no-checkout https://github.com/coredns/coredns.git /tmp/coredns.git'" > /dev/stderr + echo " Re-run with 'COREDNS_GIT_DIR=/tmp/coredns.git $0'" > /dev/stderr + exit 1 + fi +} + + +function check_dependencies(){ + for cmd in yq jq git envsubst; do + if ! command -v $cmd &> /dev/null; then + echo "$cmd could not be found" > /dev/stderr + exit 1 + fi + done +} + + +function create_rockcrafts(){ + # Get the current releases from existing rockcraft yamls + if [[ -v GITHUB_WORKSPACE ]]; then + echo "::group::Create rockcrafts" + fi + + rm -rf ${RO_VERSIONS} + for rockcraft in $(find ${RO_REPO_DIR} -name 'rockcraft.yaml'); do + echo $(yq '.version' $rockcraft) >> ${RO_VERSIONS} + done + current_releases=( $(sort -V ${RO_VERSIONS}) ) + min_tag="v${current_releases[0]}" # this is the oldest release tag we support + rm -rf ${RO_VERSIONS} + + # Get the tags from the coredns repo, ignoring all before the min_tag + coredns_tags=( $(git -C ${COREDNS_GIT_DIR} tag --sort=v:refname | sed -n '/'${min_tag}'/,$p') ) + new_tags=() + + for coredns_tag in "${coredns_tags[@]}"; do + if [[ ! -e ${RO_REPO_DIR}/${coredns_tag:1}/rockcraft.yaml ]]; then + new_tag=${coredns_tag:1} + new_tags+=($new_tag) + echo "Creating rockcraft.yaml for ${new_tag}" + mkdir -p ${RO_REPO_DIR}/${new_tag} + unset ignored_template_var + tag=${new_tag} envsubst < ${RO_SCRIPT_DIR}/template/rockcraft.yaml.in > ${RO_REPO_DIR}/${new_tag}/rockcraft.yaml + else + echo "Skipping ${coredns_tag} as it already exists" + fi + done + + if [ ${#new_tags[@]} -eq 0 ]; then + tags='[]' + else + tags=$(printf '%s\n' "${new_tags[@]}" | jq -R . | jq --compact-output -s .) + fi + if [[ -v GITHUB_OUTPUT ]]; then + echo "tags=$tags" >> $GITHUB_OUTPUT + fi + if [[ -v GITHUB_WORKSPACE ]]; then + echo "::endgroup::" + fi + +} + + +function main() { + usage + check_dependencies + create_rockcrafts +} + +main \ No newline at end of file diff --git a/build/template/rockcraft.yaml.in b/build/template/rockcraft.yaml.in new file mode 100644 index 0000000..8eb1de0 --- /dev/null +++ b/build/template/rockcraft.yaml.in @@ -0,0 +1,37 @@ +name: coredns +summary: ROCK for the CoreDNS Project. +description: This ROCK is a drop in replacement for the coredns/coredns image. +version: "${tag}" +license: Apache-2.0 + +base: bare +build-base: ubuntu@22.04 +platforms: + amd64: + arm64: + +entrypoint-service: coredns +services: + coredns: + override: replace + summary: "coredns service" + startup: enabled + command: "/coredns [ -conf /etc/coredns/Corefile ]" + on-failure: shutdown + +parts: + coredns: + plugin: nil + source: https://github.com/coredns/coredns + source-type: git + source-tag: v${tag} + source-depth: 1 + build-packages: + - build-essential + build-snaps: + - go/1.21/stable + stage-packages: + - ca-certificates_data + override-build: | + make + cp $${ignored_template_var}CRAFT_PART_BUILD/coredns $${ignored_template_var}CRAFT_PRIME diff --git a/tests/sanity/test_rock.py b/tests/sanity/test_rock.py index 4defa55..b8b2765 100644 --- a/tests/sanity/test_rock.py +++ b/tests/sanity/test_rock.py @@ -2,11 +2,23 @@ # Copyright 2024 Canonical, Ltd. # +from pathlib import Path + import pytest +import yaml from k8s_test_harness.util import docker_util, env_util +TEST_PATH = Path(__file__) +REPO_PATH = TEST_PATH.parent.parent.parent + + +def _image_versions(): + all_rockcrafts = REPO_PATH.glob("**/rockcraft.yaml") + yamls = [yaml.safe_load(rock.read_bytes()) for rock in all_rockcrafts] + return [rock["version"] for rock in yamls] + -@pytest.mark.parametrize("image_version", ["1.11.1", "1.11.3"]) +@pytest.mark.parametrize("image_version", _image_versions()) def test_sanity(image_version): rock = env_util.get_build_meta_info_for_rock_version( "coredns", image_version, "amd64"