Compare commits
No commits in common. "98268ffe0abe071b79a854e8b4f081d65decc8ec" and "8a6734fba325ead97c46749b03d91be4d9744ec6" have entirely different histories.
98268ffe0a
...
8a6734fba3
|
@ -1,5 +1,3 @@
|
||||||
.env
|
.env
|
||||||
bin
|
bin
|
||||||
*.txt
|
*.txt
|
||||||
artifacts
|
|
||||||
bin
|
|
|
@ -7,22 +7,13 @@ steps:
|
||||||
image: golang:1.20-alpine
|
image: golang:1.20-alpine
|
||||||
commands:
|
commands:
|
||||||
- apk update
|
- apk update
|
||||||
- apk add --no-cache make alpine-sdk g++ bash
|
- apk add --no-cache make alpine-sdk g++
|
||||||
- make build
|
- make build
|
||||||
- echo "$${CI_COMMIT_TAG}"
|
- echo "$${CI_COMMIT_TAG}"
|
||||||
- make release
|
- make release
|
||||||
|
|
||||||
generate-changelog:
|
|
||||||
image: python:3.11-alpine
|
|
||||||
commands:
|
|
||||||
- apk update
|
|
||||||
- apk add --no-cache make alpine-sdk g++ bash
|
|
||||||
- make changelog-draft
|
|
||||||
|
|
||||||
release:
|
release:
|
||||||
image: woodpeckerci/plugin-gitea-release
|
image: woodpeckerci/plugin-gitea-release
|
||||||
when:
|
|
||||||
event: tag
|
|
||||||
settings:
|
settings:
|
||||||
base_url: https://git.iratusmachina.com
|
base_url: https://git.iratusmachina.com
|
||||||
files:
|
files:
|
||||||
|
@ -34,4 +25,3 @@ steps:
|
||||||
skip_verify: true
|
skip_verify: true
|
||||||
target: main
|
target: main
|
||||||
checksum: sha256
|
checksum: sha256
|
||||||
note: "./draft_notes.md"
|
|
||||||
|
|
8
Makefile
8
Makefile
|
@ -42,14 +42,6 @@ release:
|
||||||
rm -rf ${BIN_DIR}/tmp
|
rm -rf ${BIN_DIR}/tmp
|
||||||
cd ${CURRENT_DIR}
|
cd ${CURRENT_DIR}
|
||||||
|
|
||||||
.PHONY: changelog-full
|
|
||||||
changelog-full:
|
|
||||||
python3 generate_notes.py --full
|
|
||||||
|
|
||||||
.PHONY: changelog-draft
|
|
||||||
changelog-draft:
|
|
||||||
python3 generate_notes.py --draft
|
|
||||||
|
|
||||||
.PHONY: lint-all
|
.PHONY: lint-all
|
||||||
lint-all:
|
lint-all:
|
||||||
golangci-lint run --enable-all
|
golangci-lint run --enable-all
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
"""
|
|
||||||
This module generates a draft_notes.md to be attached to a Gitea release and
|
|
||||||
a CHANGELOG.md to be committed into the repo.
|
|
||||||
|
|
||||||
It is the python version of this https://stackoverflow.com/a/46033999
|
|
||||||
"""
|
|
||||||
|
|
||||||
import subprocess
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
def full():
|
|
||||||
with open("CHANGELOG.md", "w+") as fw:
|
|
||||||
try:
|
|
||||||
# Get all the tags sorted in decreasing order (the -creatordate is what sorts in decreasing order)
|
|
||||||
tags = subprocess.check_output(["git", "tag", "--sort=-creatordate"], text=True)
|
|
||||||
tags = [tag for tag in tags.split("\n") if tag]
|
|
||||||
# Get the remote url
|
|
||||||
remote_url = subprocess.check_output(["git", "remote", "get-url", "origin"], text=True)
|
|
||||||
# Remove the first occurence of the word git starting from the end of the string
|
|
||||||
remote_url = remote_url[0:remote_url.rfind(".git")]
|
|
||||||
previous_tag = ""
|
|
||||||
for tag in tags:
|
|
||||||
if previous_tag:
|
|
||||||
# Extract the date of the commit
|
|
||||||
tag_date = subprocess.check_output(["git", "log", "-1", f"--pretty=format:'%ad'", "--date=short", f"{tag}"], text=True)
|
|
||||||
tag_date = tag_date.replace("'", "")
|
|
||||||
|
|
||||||
# Get each commit of a tag formatted
|
|
||||||
formatted_lines = subprocess.check_output(["git", "log", f"{tag}...{previous_tag}", f'--pretty=format:"* %s [View]({remote_url}/commits/%H)"'], text=True)
|
|
||||||
if formatted_lines:
|
|
||||||
fw.write(f"## {tag} ({tag_date})\n\n")
|
|
||||||
# Remove merge commits or Changelog commits
|
|
||||||
lines = "\n".join([line.replace("\"", "") for line in formatted_lines.split("\n") if all(["merge" not in line.lower(), "changelog.md" not in line.lower()])])
|
|
||||||
fw.write(lines)
|
|
||||||
fw.write("\n\n")
|
|
||||||
previous_tag = tag
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
print(f"Command failed with return code {e.returncode}")
|
|
||||||
|
|
||||||
def draft():
|
|
||||||
with open("draft_notes.md", "w+") as fw:
|
|
||||||
try:
|
|
||||||
# Get the remote url
|
|
||||||
remote_url = subprocess.check_output(["git", "remote", "get-url", "origin"], text=True)
|
|
||||||
# Remove the first occurence of the word git starting from the end of the string
|
|
||||||
remote_url = remote_url[0:remote_url.rfind(".git")]
|
|
||||||
|
|
||||||
# Get the current and previous tags
|
|
||||||
tags = subprocess.check_output(["git", "tag", "--sort=creatordate"], text=True)
|
|
||||||
tags = [tag for tag in tags.split("\n") if tag]
|
|
||||||
tags.reverse()
|
|
||||||
current_tag, previous_tag, *_ = tags
|
|
||||||
formatted_lines = subprocess.check_output(["git", "log", f"{current_tag}...{previous_tag}", f'--pretty=format:"* %s"'], text=True)
|
|
||||||
lines = "\n".join([line.replace("\"", "") for line in formatted_lines.split("\n") if all(["merge" not in line.lower(), "changelog.md" not in line.lower()])])
|
|
||||||
fw.write(lines)
|
|
||||||
fw.write("\n\n")
|
|
||||||
fw.write(f"Compare between recent changes: [{previous_tag[1:]}...{current_tag[1:]}]({remote_url}/compare/{previous_tag}...{current_tag})")
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
print(f"Command failed with return code {e.returncode}")
|
|
||||||
|
|
||||||
def run():
|
|
||||||
parser = argparse.ArgumentParser(description='Generate changelogs....')
|
|
||||||
group = parser.add_mutually_exclusive_group(required=True)
|
|
||||||
group.add_argument("--full", help="Generate full changelog", action="store_true")
|
|
||||||
group.add_argument("--draft", help="Generate notes with tag", action="store_true")
|
|
||||||
args = parser.parse_args()
|
|
||||||
if args.full:
|
|
||||||
full()
|
|
||||||
elif args.draft:
|
|
||||||
draft()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
run()
|
|
|
@ -2,7 +2,6 @@ package cmdline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
@ -16,8 +15,6 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
printDebug bool
|
printDebug bool
|
||||||
useGenius bool
|
|
||||||
useGoogle bool
|
|
||||||
outputFile string
|
outputFile string
|
||||||
errorLog *log.Logger
|
errorLog *log.Logger
|
||||||
mainLog *log.Logger
|
mainLog *log.Logger
|
||||||
|
@ -32,78 +29,69 @@ func recurseNodes(top *html.Node, sb *strings.Builder) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func searchGoogle(song string) (err error) {
|
func searchGoogle(song string) error {
|
||||||
runOption := &playwright.RunOptions{
|
runOption := &playwright.RunOptions{
|
||||||
SkipInstallBrowsers: true,
|
SkipInstallBrowsers: true,
|
||||||
}
|
}
|
||||||
tempErr := playwright.Install(runOption)
|
err := playwright.Install(runOption)
|
||||||
if tempErr != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("could not install playwright dependencies: %v", tempErr)
|
return fmt.Errorf("could not install playwright dependencies: %v", err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
pw, tempErr := playwright.Run()
|
pw, err := playwright.Run()
|
||||||
if tempErr != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("could not start playwright: %v", tempErr)
|
return fmt.Errorf("could not start playwright: %v", err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
defer func(pw *playwright.Playwright) {
|
defer func(pw *playwright.Playwright) error {
|
||||||
tempErr := pw.Stop()
|
err := pw.Stop()
|
||||||
if tempErr != nil {
|
if err != nil {
|
||||||
e := fmt.Errorf("could not stop Playwright: %v", tempErr)
|
return fmt.Errorf("could not stop Playwright: %v", err)
|
||||||
err = errors.Join(err, e)
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}(pw)
|
}(pw)
|
||||||
|
|
||||||
option := playwright.BrowserTypeLaunchOptions{
|
option := playwright.BrowserTypeLaunchOptions{
|
||||||
Channel: playwright.String("chrome"),
|
Channel: playwright.String("chrome"),
|
||||||
Headless: playwright.Bool(false),
|
Headless: playwright.Bool(false),
|
||||||
}
|
}
|
||||||
browser, tempErr := pw.Chromium.Launch(option)
|
browser, err := pw.Chromium.Launch(option)
|
||||||
if tempErr != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("could not launch browser: %v", tempErr)
|
return fmt.Errorf("could not launch browser: %v", err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func(browser playwright.Browser) {
|
defer func(browser playwright.Browser) error {
|
||||||
tempErr = browser.Close()
|
err = browser.Close()
|
||||||
if tempErr != nil {
|
if err != nil {
|
||||||
e := fmt.Errorf("could not close browser: %v", tempErr)
|
return fmt.Errorf("could not close browser: %v", err)
|
||||||
err = errors.Join(err, e)
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}(browser)
|
}(browser)
|
||||||
page, tempErr := browser.NewPage()
|
page, err := browser.NewPage()
|
||||||
if tempErr != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("could not create page: %v", tempErr)
|
return fmt.Errorf("could not create page: %v", err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
if _, tempErr := page.Goto(fmt.Sprintf("https://www.google.com/search?q=%ss+lyrics", song),
|
if _, err := page.Goto(fmt.Sprintf("https://www.google.com/search?q=%ss+lyrics", song),
|
||||||
playwright.PageGotoOptions{
|
playwright.PageGotoOptions{
|
||||||
WaitUntil: playwright.WaitUntilStateLoad,
|
WaitUntil: playwright.WaitUntilStateLoad,
|
||||||
}); tempErr != nil {
|
}); err != nil {
|
||||||
err = fmt.Errorf("could not goto: %v", tempErr)
|
return fmt.Errorf("could not goto: %v", err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
tempErr = page.Locator("body").WaitFor(playwright.LocatorWaitForOptions{
|
err = page.Locator("body").WaitFor(playwright.LocatorWaitForOptions{
|
||||||
State: playwright.WaitForSelectorStateVisible,
|
State: playwright.WaitForSelectorStateVisible,
|
||||||
})
|
})
|
||||||
if tempErr != nil {
|
|
||||||
err = fmt.Errorf("could not wait for body: %v", tempErr)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
html, tempErr := page.Locator("html").InnerHTML()
|
|
||||||
if tempErr != nil {
|
|
||||||
err = fmt.Errorf("could not get innerHtml: %v", tempErr)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
doc, tempErr := htmlquery.Parse(bytes.NewReader([]byte(html)))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("could not parse the innerHtml: %v", tempErr)
|
return fmt.Errorf("could not wait for body: %v", err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
nodes, tempErr := htmlquery.QueryAll(doc, "//div[@data-lyricid]/div")
|
html, err := page.Locator("html").InnerHTML()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("could not get the nodes: %v", tempErr)
|
return fmt.Errorf("could not get innerHtml: %v", err)
|
||||||
return err
|
}
|
||||||
|
doc, err := htmlquery.Parse(bytes.NewReader([]byte(html)))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not parse the innerHtml: %v", err)
|
||||||
|
}
|
||||||
|
nodes, err := htmlquery.QueryAll(doc, "//div[@data-lyricid]/div")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not get the nodes: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
|
@ -115,10 +103,9 @@ func searchGoogle(song string) (err error) {
|
||||||
mainLog.Println("Writing lyrics from Google...")
|
mainLog.Println("Writing lyrics from Google...")
|
||||||
}
|
}
|
||||||
filename := fmt.Sprintf("%s_google.txt", outputFile)
|
filename := fmt.Sprintf("%s_google.txt", outputFile)
|
||||||
tempErr = os.WriteFile(filename, []byte(sb.String()), os.ModePerm)
|
err = os.WriteFile(filename, []byte(sb.String()), os.ModePerm)
|
||||||
if tempErr != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("could not write to %s: %v", filename, err)
|
return fmt.Errorf("could not write to %s: %v", filename, err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mainLog.Println("Lyrics cannot be found...")
|
mainLog.Println("Lyrics cannot be found...")
|
||||||
|
@ -141,13 +128,11 @@ func Main() int {
|
||||||
out := flags.Output()
|
out := flags.Output()
|
||||||
fmt.Fprintf(out, "Usage: %v \n\n", programName)
|
fmt.Fprintf(out, "Usage: %v \n\n", programName)
|
||||||
fmt.Fprint(out, " This program is used to download lyrics for a song\n")
|
fmt.Fprint(out, " This program is used to download lyrics for a song\n")
|
||||||
fmt.Fprint(out, " from the internet. There are two modes of operation.\n\n")
|
fmt.Fprint(out, " from the internet. The steps of operation are shown here: \n\n")
|
||||||
fmt.Fprint(out, " The first mode is scraping the lyrics from Google. So the operation is this: \n")
|
fmt.Fprint(out, " (a) It first opens a chrome window, searches for the lyrics \n")
|
||||||
fmt.Fprint(out, " It first opens a chrome window, searches for the lyrics \n")
|
|
||||||
fmt.Fprint(out, " , and copies the lyrics returned by Google Search to a \n")
|
fmt.Fprint(out, " , and copies the lyrics returned by Google Search to a \n")
|
||||||
fmt.Fprint(out, " file defined by you.\n\n")
|
fmt.Fprint(out, " file defined by you.\n\n")
|
||||||
fmt.Fprint(out, " The second mode is getting the lyrics from Genius API. So the operation is this: \n")
|
fmt.Fprint(out, " (b) It then tries to get search for the same song using the \n")
|
||||||
fmt.Fprint(out, " It then tries to get search for the same song using the \n")
|
|
||||||
fmt.Fprint(out, " Genius API. It then tries to compare the lyrics with the \n")
|
fmt.Fprint(out, " Genius API. It then tries to compare the lyrics with the \n")
|
||||||
fmt.Fprint(out, " Genius one.\n\n")
|
fmt.Fprint(out, " Genius one.\n\n")
|
||||||
flags.PrintDefaults()
|
flags.PrintDefaults()
|
||||||
|
@ -157,13 +142,8 @@ func Main() int {
|
||||||
verboseFlag := flags.Bool("verbose", false, "Optional. Turn on debug. Default is false.")
|
verboseFlag := flags.Bool("verbose", false, "Optional. Turn on debug. Default is false.")
|
||||||
searchFlag := flags.String("search", "", "Required. Name of song to search. If the name of the song is not a single word, put in quotes\"\"")
|
searchFlag := flags.String("search", "", "Required. Name of song to search. If the name of the song is not a single word, put in quotes\"\"")
|
||||||
helpFlag := flags.Bool("help", false, "Optional. Print Usage")
|
helpFlag := flags.Bool("help", false, "Optional. Print Usage")
|
||||||
useGoogleFlag := flags.Bool("google", false, "Optional. Use google.")
|
|
||||||
useGeniusFlag := flags.Bool("genius", false, "Optional. Use genius")
|
|
||||||
|
|
||||||
err := flags.Parse(os.Args[1:])
|
flags.Parse(os.Args[1:])
|
||||||
if err != nil {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(flags.Args()) > 1 {
|
if len(flags.Args()) > 1 {
|
||||||
errorLog.Println("Error: too many command-line arguments")
|
errorLog.Println("Error: too many command-line arguments")
|
||||||
|
@ -179,18 +159,6 @@ func Main() int {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if !allSetFlags["google"] && !allSetFlags["genius"] {
|
|
||||||
errorLog.Println("Error: One of -google or -genius must be set")
|
|
||||||
flags.Usage()
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if allSetFlags["google"] && allSetFlags["genius"] {
|
|
||||||
errorLog.Println("Error: if -google is set, -genius must remain unset and vice versa")
|
|
||||||
flags.Usage()
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if *helpFlag {
|
if *helpFlag {
|
||||||
flags.Usage()
|
flags.Usage()
|
||||||
return 0
|
return 0
|
||||||
|
@ -216,20 +184,11 @@ func Main() int {
|
||||||
mainLog.Printf("Output flag: %s, Debug flag: %t, Search flag: %s\n", outputFile, printDebug, songToSearch)
|
mainLog.Printf("Output flag: %s, Debug flag: %t, Search flag: %s\n", outputFile, printDebug, songToSearch)
|
||||||
}
|
}
|
||||||
|
|
||||||
useGenius = *useGeniusFlag
|
|
||||||
useGoogle = *useGoogleFlag
|
|
||||||
|
|
||||||
if useGoogle {
|
|
||||||
err := searchGoogle(songToSearch)
|
err := searchGoogle(songToSearch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorLog.Printf("Err: %+v", err)
|
errorLog.Printf("Err: %+v", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if useGenius {
|
|
||||||
fmt.Println("No op")
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue