GitHub工作流程:仅在主上构建时,我该如何标记Docker图像?

发布于 2025-02-08 13:12:13 字数 5500 浏览 1 评论 0 原文

我已经四处挖掘了一段时间,无法完全弄清楚如何实现这一目标。

我现在拥有的:端到端,我有两个工作流程。一个监视新的Pi-hole版本,而另一个则在新提交时会构建Docker图像。

目标:使用github工作流程,只有在提交 master 分支时,我想构建一个用 master ,<代码>最新的,如果存在(通常是版本标签)上的每个标签(通常是版本标签)。这样,无论我是对 Master 的提交还是我的pi-hole Monitor Workflow进行提交,适当的Docker映像标签将仅从单个构建运行中发布。

用例1:我将更新更新到 Master ,并更改对Dockerfile。结果应该是将新的Docker映像发布使用 Master 最新标签。应使用单个Docker映像,以便标签的SHA匹配。当前的PI孔版本标签图像应保持不变。

目前有效!我获得了一个Docker Build Run,该运行在 Master 最新下发布图像。

用例2:我的pi-hole Monitor工作流程检测到新的PI孔释放。结果应该是发布了一个新的Docker映像,上面有三个标签: Master 最新和pi-hole release warrie tag(例如 pihole-v5.10 )。应使用单个Docker映像,以便标签的SHA匹配。

这目前不起作用。这触发了两次我的工作流程。因此,两个Docker构建运行。 最新的已更新两次(首先完成)。 Master 和版本标签( pihole-v*。*)具有不同的shas。

工作流程#1:pi-hole Monitor

name: Pi-hole Monitor
on:
  schedule:
    - cron:  '0 8 * * *'
  workflow_dispatch:
jobs:
  check-pihole-version:
    runs-on: ubuntu-latest
    steps:
      # https://github.com/actions/checkout
      - name: Checkout repository
        uses: actions/checkout@v2
        # https://stackoverflow.com/questions/67550727/push-event-doesnt-trigger-workflow-on-push-paths-github-actions
        with:
          token: ${{ secrets.BUILD_AUTOMATION_TOKEN }}

      - name: Fetch latest release version of Pi-hole
        id: pi-hole_ver
        run: |
          curl -sL https://api.github.com/repos/pi-hole/pi-hole/releases/latest | \
          jq -r ".tag_name" > pihole-latest.txt
          echo ::set-output name=pihole-latest::$(cat pihole-latest.txt)

      - name: Check for modified files
        id: git-check
        run: echo ::set-output name=modified::$([ -z "`git status --porcelain`" ] && echo "false" || echo "true")

      - name: Commit latest release version
        if: steps.git-check.outputs.modified == 'true'
        run: |
          git config --global user.name 'Hossy'
          git config --global user.email '[email protected]'
          git commit -am "New Pi-hole release ${{ steps.pi-hole_ver.outputs.pihole-latest }}"
          git tag -am "Pi-hole ${{ steps.pi-hole_ver.outputs.pihole-latest }}" pihole-${{ steps.pi-hole_ver.outputs.pihole-latest }}
          git push origin pihole-${{ steps.pi-hole_ver.outputs.pihole-latest }}
          git push

工作流程#2:Docker Builder

name: Publish Docker Image

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

on:
  schedule:
    - cron: '37 8 1,15 * *'
  push:
    branches: [ master ]
    tags: [ 'pihole-**' ]
    paths-ignore: [ '.github/**' ]
  pull_request:
    branches: [ master ]
  workflow_dispatch:

env:
  # Use docker.io for Docker Hub if empty
  REGISTRY: ghcr.io
  # github.repository as <account>/<repo>
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build:

    runs-on: ubuntu-latest
    permissions:
      packages: write

    steps:
      # Login against a Docker registry except on PR
      # https://github.com/docker/login-action
      - name: Log into registry ${{ env.REGISTRY }}
        if: github.event_name != 'pull_request'
        uses: docker/[email protected]
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      # Extract metadata (tags, labels) for Docker
      # https://github.com/docker/metadata-action
      - name: Extract Docker metadata
        id: meta
        uses: docker/[email protected]
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          # set latest tag for master branch
          tags: |
            type=schedule
            type=ref,event=branch
            type=ref,event=tag
            type=ref,event=pr
            type=raw,value=latest,enable={{is_default_branch}}

      # Build and push Docker image with Buildx (don't push on PR)
      # https://github.com/docker/build-push-action
      - name: Build and push Docker image
        uses: docker/[email protected]
        with:
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

其他可能会有所帮助的事物,并且仍在修补:

I've been digging around for a while and can't quite figure out how to accomplish this.

What I have now: End-to-end, I have two workflows. One monitors for new releases of Pi-hole and the other builds a docker image when new commits happen.

Goal: Using GitHub Workflows, only when committing to the master branch, I want to build a single Docker image that is tagged with master, latest, and every tag on the commit (usually a version tag), if they exist. This way, whether I do a commit to master or my Pi-hole monitor workflow does a commit, the appropriate docker image tags will be published from only a single build run.

Use case 1: I commit an update to master with a change to Dockerfile. The result should be that a new docker image is published with both master and latest tags. A single docker image should be used so the SHAs for the tags match. The current Pi-hole version-tagged image should remain untouched.

This currently works! I get one docker build run which publishes the image under master and latest.

Use case 2: My Pi-hole monitor workflow detects a new Pi-hole release. The result should be that a new docker image is published with three tags: master, latest, and the Pi-hole release tag (e.g. pihole-v5.10). A single docker image should be used so the SHAs for the tags match.

This does not currently work. This triggers my workflow twice. So, two docker builds run. latest is updated twice (whichever finishes first). The master and version tags (pihole-v*.*) have different SHAs.

Workflow #1: Pi-hole monitor

name: Pi-hole Monitor
on:
  schedule:
    - cron:  '0 8 * * *'
  workflow_dispatch:
jobs:
  check-pihole-version:
    runs-on: ubuntu-latest
    steps:
      # https://github.com/actions/checkout
      - name: Checkout repository
        uses: actions/checkout@v2
        # https://stackoverflow.com/questions/67550727/push-event-doesnt-trigger-workflow-on-push-paths-github-actions
        with:
          token: ${{ secrets.BUILD_AUTOMATION_TOKEN }}

      - name: Fetch latest release version of Pi-hole
        id: pi-hole_ver
        run: |
          curl -sL https://api.github.com/repos/pi-hole/pi-hole/releases/latest | \
          jq -r ".tag_name" > pihole-latest.txt
          echo ::set-output name=pihole-latest::$(cat pihole-latest.txt)

      - name: Check for modified files
        id: git-check
        run: echo ::set-output name=modified::$([ -z "`git status --porcelain`" ] && echo "false" || echo "true")

      - name: Commit latest release version
        if: steps.git-check.outputs.modified == 'true'
        run: |
          git config --global user.name 'Hossy'
          git config --global user.email '[email protected]'
          git commit -am "New Pi-hole release ${{ steps.pi-hole_ver.outputs.pihole-latest }}"
          git tag -am "Pi-hole ${{ steps.pi-hole_ver.outputs.pihole-latest }}" pihole-${{ steps.pi-hole_ver.outputs.pihole-latest }}
          git push origin pihole-${{ steps.pi-hole_ver.outputs.pihole-latest }}
          git push

Workflow #2: Docker builder

name: Publish Docker Image

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

on:
  schedule:
    - cron: '37 8 1,15 * *'
  push:
    branches: [ master ]
    tags: [ 'pihole-**' ]
    paths-ignore: [ '.github/**' ]
  pull_request:
    branches: [ master ]
  workflow_dispatch:

env:
  # Use docker.io for Docker Hub if empty
  REGISTRY: ghcr.io
  # github.repository as <account>/<repo>
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build:

    runs-on: ubuntu-latest
    permissions:
      packages: write

    steps:
      # Login against a Docker registry except on PR
      # https://github.com/docker/login-action
      - name: Log into registry ${{ env.REGISTRY }}
        if: github.event_name != 'pull_request'
        uses: docker/[email protected]
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      # Extract metadata (tags, labels) for Docker
      # https://github.com/docker/metadata-action
      - name: Extract Docker metadata
        id: meta
        uses: docker/[email protected]
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          # set latest tag for master branch
          tags: |
            type=schedule
            type=ref,event=branch
            type=ref,event=tag
            type=ref,event=pr
            type=raw,value=latest,enable={{is_default_branch}}

      # Build and push Docker image with Buildx (don't push on PR)
      # https://github.com/docker/build-push-action
      - name: Build and push Docker image
        uses: docker/[email protected]
        with:
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

Other things that might help that I've looked at and are still tinkering with:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

只怪假的太真实 2025-02-15 13:12:13

