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

Draft: Make Wrapper validator self executable and GitLab CI ready #50

Draft
wants to merge 28 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1bf572e
adding dockerfile
RAkasheh Oct 13, 2021
80c2095
edited Dockerfile
RAkasheh Oct 13, 2021
1da789c
Update Dockerfile
RAkasheh Oct 13, 2021
11a69d5
Make Wrapper validator executable and GitLab CI ready
Oct 13, 2021
db78afa
Using action.yml as definition for the program parameters
Oct 14, 2021
9199393
removing redundant type specifier
Oct 14, 2021
701d3cc
refinements and preparing test setup
Oct 14, 2021
860cd41
Merge remote-tracking branch 'aepfli/feature/gitlab-ci-compatibility'
RAkasheh Oct 14, 2021
0a71729
Merge branch 'master' of gitlab.com:netconomy/personal/r.akasheh/grad…
RAkasheh Oct 14, 2021
bd9a29d
Update WrapperValidation.gitlab-ci.yml
RAkasheh Oct 14, 2021
3ccbb71
Make it nice executable
Oct 14, 2021
9e67ca1
Removing node_env
Oct 14, 2021
841abf7
fixing build
Oct 14, 2021
1d5211f
trying out action yml path
RAkasheh Oct 14, 2021
1e99869
Update main.ts
RAkasheh Oct 14, 2021
ac7d358
Update main.ts
RAkasheh Oct 14, 2021
32ecb1b
Update main.ts
RAkasheh Oct 14, 2021
3c1acdf
Update main.ts
RAkasheh Oct 14, 2021
584dbed
Update main.ts
RAkasheh Oct 14, 2021
679d29d
testing cd __tests
RAkasheh Oct 14, 2021
50ff280
trying to add githubaction
Oct 14, 2021
7f998fa
Merge pull request #1 from aepfli/feature/gitlab-ci-compatibility
aepfli Oct 14, 2021
56586fb
adding gitlab-ci file
Oct 14, 2021
03df991
Further Testing
Oct 14, 2021
d44ce28
CI
Oct 14, 2021
1b1b81d
trying to get tests running
Oct 14, 2021
6cef04d
another try
Oct 14, 2021
520cf8a
Delete .gitlab-ci.yml
aepfli Oct 14, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
__tests__
.github
.gitlab-ci-local
49 changes: 49 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ on: # rebuild any PRs and main branch changes
- master
- 'releases/*'

env:
IMAGE_NAME: wrapper-validation

jobs:
build: # make sure build/ci work properly
runs-on: ubuntu-latest
Expand All @@ -22,3 +25,49 @@ jobs:
with:
# to allow the invalid wrapper jar present in test data
allow-checksums: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

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

steps:
- uses: actions/checkout@v2

- name: Build image
run: docker build . --file Dockerfile --tag $IMAGE_NAME --label "runnumber=${GITHUB_RUN_ID}"

- name: Setting up GitLab CI
run: |
npm install -g gitlab-ci-local
mkdir -p .gitlab-ci-local
echo "global:" > .gitlab-ci-local/variables.yml
echo " IMAGE_NAME: $IMAGE_NAME" >> .gitlab-ci-local/variables.yml

- name: Testing GitLab CI
run: |
cat .gitlab-ci-local/variables.yml
gitlab-ci-local --home ./ --file __tests__/.gitlab-ci.yml

- name: Log in to registry
# This is where you will update the PAT to GITHUB_TOKEN
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
if: github.event_name != 'pull_request'
- name: Push image
run: |
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$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
[ "$VERSION" == "master" ] && VERSION=latest
echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION
docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
docker push $IMAGE_ID:$VERSION
if: github.event_name != 'pull_request'
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM node:12-slim

WORKDIR /app

COPY . .

RUN npm install && npm run-script build && npm install -g

ENTRYPOINT [ "wrapper-validation" ]
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,11 @@ Regardless of what you find, we still kindly request that you reach out to us an

