# Harness CI Keeper Plugin - Release Workflow # # HOW TO PUBLISH A NEW RELEASE: # 1. Update the version in package.json (e.g., from 1.0.0 to 1.0.1) # 2. Commit your changes: git commit -am "Bump version to 1.0.1" # 3. Create a git tag matching the version: git tag v1.0.1 # 4. Push the tag to GitHub: git push origin v1.0.1 # 5. The workflow will automatically: # - Run linting # - Run tests # - Build the Docker image # - Generate SBOM # - Create a GitHub release # # Note: This workflow triggers on version tags (v*.*.*) or manual workflow dispatch name: Publish Harness CI Keeper Plugin on: workflow_dispatch: push: tags: - 'v*.*.*' # Triggers on any version tag (v1.0.0, v1.0.1, v2.0.0, etc.) — no manual update per release jobs: test: runs-on: ubuntu-latest strategy: matrix: node-version: [20.x] steps: - name: Checkout code uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: 'npm' - name: Install dependencies run: npm ci - name: Run linting run: npm run lint - name: Run tests run: npm run test build: runs-on: ubuntu-latest needs: [test] steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Get version id: get_version run: | VERSION=$(node -p "require('./package.json').version") echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT echo "Version: ${VERSION}" - name: Check for Docker Hub credentials id: docker_creds env: DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} run: | if [ -n "${DOCKERHUB_USERNAME}" ]; then echo "HAS_CREDENTIALS=true" >> $GITHUB_OUTPUT else echo "HAS_CREDENTIALS=false" >> $GITHUB_OUTPUT fi - name: Log in to Docker Hub (if credentials provided) if: steps.docker_creds.outputs.HAS_CREDENTIALS == 'true' uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Set Docker image tags id: docker_tags env: DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} run: | if [ -n "${DOCKERHUB_USERNAME}" ]; then IMAGE_TAG="${DOCKERHUB_USERNAME}/harness-plugin:${{ steps.get_version.outputs.version }}" LATEST_TAG="${DOCKERHUB_USERNAME}/harness-plugin:latest" else IMAGE_TAG="harness-plugin:${{ steps.get_version.outputs.version }}" LATEST_TAG="harness-plugin:latest" fi echo "IMAGE_TAG=${IMAGE_TAG}" >> $GITHUB_OUTPUT echo "LATEST_TAG=${LATEST_TAG}" >> $GITHUB_OUTPUT echo "Image tag: ${IMAGE_TAG}" echo "Latest tag: ${LATEST_TAG}" - name: Build Docker image (multi-platform) uses: docker/build-push-action@v5 with: context: . platforms: linux/amd64,linux/arm64 push: ${{ github.event_name != 'workflow_dispatch' && startsWith(github.ref, 'refs/tags/') }} tags: | ${{ steps.docker_tags.outputs.IMAGE_TAG }} ${{ steps.docker_tags.outputs.LATEST_TAG }} cache-from: type=gha cache-to: type=gha,mode=max - name: Upload build artifacts uses: actions/upload-artifact@v4 with: name: harness-plugin-build path: | Dockerfile package.json retention-days: 30 generate-sbom: runs-on: ubuntu-latest needs: build steps: - name: Get the source code uses: actions/checkout@v4 - name: Install Syft run: | echo "Installing Syft v1.18.1..." curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /tmp/bin v1.18.1 echo "/tmp/bin" >> $GITHUB_PATH - name: Install Manifest CLI run: | echo "Installing Manifest CLI v0.18.3..." curl -sSfL https://raw.githubusercontent.com/manifest-cyber/cli/main/install.sh | sh -s -- -b /tmp/bin v0.18.3 - name: Create Syft configuration run: | cat > syft-config.yaml << 'EOF' package: search: scope: all-layers cataloger: enabled: true java: enabled: false python: enabled: false nodejs: enabled: true EOF - name: Generate and upload SBOM env: MANIFEST_API_KEY: ${{ secrets.MANIFEST_TOKEN }} run: | # Get version from package.json echo "Detecting Harness CI Keeper Plugin version..." if [ -f "package.json" ]; then VERSION=$(grep -o '"version": "[^"]*"' "package.json" | cut -d'"' -f4) echo "Detected version: ${VERSION}" else VERSION="1.0.0" echo "Could not detect version, using default: ${VERSION}" fi echo "Generating SBOM with Manifest CLI..." /tmp/bin/manifest sbom "." \ --generator=syft \ --name=harness-plugin \ --version=${VERSION} \ --output=spdx-json \ --file=harness-plugin-sbom.json \ --api-key=${MANIFEST_API_KEY} \ --publish=true \ --asset-label=application,sbom-generated,nodejs,harness-plugin,docker \ --generator-config=syft-config.yaml echo "SBOM generated and uploaded successfully: harness-plugin-sbom.json" echo "---------- SBOM Preview (first 20 lines) ----------" head -n 20 harness-plugin-sbom.json # Docker registry publish job - reserved for future use # publish-docker-registry: # runs-on: ubuntu-latest # environment: prod # needs: [test, build, generate-sbom] # # steps: # - name: Checkout code # uses: actions/checkout@v4 # # - name: Set up Docker Buildx # uses: docker/setup-buildx-action@v3 # # - name: Get version # id: get_version # run: | # VERSION=$(node -p "require('./package.json').version") # echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT # # - name: Log in to Docker Registry # uses: docker/login-action@v3 # with: # registry: ${{ secrets.DOCKER_REGISTRY }} # username: ${{ secrets.DOCKER_USERNAME }} # password: ${{ secrets.DOCKER_PASSWORD }} # # - name: Build and push Docker image # uses: docker/build-push-action@v5 # with: # context: . # push: true # tags: | # ${{ secrets.DOCKER_REGISTRY }}/harness-plugin:${{ steps.get_version.outputs.version }} # ${{ secrets.DOCKER_REGISTRY }}/harness-plugin:latest create-release: runs-on: ubuntu-latest needs: [test, build, generate-sbom] # Only run when triggered by a tag push if: startsWith(github.ref, 'refs/tags/') steps: - name: Checkout code uses: actions/checkout@v4 - name: Use Node.js uses: actions/setup-node@v4 with: node-version: '20.x' - name: Get version id: get_version run: | VERSION=$(node -p "require('./package.json').version") echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT echo "Version: ${VERSION}" - name: Set Docker image name for release id: docker_image env: DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} run: | if [ -n "${DOCKERHUB_USERNAME}" ]; then IMAGE_NAME="${DOCKERHUB_USERNAME}/harness-plugin:${{ steps.get_version.outputs.version }}" else IMAGE_NAME="harness-plugin:${{ steps.get_version.outputs.version }}" fi echo "IMAGE_NAME=${IMAGE_NAME}" >> $GITHUB_OUTPUT - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ github.ref_name }} name: Release ${{ github.ref_name }} body: | ## Harness CI Keeper Plugin ${{ github.ref_name }} ### Installation #### Docker Image: The Docker image for this release is available at: ``` ${{ steps.docker_image.outputs.IMAGE_NAME }} ``` #### Usage in Harness CI: ```yaml - step: type: Plugin name: Fetch_Keeper_Secrets identifier: Fetch_Keeper_Secrets spec: image: ${{ steps.docker_image.outputs.IMAGE_NAME }} settings: ksm_config: <+secrets.getValue("Keeper_Config_Secret")> secrets: | VeYTRo-PHElAwfQT6f0TIA/field/password > DB_PASSWORD VeYTRo-PHElAwfQT6f0TIA/field/login > DB_USERNAME ``` ### What's Changed See the [full changelog](https://github.com/${{ github.repository }}/compare/previous-tag...${{ github.ref_name }}) draft: false prerelease: false env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}