在发布了这个问题之后,我继续挖掘,找到了一个解决方案。我不会声称这是一个漂亮的解决方案,但它实现了目标。

我还想补充一点,最多,GitHub API严重缺乏。但是我离题...好东西!

我最终要做的是:

  1. 使用 github api a> to get/repos/:lander/:repo/tags ,检索存储库上存在的每个标签。这是我发现唯一可以返回标签的提交sha的API呼叫。其他所有人都不断返回标签本身的对象(对我来说没用)。

示例输出(JSON数组):

[
    {
        "name": "pihole-v5.10",
        "zipball_url": "https://api.github.com/repos/Hossy/pihole/zipball/refs/tags/pihole-v5.10",
        "tarball_url": "https://api.github.com/repos/Hossy/pihole/tarball/refs/tags/pihole-v5.10",
        "commit": {
            "sha": "e696d33d0dca3df5157cbc8558cc303cec027851",
            "url": "https://api.github.com/repos/Hossy/pihole/commits/e696d33d0dca3df5157cbc8558cc303cec027851"
        },
        "node_id": "MDM6UmVmMjc4NDM1ODg3OnJlZnMvdGFncy9waWhvbGUtdjUuMTA="
    }
]
  1. jq 的JSON输出解析,并过滤到具有与工作流的Commit SHA相匹配的标签。
  2. 进行一些字符串操作以合并 docker/metadata-action 和github api( jq )的标签,以构建 docker/build-build-push-的标签超集动作

我的新Docker Builder工作流程:

name: Publish Docker Image

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

on:
  schedule:
    - cron: '37 8 1,15 * *'
  push:
    branches: [ master ]
    #tags: [ 'pihole-**' ]
    paths-ignore: [ '.github/**' ]
  pull_request:
    branches: [ master ]
  # workflow_dispatch:

env:
  # Use docker.io for Docker Hub if empty
  REGISTRY: ghcr.io
  # github.repository as <account>/<repo>
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build:

    runs-on: ubuntu-latest
    permissions:
      # contents: read
      packages: write

    steps:
      # Login against a Docker registry except on PR
      # https://github.com/docker/login-action
      - name: Log into registry ${{ env.REGISTRY }}
        if: github.event_name != 'pull_request'
        uses: docker/[email protected]
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      # Extract metadata (tags, labels) for Docker
      # https://github.com/docker/metadata-action
      - name: Extract Docker metadata
        id: meta
        uses: docker/[email protected]
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          # set latest tag for master branch
          tags: |
            type=schedule
            type=ref,event=branch
            type=ref,event=tag
            type=ref,event=pr
            type=raw,value=latest,enable={{is_default_branch}}

      # Retrieve all repository tags from the GitHub API using undocumented API call to get all tags
      # https://github.com/actions/github-script
      - name: Get all tags
        id: all-tags
        uses: actions/github-script@v6
        with:
          script: |
            const path = "/repos/" + "${{ github.repository }}" + "/tags"
            const parameters = "{'" + "${{ github.repository_owner }}" + "', '" + "${{ github.repository }}" + "'}"
            return github.rest.git.getTag(path,parameters)
      
      # Prepare JSON output for Unix command line
      # https://github.com/mad9000/actions-find-and-replace-string
      - name: Format jq result
        id: formatted-jq
        uses: mad9000/actions-find-and-replace-string@2
        with:
          source: ${{ steps.all-tags.outputs.result }}
          find: "'"
          replace: "\\\'"

      # Parse Github API output and search for tags only matching the current commit SHA 
      - name: Search all tags for commit
        id: tag-results
        run: echo ::set-output name=tags::"$( echo '${{ steps.formatted-jq.outputs.value }}' | jq -r ".data | .[] | select( .commit.sha == \"${{ github.sha }}\" ) | .name" )"
      
      # Merge the tag lists from docker/metadata-action and GitHub API
      - name: Build tag list
        id: tag-list
        run: |
          echo ::set-output name=tags::"$(
            echo -n "${{ steps.meta.outputs.tags }}" | tr '\n' ','
            for r in `echo "${{ steps.tag-results.outputs.tags }}" | tr '\n' ' '`; do echo -n ,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$r | tr '[:upper:]' '[:lower:]'; done
          )"

      # Build and push Docker image with Buildx (don't push on PR)
      # https://github.com/docker/build-push-action
      - name: Build and push Docker image
        uses: docker/[email protected]
        with:
          # context: .
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.tag-list.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