To learn more about verifying the Gradle Wrapper JAR locally, see our
[guide on the topic](https://docs.gradle.org/current/userguide/gradle_wrapper.html#wrapper_checksum_verification).


## Usage in GitLab CI

```yaml
include:
- remote: https://raw.githubusercontent.com/gradle/wrapper-validation-action/master/WrapperValidation.gitlab-ci.yml
```
7 changes: 7 additions & 0 deletions WrapperValidation.gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
validate-wrapper:
stage: .pre
image:
name: ghcr.io/aepfli/wrapper-validation:latest

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we change this to ghcr.io/gradle if we use ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME in the publish job?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes we can, this is currently just for evaluation, that it works, and to show the greater picture - the question is, what kind of hosting for the docker image we will be using.

  • ghcr
  • docker hub
  • gitlab registry (with an automatically updated fork of this project)

There are multiple possible solutions, and i am open to any of those ;)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think any of us have enough experience with GitLab to make any sort of evaluation as to the value of picking one vs the other. I think that a clear list of pros-and cons would be useful. I'd defer to your suggestion here most likely.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comparison of Registries for the docker image

Options:

  • Docker Hub
  • GitHub Docker Registry
  • GitLab Docker Registry

Docker Hub

Pros:

  • easiest accessible registry - image name would be just gradle/wrapper-validation
  • account does already exist
  • easy do apply to all kind of docker based CI systems

Cons:

  • secrets need to be added to GitHub for pushing*
  • pricing - i have no clue about the impact regarding this
  • as far as i understood, there is already a teamcity server in place, which pushes the other docker images, but gradle wrapper validation is using GitHub Actions, so we need to somehow provide this credentials.

GitHub Docker Registry

Pros:

  • easily included in the GitHub Action
  • Registry is already existing, as it is coupled to the repository
  • as long as it is public the registry is free:

    GitHub Packages usage is free for public packages. For private packages, each account on GitHub.com receives a certain amount of free storage and data transfer, depending on the product used with the account. Any usage beyond the included amounts is controlled by spending limits. - https://docs.github.com/en/billing/managing-billing-for-github-packages/about-billing-for-github-packages

Cons:

  • image name for includes will not be as short as intended
  • not as easy to find, people will search docker hub for such images

GitLab Docker Registry

Pros:

  • Registry is easily included into GitLab Actions
  • Due to the Fork (see cons) the include statement will be much clearer for gitlab ci
     include:
     	- remote: https://raw.githubusercontent.com/gradle/wrapper-validation-action/master/WrapperValidation.gitlab-ci.yml
    turns into
     include:
     	- project: <Project Path eg. gradle/wrapper-validation - depends on availability of names>
     	  file: WrapperValidation.gitlab-ci.yml
  • docker image creation could be also done via GitLab Registry
  • as longas it is public, registry is free

Cons:

  • Fork needs to be created on GitLab.com side (i can maintain and create it) - i would recommend a fork which is autmatically updating itself.
  • Additional indirection with GitLab
  • image name for includes will not be as short as intended
  • not as easy to find, people will search docker hub for such images

Recommendation

There are two scenarios, which i can recommend for now, which actually could also be applied in parallel

  1. i would go with GitHub Registry - it is easy to apply and as a first step a good evaluation. We will see adaption etc.

  2. i would also prepare a GitLab CI file to push it to a gitlab registry, I can create a group and a fork, which automatically updates from github (so source of truth will still be GitHub) - this would allow users to use the easier and better readable approach for includes.

I will prepare 1. during the christmas holidays, and i will also update the readme. - we can then decide how to proceed in the new year.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I agree with your recommendation to go with the GitHub Registry. Thank you for writing up this thorough assessment, much appreciated.

entrypoint: [""]
script:
- wrapper-validation
51 changes: 51 additions & 0 deletions __tests__/.gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@


include:
- local: WrapperValidation.gitlab-ci.yml

.false-test:
script:
- wrapper-validation && false || true

job:
stage: .pre
script:
- echo "IMAGE $IMAGE_NAME"

validate-wrapper:
image:
name: $IMAGE_NAME
entrypoint: [""]
stage: test
before_script:
- cd __tests__/data/valid

validate-wrapper-numbers:
extends:
- validate-wrapper
variables:
MIN_WRAPPER_COUNT: 1

