Browse Source

tools: remove obsolete test tooling + add CI badge (#3555)

* tools: remove obsolete test tooling
- tests should now be performed from https://github.com/awesome-selfhosted/awesome-selfhosted-data#maintenance
- ref. https://github.com/awesome-selfhosted/awesome-selfhosted/issues/1038
- ref. https://github.com/awesome-selfhosted/awesome-selfhosted/issues/1852
- ref. https://github.com/awesome-selfhosted/awesome-selfhosted/issues/2266
* add a badge pointing to the main issue about unmaintained projects/dead links removal
- ref. https://github.com/awesome-selfhosted/awesome-selfhosted/issues/2266
pull/3556/head
nodiscc 1 year ago
committed by GitHub
parent
commit
794490c2bc
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .github/CONTRIBUTING.md
  2. 20
      .travis.yml
  3. 47
      Makefile
  4. 2
      README.md
  5. 39
      tests/Dangerfile
  6. 60
      tests/check-github-commit-dates.py
  7. 251
      tests/test.js

1
.github/CONTRIBUTING.md

@ -8,7 +8,6 @@ Other recommendations:
- To add a new entry, [edit the README.md file](https://github.com/awesome-selfhosted/awesome-selfhosted/edit/master/README.md) through Github's web interface or a text editor, and send a Pull Request.
- See [Editing files in another user's repository](https://help.github.com/articles/editing-files-in-another-user-s-repository/), [Creating Pull Requests](https://help.github.com/articles/creating-a-pull-request/), [Using Pull Requests](https://help.github.com/articles/using-pull-requests/) for help on sending your patch.
- A script to help you format new entries is available at (it requires `make` to be installed): `git clone`/[download](https://github.com/awesome-selfhosted/awesome-selfhosted/archive/master.zip) and enter the repository, run `make add` and follow the instructions.
- A website to help you format new entries is available at https://n8225.github.io/
- The list of contributors can be updated with `make contrib`.
- Software with no development activity for 6-12 months may be removed from the list.

20
.travis.yml

@ -1,20 +0,0 @@
language: node_js
node_js:
- "node"
cache:
npm: false
before_install:
- rvm install 2.6.2
- gem install awesome_bot
- sudo apt update && sudo apt install python3-pip python3-setuptools
- cd tests && npm install chalk && cd ..
script:
- 'if [[ "$TRAVIS_BRANCH" == "master" && "$TRAVIS_EVENT_TYPE" == "cron" ]]; then make check_all; fi'
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then make check_pr; fi'
notifications:
email: false

47
Makefile

@ -1,52 +1,5 @@
#!/usr/bin/make -f
SHELL = /bin/bash
AWESOME_BOT_OPTIONS = --allow-redirect --request-delay 1 --skip-save-results --allow 202 --white-list flaskbb.org,nitter.net,airsonic.github.io/docs/apps
all: check_all
# run all checks
check_all: check_syntax_full awesome_bot check_github_commit_dates
# check pull requests
check_pr: check_syntax_diff
# check syntax in whole file
check_syntax_full:
node tests/test.js -r README.md
# check syntax in the diff from master to current branch
check_syntax_diff:
git diff origin/master -U0 README.md | grep --perl-regexp --only-matching "(?<=^\+).*" >> temp.md && \
node tests/test.js -r README.md -d temp.md && \
awesome_bot -f temp.md $(AWESOME_BOT_OPTIONS)
# check dead links
# requiements: sudo apt install ruby && gem install --user-install awesome_bot
awesome_bot:
~/.local/share/gem/ruby/2.7.0/bin/awesome_bot -f README.md $(AWESOME_BOT_OPTIONS)
# check date of last commit for github.com repository URLs
check_github_commit_dates:
pip3 install PyGithub
python3 tests/check-github-commit-dates.py
#################################
# update the AUTHORS.md file
contrib:
@mv .github/.mailmap . && printf "|Commits | Author |\n| :---: | --- |\n" > AUTHORS.md && git shortlog -sne | sed -r 's/^\s*([[:digit:]]*?)\s*?(.*?)/|\1|\2|/' >> AUTHORS.md && mv .mailmap .github/.mailmap
# add a new entry
add:
@read -r -p "Software name: " Name && [[ ! -z "$$Name" ]] && \
read -r -p "Homepage/URL: " Url && [[ ! -z "$$Url" ]] && \
read -r -p "Description (max 250 characters, ending with .): " Description && [[ ! -z "$$Description" ]] && \
read -r -p "License: " License && [[ ! -z "$$License" ]] && \
read -r -p "Main server-side language/platform/requirement: " Language && [[ ! -z "$$Language" ]] && \
read -r -p "Demo URL (optional,leave empty): " Demo && \
if [[ "$$Demo" == "" ]]; then CDemo=""; else CDemo="[Demo]($$Demo)"; fi; \
read -r -p "Source code URL (if different from homepage): " Source && \
if [[ "$$Source" == "" ]]; then CSource=""; else CSource="[Source Code]($$Source)"; fi; \
if [[ "$$CSource" == "" && "$$Demo" == "" ]]; then Moreinfo=""; else Moreinfo="($$CDemo $$CSource)"; fi; \
echo "Copy this entry to your clipboard, paste it in the appropriate category:" ;\
echo "- [$$Name]($$Url) - $${Description} $${Moreinfo} \`$$License\` \`$$Language\`"

2
README.md

@ -1,6 +1,6 @@
# Awesome-Selfhosted
[![Awesome](https://cdn.jsdelivr.net/gh/sindresorhus/awesome@d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/sindresorhus/awesome)
[![Awesome](https://cdn.jsdelivr.net/gh/sindresorhus/awesome@d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/sindresorhus/awesome) [![](https://github.com/awesome-selfhosted/awesome-selfhosted-data/actions/workflows/ci.yml/badge.svg)](https://github.com/awesome-selfhosted/awesome-selfhosted/issues/2266)
Self-hosting is the practice of hosting and managing applications on your own server(s) instead of consuming from [SaaSS](https://www.gnu.org/philosophy/who-does-that-server-really-serve.html) providers.

39
tests/Dangerfile

@ -1,39 +0,0 @@
# Danger CI configuration file
# https://danger.systems/guides/getting_started.html
# Check for changes to README.md
has_readme_changes = git.modified_files.include?("README.md")
# Ensure there is a summary for a pull request
fail 'Please provide a summary in the Pull Request description' if github.pr_body.length < 5
# Warn if PR guideline boxes are not checked.
warn 'Please check PR guidelines and check the boxes.' if github.pr_body.include? '- [ ]'
# Warn if pull request is not updated
warn 'Please provide a descriptive title for the Pull Request' if github.pr_title.include? 'Update README.md'
# Warn when there are merge commits in the diff
warn 'Please rebase to get rid of the merge commits in this Pull Request' if git.commits.any? { |c| c.message =~ /^Merge branch 'master'/ }
# Check links
if has_readme_changes
require 'json'
results = File.read 'ab-results-temp.md-markdown-table.json'
j = JSON.parse results
if j['error']==true
warn j['title']
markdown j['message']
end
end
# Check syntax
if has_readme_changes
require 'json'
syntaxresults = File.read 'syntaxcheck.json'
sj = JSON.parse syntaxresults
if sj['error']==true
fail sj['title']
markdown sj['message']
end
end

60
tests/check-github-commit-dates.py

@ -1,60 +0,0 @@
#!/usr/bin/env python3
""" A script to find github repo links and last commit dates in a markdown file
Requirements:
- python3 github module (sudo apt install python3-github on Debian)
- A personal access token (https://github.com/settings/tokens)
Usage:
- Run awesome_bot --allow-redirect -f README.md beforehand to detect any error(4xx, 5xx) that would
cause the script to abort
- Github API calls are limited to 5000 requests/hour https://developer.github.com/v3/#rate-limiting
- Put the token in your environment variables:
export GITHUB_TOKEN=18c45f8d8d556492d1d877998a5b311b368a76e4
- The output is unsorted, just pipe it through 'sort' or paste it in your editor and sort from there
- Put the script in your crontab or run it from time to time. It doesn't make sense to add this
script to the CI job that runs every time something is pushed.
- To detect no-commit related activity (repo metadata changes, wiki edits, ...), replace pushed_at
with updated_at
"""
from github import Github
import sys
import time
import re
import os
__author__ = "nodiscc"
__copyright__ = "Copyright 2019, nodiscc"
__credits__ = ["https://github.com/awesome-selfhosted/awesome-selfhosted"]
__license__ = "MIT"
__version__ = "1.0"
__maintainer__ = "nodiscc"
__email__ = "nodiscc@gmail.com"
__status__ = "Production"
###############################################################################
access_token = os.environ['GITHUB_TOKEN']
""" find all URLs of the form https://github.com/owner/repo """
with open('README.md', encoding="utf8") as readme:
data = readme.read()
project_urls = re.findall('https://github.com/[A-z]*/[A-z|0-9|\-|_|\.]+', data)
urls = sorted(set(project_urls))
""" Uncomment this to debug the list of matched URLs """
# print(str(urls))
# exit(0)
""" login to github API """
g = Github(access_token)
""" load project metadata, output last commit date and URL """
for url in urls:
project = re.sub('https://github.com/', '', url)
repo = g.get_repo(project)
print(str(repo.pushed_at) + ' https://github.com/' + project + ' archived:' + str((repo.archived)))

251
tests/test.js

@ -1,251 +0,0 @@
// USAGE:
// node test.js -r README.md (Checks whole file)
// node test.js -r README.md -d temp.md (Checks just the diff)
const fs = require('fs');
const chalk = require('chalk');
let licenses = new Set();
let pr = false;
let readme;
let diff;
//Parse the command options and set the pr var
function parseArgs(args) {
if ( args.indexOf('-r', 2) > 0 ) {
readme = fs.readFileSync(args[args.indexOf('-r', 2)+1], 'utf8')
}
if (args.indexOf('-d', 2) > 0) {
pr = true;
diff = fs.readFileSync(args[args.indexOf('-d', 2)+1], 'utf8');
}
if ( pr === true) {
console.log(chalk.blue(`Running on PR. README.md: ${args[args.indexOf('-r', 2)+1]} diff: ${args[args.indexOf('-d', 2)+1]}`))
}
}
// Function to find lines with entries
function entryFilter(md) {
const linepatt = /^\s{0,2}-\s\[.*`/;
return linepatt.test(md);
}
// Function to find lines with licenses
function licenseFilter(md) {
const linepatt = /^- `.*` - .*/;
return linepatt.test(md)
}
// Function to split lines into array
function split(text) {
return text.split(/\r?\n/);
}
// All entries should match this pattern. If matches pattern returns true.
function findPattern(text) {
const patt = /^\s{0,2}-\s\[.*?\]\(.*?\) (`⚠` )?- .{0,249}?\.( \(\[(Demo|Source Code|Clients)\]\([^)\]]*\)(, \[(Source Code|Clients)\]\([^)\]]*\))?(, \[(Source Code|Clients)\]\([^)\]]*\))*\))? \`.*?\` \`.*?\`$/;
if (patt.test(text) === true) {
return true;
}
return false;
}
// Parses SPDX identifiers from list of licenses
function parseLicense(md) {
const patt = /^- `(.*)` - .*/
return patt.exec(md)[1]
}
//Test '- [Name](http://homepage/)'
function testMainLink(text) {
let testA = /(^ {0,2}- \[.*?\]\([^)]*\.[^)]*?\))(?=\ ?\-?\ ?\w)/ // /(^ {0,2}- \[.*?\]\(.*\))(?=.?-? ?\w)/;
const testA1 = /(- \W?\w*\W{0,2}.*?\)?)( .*$)/;
if (!testA.test(text)) {
let a1 = testA1.exec(text)[2];
return chalk.red(text.replace(a1, ''))
}
return chalk.green(testA.exec(text)[1])
}
//Test '`⚠` - Short description, less than 250 characters.'
function testDescription(text) {
const testB = /( - .*\. )(?:(\(?\[?|\`))/;
const testA1 = /(- \W?\w*\W{0,2}.*?\)?)( .*$)/;
const testB2 = /((\(\[|\`).*$)/;
if (!testB.test(text)) {
let b1 = testA1.exec(text)[1];
let b2 = testB2.exec(text)[1];
return chalk.red(text.replace(b1, '').replace(b2, ''))
}
return chalk.green(testB.exec(text)[1])
}
//If present, tests '([Demo](http://url.to/demo), [Source Code](http://url.of/source/code), [Clients](https://url.to/list/of/related/clients-or-apps))'
function testSrcDemCli(text) {
let testC = text.search(/\.\ \(|\.\ \[|\ \(\[[sSdDcC]/); // /\(\[|\)\,|\)\)/);
let testD = /(?<=\w. )(\(\[(Demo|Source Code|Clients)\]\([^)\]]*\)(, \[(Source Code|Clients)\]\([^)\]]*\))?(, \[(Source Code|Clients)\]\([^)\]]*\))*\))(?= \`?)/;
const testD1 = /(^- \W[a-zA-Z0-9-_ .]*\W{0,2}http[^\[]*)(?<= )/;
const testD2 = /(\`.*\` \`.*\`$)/;
if ((testC > -1) && (!testD.test(text))) {
let d1 = testD1.exec(text)[1];
let d2 = testD2.exec(text)[1];
return chalk.red(text.replace(d1, '').replace(d2, ''))
} else if (testC > -1) {
return chalk.green(testD.exec(text)[1])
}
return ""
}
// Tests '`License` `Language`'
function testLangLic(text) {
const testD2 = /(\`.*\` \`.*\`$)/;
let testE = testD2.test(text);
const testE1 = /(^[^`]*)/;
if (!testE) {
let e1 = testE1.exec(text)[1];
return chalk.red(text.replace(e1, ''))
}
return chalk.green(testD2.exec(text)[1])
}
//Runs all the syntax tests...
function findError(text) {
let res
res = testMainLink(text)
res += testDescription(text)
res += testSrcDemCli(text)
res += testLangLic(text)
return res + `\n`
}
//Check if license is in the list of licenses.
function testLicense(md) {
let pass = true;
let lFailed = []
let lPassed = []
const regex = /.*\`(.*)\` .*$/;
try {
for (l of regex.exec(md)[1].split("/")) {
if (!licenses.has(l)) {
pass = false;
lPassed.push(l)
}
lFailed.push(l)
}
}
catch(err) {
console.log(chalk.yellow("Error in License syntax, license not checked against list."))
return [false, "", ""]
}
return [pass, lFailed, lPassed]
}
//Parses name from entry
function parseName(md) {
const regex = /^\W*(.*?)\W/
return regex.exec(md)[1]
}
function entryErrorCheck() {
const lines = split(readme); // Inserts each line into the entries array
let totalFail = 0;
let totalPass = 0;
let total = 0;
let entries = [];
let diffEntries = [];
if (lines[0] === "") {
console.log(chalk.red("0 Entries Found, check your commandline arguments"))
process.exit(0)
}
for (let i = 0; i < lines.length; i ++) { // Loop through array of lines
if (entryFilter(lines[i]) === true) { // filter out lines that don't start with * [)
e = {};
e.raw = lines[i];
e.line = i + 1
entries.push(e);
} else if (licenseFilter(lines[i]) === true) {
licenses.add(parseLicense(lines[i]))
}
}
if (pr === true) {
console.log(chalk.cyan("Only testing the diff from the PR.\n"))
const diffLines = split(diff); // Inserts each line of diff into an array
for (let l of diffLines) {
if (entryFilter(l) === true) { // filter out lines that don't start with * [)
e = {};
e.raw = l;
diffEntries.push(e);
} else if (licenseFilter(l) === true) {
licenses.add(parseLicense(l))
}
}
if (diffEntries.length === 0) {
console.log("No entries changed in README.md, Exiting...")
process.exit(0)
}
total = diffEntries.length
for (let e of diffEntries) {
e.pass = true
e.name = parseName(e.raw)
if (!findPattern(e.raw)) {
e.highlight = findError(e.raw);
e.pass = false;
console.log(e.highlight)
}
e.licenseTest = testLicense(e.raw);
if (!e.licenseTest) {
e.pass = false;
console.log(chalk.red(`${e.name}'s license is not on License list.`))
}
if (e.pass) {
totalPass++
} else {
totalFail++
}
}
} else {
console.log(chalk.cyan("Testing entire README.md\n"))
total = entries.length
for (let e of entries) {
e.pass = true
e.name = parseName(e.raw)
if (!findPattern(e.raw)) {
e.highlight = findError(e.raw);
e.pass = false;
console.log(`${chalk.yellow(e.line + ": ")}${e.highlight}`);
syntax = e.highlight;
}
e.licenseTest = testLicense(e.raw);
if (!e.licenseTest[0]) {
e.pass = false;
console.log(chalk.yellow(e.line + ": ") + `${e.name}'s license ${chalk.red(`'${e.licenseTest[1]}'`)} is not on the License list.\n`)
}
if (e.pass) {
totalPass++
} else {
totalFail++
}
}
}
if (totalFail > 0) {
console.log(chalk.blue(`\n-----------------------------\n`))
console.log(chalk.red(`${totalFail} Failed, `) + chalk.green(`${totalPass} Passed, `) + chalk.blue(`of ${total}`))
console.log(chalk.blue(`\n-----------------------------\n`))
process.exit(1);
} else {
console.log(chalk.blue(`\n-----------------------------\n`))
console.log(chalk.green(`${totalPass} Passed of ${total}`))
console.log(chalk.blue(`\n-----------------------------\n`))
process.exit(0)
}
}
parseArgs(process.argv)
entryErrorCheck();
Loading…
Cancel
Save