After posting this question, I continued to dig and I found a solution. I'm not going to claim it's a pretty solution, but it accomplishes the goal.

I'd also like to add that, at the very most, the GitHub API is severely lacking. But I digress... to the good stuff!

What I ended up doing is:

  1. Using a GitHub API call to GET /repos/:owner/:repo/tags, retrieve every tag that exists on the repository. This is the only API call I found that would return the commit SHA of the tag. All the others kept returning the object SHA of the tag itself (useless to me).

Example output (JSON array):

[
    {
        "name": "pihole-v5.10",
        "zipball_url": "https://api.github.com/repos/Hossy/pihole/zipball/refs/tags/pihole-v5.10",
        "tarball_url": "https://api.github.com/repos/Hossy/pihole/tarball/refs/tags/pihole-v5.10",
        "commit": {
            "sha": "e696d33d0dca3df5157cbc8558cc303cec027851",
            "url": "https://api.github.com/repos/Hossy/pihole/commits/e696d33d0dca3df5157cbc8558cc303cec027851"
        },
        "node_id": "MDM6UmVmMjc4NDM1ODg3OnJlZnMvdGFncy9waWhvbGUtdjUuMTA="
    }
]
  1. Parse the JSON output with jq and filter to the tag that has a commit SHA that matches the workflow's commit SHA.
  2. Do some string manipulation to merge the tags from docker/metadata-action and GitHub API (jq) to build a superset of tags for docker/build-push-action.

My new docker builder workflow:

name: Publish Docker Image

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

on:
  schedule:
    - cron: '37 8 1,15 * *'
  push:
    branches: [ master ]
    #tags: [ 'pihole-**' ]
    paths-ignore: [ '.github/**' ]
  pull_request:
    branches: [ master ]
  # workflow_dispatch:

env:
  # Use docker.io for Docker Hub if empty
  REGISTRY: ghcr.io
  # github.repository as <account>/<repo>
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build:

    runs-on: ubuntu-latest
    permissions:
      # contents: read
      packages: write

    steps:
      # Login against a Docker registry except on PR
      # https://github.com/docker/login-action
      - name: Log into registry ${{ env.REGISTRY }}
        if: github.event_name != 'pull_request'
        uses: docker/[email protected]
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      # Extract metadata (tags, labels) for Docker
      # https://github.com/docker/metadata-action
      - name: Extract Docker metadata
        id: meta
        uses: docker/[email protected]
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          # set latest tag for master branch
          tags: |
            type=schedule
            type=ref,event=branch
            type=ref,event=tag
            type=ref,event=pr
            type=raw,value=latest,enable={{is_default_branch}}

      # Retrieve all repository tags from the GitHub API using undocumented API call to get all tags
      # https://github.com/actions/github-script
      - name: Get all tags
        id: all-tags
        uses: actions/github-script@v6
        with:
          script: |
            const path = "/repos/" + "${{ github.repository }}" + "/tags"
            const parameters = "{'" + "${{ github.repository_owner }}" + "', '" + "${{ github.repository }}" + "'}"
            return github.rest.git.getTag(path,parameters)
      
      # Prepare JSON output for Unix command line
      # https://github.com/mad9000/actions-find-and-replace-string
      - name: Format jq result
        id: formatted-jq
        uses: mad9000/actions-find-and-replace-string@2
        with:
          source: ${{ steps.all-tags.outputs.result }}
          find: "'"
          replace: "\\\'"

      # Parse Github API output and search for tags only matching the current commit SHA 
      - name: Search all tags for commit
        id: tag-results
        run: echo ::set-output name=tags::"$( echo '${{ steps.formatted-jq.outputs.value }}' | jq -r ".data | .[] | select( .commit.sha == \"${{ github.sha }}\" ) | .name" )"
      
      # Merge the tag lists from docker/metadata-action and GitHub API
      - name: Build tag list
        id: tag-list
        run: |
          echo ::set-output name=tags::"$(
            echo -n "${{ steps.meta.outputs.tags }}" | tr '\n' ','
            for r in `echo "${{ steps.tag-results.outputs.tags }}" | tr '\n' ' '`; do echo -n ,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$r | tr '[:upper:]' '[:lower:]'; done
          )"

      # Build and push Docker image with Buildx (don't push on PR)
      # https://github.com/docker/build-push-action
      - name: Build and push Docker image
        uses: docker/[email protected]
        with:
          # context: .
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.tag-list.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文