.validate-wrapper-invalid:
extends:
- validate-wrapper
before_script:
- cd __tests__/data/invalid

validate-wrapper-invalid-with-checksum:
extends:
- .validate-wrapper-invalid
variables:
ALLOW_CHECKSUMS: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

validate-wrapper-invalid-failing:
extends:
- .validate-wrapper-invalid
- .false-test

validate-wrapper-invalid-numbers-exceeded:
extends:
- .validate-wrapper-invalid
- .false-test
variables:
MIN_WRAPPER_COUNT: 3
17 changes: 14 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 9 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"private": true,
"description": "Gradle Wrapper Validation Action",
"main": "lib/main.js",
"bin": {
"wrapper-validation": "lib/main.js"
},
"scripts": {
"build": "tsc",
"format": "prettier --write **/*.ts",
Expand All @@ -26,22 +29,24 @@
"license": "MIT",
"dependencies": {
"@actions/core": "1.4.0",
"commander": "^8.2.0",
"typed-rest-client": "1.8.4",
"unhomoglyph": "1.0.6"
},
"devDependencies": {
"@types/node": "12.20.16",
"@types/js-yaml": "^4.0.3",
"@types/node": "^12.20.33",
"@typescript-eslint/parser": "4.28.4",
"@vercel/ncc": "0.29.0",
"eslint": "7.31.0",
"eslint-plugin-github": "4.1.5",
"eslint-plugin-jest": "24.4.0",
"glob-parent": ">=5.1.2",
"jest": "27.0.6",
"js-yaml": "4.1.0",
"js-yaml": "^4.1.0",
"nock": "13.1.1",
"prettier": "2.3.2",
"ts-jest": "27.0.4",
"typescript": "4.0.8",
"glob-parent": ">=5.1.2"
"typescript": "4.0.8"
}
}
71 changes: 60 additions & 11 deletions src/main.ts
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,25 +1,74 @@
import * as path from 'path'
import * as core from '@actions/core'
#!/usr/bin/env node

import * as validate from './validate'
import { resolve, dirname } from 'path'
import { promises as fs } from 'fs'
import { setFailed, getInput, info } from '@actions/core'

import { findInvalidWrapperJars } from './validate'
import { Command, Option } from 'commander'
import jsyaml from 'js-yaml'

interface Action {
name: string;
description: string;
author: string;
inputs: Map<string, Input>;
}

interface Input {
description: string;
required?: boolean;
default?: string;
}

export async function run(): Promise<void> {
try {
const result = await validate.findInvalidWrapperJars(
path.resolve('.'),
+core.getInput('min-wrapper-count'),
core.getInput('allow-snapshots') === 'true',
core.getInput('allow-checksums').split(',')
let minWrapperCount: number
let allowSnapshots: string
let allowChecksums: string

if (process.env.GITHUB_ACTION) {
minWrapperCount = +getInput('min-wrapper-count')
allowSnapshots = getInput('allow-snapshots')
allowChecksums = getInput('allow-checksums')

} else {
const program = new Command()
const actionYaml = jsyaml.load(await fs.readFile(dirname(require.main?.filename ??'') + '/../action.yml', 'utf8')) as Action

program
.description(actionYaml.description)

Object.entries(actionYaml.inputs).forEach(([key, value]) => {
program.addOption(
new Option(`--${key} <value>`, value.description)
.default(value.default)
.env(key.toLocaleUpperCase().replace(/-/g, '_')))
})

program.parse(process.argv)
const options = program.opts()
minWrapperCount = +options.minWrapperCount
allowSnapshots = options.allowSnapshots
allowChecksums = options.allowChecksums
}

const result = await findInvalidWrapperJars(
resolve('.'),
minWrapperCount,
allowSnapshots === 'true',
allowChecksums.split(',')
)
if (result.isValid()) {
core.info(result.toDisplayString())
info(result.toDisplayString())
} else {
core.setFailed(
setFailed(
`Gradle Wrapper Validation Failed!\n See https://github.com/gradle/wrapper-validation-action#reporting-failures\n${result.toDisplayString()}`
)
}
} catch (error) {
core.setFailed(error.message)
if (error instanceof Error)
setFailed(error.message)
}
}

Expand Down