1

I'm trying to build docker image using github actions and it's triggered if a tagged commit happens and if a push or pull request on staging & main branches. I'm using also kustomize to customize the legacy manifest depending on the commit. But i have an issue every time i tried to tag a commit to trigger the pipeline, it fails at the part of committing the kustomize.yaml with this error

Run ad-m/github-push-action@master
Push to branch refs/tags/v0.3.8
To https://github.com/ahmedappout08/robo-demo.git
 ! [rejected]        HEAD -> v0.3.8 (already exists)
error: failed to push some refs to 'https://github.com/ahmedappout08/robo-demo.git'
hint: Updates were rejected because the tag already exists in the remote.
Error: Invalid exit code: 1
    at ChildProcess.<anonymous> (/home/runner/work/_actions/ad-m/github-push-action/master/start.js:29:21)
    at ChildProcess.emit (events.js:210:5)
    at maybeClose (internal/child_process.js:1021:16)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:283:5) {
  code: 1
}
Error: Invalid exit code: 1
    at ChildProcess.<anonymous> (/home/runner/work/_actions/ad-m/github-push-action/master/start.js:29:21)
    at ChildProcess.emit (events.js:210:5)
    at maybeClose (internal/child_process.js:1021:16)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:283:5)

And here's the Ci.yaml file:

name: Docker

on:
  
  push:
    branches:
      - main
      - staging
    tags:
      - v*
  pull_request:
    branches:
      - main
      - staging

env:
  # TODO: Change variable to your image's name.
  IMAGE_NAME: robo-demo 
jobs:
  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push:
    # Ensure test job passes before pushing image.

    runs-on: ubuntu-latest


    steps:
      - name: Checkout master
        uses: actions/checkout@main

      

      - name: Build image
        run: docker build . --file Dockerfile --tag $IMAGE_NAME

      - name: Log into registry
        run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login docker.pkg.github.com -u ${{ github.actor }} --password-stdin
      
      - name: Push image tag
        if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging' }} == false
        run: |
          IMAGE_ID=docker.pkg.github.com/${{ github.repository }}/$IMAGE_NAME
          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
          # Strip git ref prefix from version
          #VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
          VERSION=$GITHUB_SHA
          # Strip "v" prefix from tag name
          [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
          # Use Docker `latest` tag convention
          echo IMAGE_ID=$IMAGE_ID
          #echo VERSION=${GITHUB_REF##*/}
          echo VERSION=$GITHUB_SHA
          docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
          docker push $IMAGE_ID:$VERSION
      - name: push image main & staging
        if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging' }}
        run: |
          IMAGE_ID=docker.pkg.github.com/${{ github.repository }}/$IMAGE_NAME
          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
          # Strip "v" prefix from tag name
          [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
          # Use Docker `latest` tag convention
          echo IMAGE_ID=$IMAGE_ID
          echo VERSION=${GITHUB_REF##*/}
          docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
          docker push $IMAGE_ID:$VERSION

      - name: congrats
        run: |
          echo "Image Built on Branch" ${GITHUB_REF##*/}
      - name: Setup Kustomize
        if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging' }} == false
        uses: imranismail/setup-kustomize@v1
        with:
          kustomize-version: "3.6.1"
      - name: Update Kubernetes resources
        if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging' }} == false
        run: |
          cd k8s-deployment/feature-version
          kustomize edit set image robo-image=docker.pkg.github.com/${{ github.repository }}/$IMAGE_NAME:$GITHUB_SHA
          cat kustomization.yaml
      - name: Commit files
        if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging' }} == false
        run: |
          git config --local user.email "action@github.com"
          git config --local user.name "GitHub Action" 
          git commit -am "Bump docker tag"
      - name: Push changes
        if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging' }} == false
        uses: ad-m/github-push-action@master
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          branch: ${{ github.ref }} 

I don't how to fix that to push the commit to the branch itself connected to the tag as i need to update the kustomize.yaml there after each building

1 Answers1

0

I don't how to fix that to push the commit to the branch itself connected to the tag as i need to update the kustomize.yaml there after each building

As far as Git itself is concerned, there is no connection between a branch name and a tag name.

At the Git level, any name—any reference—is simply a name that stores a hash ID. Branch names in particular are constrained to store only commit hash IDs, while tag names can store the hash ID of any internal Git object. A tag is said to be a lightweight tag if it stores a commit hash ID, or an annotated tag if it stores the hash ID of a tag object. This tag object then typically stores the hash ID of some commit.

You can use git branch --points-at to find branch names that select some particular commit, and git tag --points-at to find tag names that select some particular commit. For details, see the git branch and git tag documentation.

Note that you can give git tag the commit hash ID here, and it still finds annotated tags. Technically, it finds the annotated tag regardless of whether you name the tag object itself, or its target commit:

$ git rev-parse v2.3.0
42de6ed0c4c5c2a184b25ffeb4936af8226ccad1
$ git rev-parse v2.3.0^{commit}
9874fca7122563e28d699a911404fc49d2a24f1c
$ git tag --points-at 42de6ed0c4c5c2a184b25ffeb4936af8226ccad1
v2.3.0
$ git tag --points-at 9874fca7122563e28d699a911404fc49d2a24f1c
v2.3.0

But if you're trying to find which branch names—there may be anywhere from none to many—identify some particular commit that you find by a tag, you'll definitely need to resolve the tag name to a commit hash ID first, before running git branch --points-at.

Regardless of all of that, your overall plan seems rather ill-founded to me. Remember that the purpose of a tag name is to identify one specific commit for all time. A raw hash ID will do that too, but the tag name provides two important features that the raw hash ID doesn't:

  • It is at least potentially human-readable, and can have semantics, such as a semver part.

  • It gives you the ability to sign the commit without actually signing each commit. That is, you can provide a GPG or other digital signature for the tagged commit, without having to use GPG or other digital signatures on every commit (which is in most cases more harmful than useful: signing just the tags, while in some sense less secure, is far more usable, and a key to getting effective security is to balance the pain level with the getting-work-done level, so that people actually use it).

Meanwhile, the purpose of a branch name is to allow something—humans, computers, or sometimes both—to find some particular but changeable commit. So we assign a branch name to the tip commit of some chain of commits, to say this is our best commit so far. Then, as we improve things, we add new commits to the chain, and move the branch name.

What this all means for a formal release process is that you would not tag a release candidate unless it's going to a wider audience. You would mark this release candidate with a branch name. You would then build it and test it, and if it passes internal testing, you might then tag it as a release candidate, perhaps after updating some sort of build customization.

In other words, you would never customize a tagged version. You always customize from a branch—perhaps a particular branch pattern, but a branch. Then you might tag the customized version, provided it's ready for candidacy. If it's sufficiently good, it gets authorized as a release or "wide RC" (something that goes outside the local organization) that is signed and verified (so that those outside the organization can see that it is trusted, and by whom). And of course, whoever adds a signature should make sure that the trust chain—the verification made at each step—is valid and unbroken.

torek
  • 448,244
  • 59
  • 642
  • 775