Skip to content

Commit

Permalink
fix proc target
Browse files Browse the repository at this point in the history
  • Loading branch information
umputun committed Jan 2, 2024
1 parent 0925389 commit 7793afa
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 43 deletions.
2 changes: 1 addition & 1 deletion publisher/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ RUN \
spot --version

COPY --from=build /build/bin/publisher /usr/local/bin/publisher
COPY spot.yml /srv/spot.yml
COPY spot.yml /etc/spot.yml

WORKDIR /srv/hugo
USER app
Expand Down
16 changes: 8 additions & 8 deletions publisher/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.DEFAULT_GOAL := help
SHELL:=/bin/bash
.ONESHELL:
.PHONY: new prep print-mp3-tags upload-mp3 deploy build
.PHONY: new-show-post prep-show-post proc-mp3 deploy-site build

TMPFILE := $(shell mktemp)
makefile_dir := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
Expand All @@ -13,26 +13,26 @@ GITREV=$(shell git describe --abbrev=7 --always --tags)
REV=$(GITREV)-$(BRANCH)-$(shell date +%Y%m%d-%H:%M:%S)

help:
@echo 'available commands: new, prep, upload-mp3, deploy'
@echo 'available commands: new-show-post, prep-show-post, proc-mp3, deploy-site'

# generate new episode post markdown file and open it using SublimeText
new:
new-episode:
@docker-compose run --rm -it publisher new | tee ${TMPFILE};
@${subl} ${makefile_dir}/../hugo/`tail -n 1 ${TMPFILE} | tr -d '\r'`;

# generate new prep post markdown file and open it using SublimeText
prep:
prep-show-post:
@docker-compose run --rm -it publisher prep | tee ${TMPFILE};
@${subl} ${makefile_dir}/../hugo/`tail -n 1 ${TMPFILE} | tr -d '\r'`;

# set necessary tags to episode mp3 file and upload it to master and all nodes
proc:
@docker-compose run --rm -it publisher proc --episode="$$EPISODE" --dbg
proc-mp3:
@docker-compose run --rm -it publisher proc --file="$$FILE" --dbg

# deploy new podcast episode page to https://radio-t.com and regenerate site
deploy:
deploy-site:
@docker-compose run --rm -it publisher deploy

build:
@echo $(REV)
@docker build -t publisher --build-arg REV=$(REV) .
@docker build -t radio-t/publisher --build-arg REV=$(REV) .
36 changes: 24 additions & 12 deletions publisher/app/cmd/proc_mp3.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,22 @@ var artifactsFS embed.FS
// Proc handles podcast upload to all destinations. It sets mp3 tags first and then deploys to master and nodes via spot tool.
type Proc struct {
Executor
LocationMp3 string
LocationPosts string
Dry bool
SkipTransfer bool
}

var authors = []string{"Umputun", "Bobuk", "Gray", "Ksenks", "Alek.sys"}

// Do uploads an episode to all destinations. It takes an episode number as input and returns an error if any of the actions fail.
// deploy performed by spot tool, see spot.yml
func (p *Proc) Do(episodeNum int) error {
log.Printf("[INFO] upload episode %d, mp3 location:%q, posts location:%q", episodeNum, p.LocationMp3, p.LocationPosts)
mp3file := filepath.Join(p.LocationMp3, fmt.Sprintf("rt_podcast%d", episodeNum), fmt.Sprintf("rt_podcast%d.mp3", episodeNum))
log.Printf("[DEBUG] mp3 file %s", mp3file)
// Do uploads an episode to all destinations. It takes the filename and extracts episode from this filename.
// Set all the mp3 tags and add chapters. Then deploy to master and nodes. Deploy performed by spot tool, see spot.yml
func (p *Proc) Do(mp3file string) error {
episodeNum, err := episodeFromFile(mp3file)
if err != nil {
return fmt.Errorf("can't get episode number from file %s, %w", mp3file, err)
}

log.Printf("[INFO] process file %s, episode %d, posts location:%q", mp3file, episodeNum, p.LocationPosts)
hugoPost := fmt.Sprintf("%s/podcast-%d.md", p.LocationPosts, episodeNum)
log.Printf("[DEBUG] hugo post file %s", hugoPost)
posstContent, err := os.ReadFile(hugoPost)
Expand All @@ -50,7 +52,7 @@ func (p *Proc) Do(episodeNum int) error {
}
log.Printf("[DEBUG] chapters %v", chapters)

err = p.setMp3Tags(episodeNum, chapters)
err = p.setMp3Tags(mp3file, episodeNum, chapters)
if err != nil {
log.Printf("[WARN] can't set mp3 tags for %s, %v", mp3file, err)
}
Expand All @@ -60,8 +62,8 @@ func (p *Proc) Do(episodeNum int) error {
return nil
}

p.Run("spot", "-e mp3:"+mp3file, `--task="deploy to master"`, "-v")
p.Run("spot", "-e mp3:"+mp3file, `--task="deploy to nodes"`, "-v")
p.Run("spot", "-p /etc/spot.yml", "-e mp3:"+mp3file, `--task="deploy to master"`, "-v")
p.Run("spot", "-p /etc/spot.yml", "-e mp3:"+mp3file, `--task="deploy to nodes"`, "-v")
return nil
}

Expand All @@ -74,8 +76,7 @@ type chapter struct {

// setMp3Tags sets mp3 tags for a given episode. It uses artifactsFS to read cover.jpg
// and uses the chapter information to set the chapter tags.
func (p *Proc) setMp3Tags(episodeNum int, chapters []chapter) error {
mp3file := fmt.Sprintf("%s/rt_podcast%d/rt_podcast%d.mp3", p.LocationMp3, episodeNum, episodeNum)
func (p *Proc) setMp3Tags(mp3file string, episodeNum int, chapters []chapter) error {
log.Printf("[INFO] set mp3 tags for %s", mp3file)
if p.Dry {
return nil
Expand Down Expand Up @@ -304,3 +305,14 @@ func (p *Proc) ShowAllTags(fname string) {
}
}
}

// episodeFromFile takes full path to mp3 file and returns episode number
func episodeFromFile(mp3Location string) (int, error) {
name := filepath.Base(mp3Location)
re := regexp.MustCompile(`rt_podcast(\d+)\.mp3`)
matches := re.FindStringSubmatch(name)
if len(matches) != 2 {
return 0, fmt.Errorf("can't find episode number in %s", mp3Location)
}
return strconv.Atoi(matches[1])
}
59 changes: 49 additions & 10 deletions publisher/app/cmd/proc_mp3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,20 @@ func TestProc_Do(t *testing.T) {

d := Proc{
Executor: ex,
LocationMp3: tempDir,
LocationPosts: "testdata",
}

err = d.Do(123)
err = d.Do("/tmp/publisher_test/rt_podcast123/rt_podcast123.mp3")
require.NoError(t, err)

require.Equal(t, 2, len(ex.RunCalls()))
assert.Equal(t, "spot", ex.RunCalls()[0].Cmd)
assert.Equal(t, []string{"-e mp3:/tmp/publisher_test/rt_podcast123/rt_podcast123.mp3", "--task=\"deploy to master\"", "-v"},
ex.RunCalls()[0].Params)
assert.Equal(t, []string{"-p /etc/spot.yml", "-e mp3:/tmp/publisher_test/rt_podcast123/rt_podcast123.mp3",
"--task=\"deploy to master\"", "-v"}, ex.RunCalls()[0].Params)

assert.Equal(t, "spot", ex.RunCalls()[1].Cmd)
assert.Equal(t, []string{"-e mp3:/tmp/publisher_test/rt_podcast123/rt_podcast123.mp3", "--task=\"deploy to nodes\"", "-v"},
ex.RunCalls()[1].Params)
assert.Equal(t, []string{"-p /etc/spot.yml", "-e mp3:/tmp/publisher_test/rt_podcast123/rt_podcast123.mp3",
"--task=\"deploy to nodes\"", "-v"}, ex.RunCalls()[1].Params)
}

func TestProc_setMp3Tags(t *testing.T) {
Expand All @@ -74,9 +73,10 @@ func TestProc_setMp3Tags(t *testing.T) {
_, err = io.Copy(dst, src)
require.NoError(t, err)

u := Proc{}

t.Run("without chapters", func(t *testing.T) {
u := Proc{LocationMp3: tempDir}
err = u.setMp3Tags(123, nil)
err = u.setMp3Tags(dst.Name(), 123, nil)
require.NoError(t, err)

tag, err := id3v2.Open(dst.Name(), id3v2.Options{Parse: true})
Expand All @@ -89,8 +89,7 @@ func TestProc_setMp3Tags(t *testing.T) {
})

t.Run("with chapters", func(t *testing.T) {
u := Proc{LocationMp3: tempDir}
err = u.setMp3Tags(123, []chapter{
err = u.setMp3Tags(dst.Name(), 123, []chapter{
{"Chapter One", "http://example.com/one", time.Second},
{"Chapter Two", "http://example.com/two", time.Second * 5},
})
Expand Down Expand Up @@ -213,3 +212,43 @@ filename = "rt_podcast686"
assert.NoError(t, err)
assert.Equal(t, expectedChapters, result)
}

func TestEpisodeFromFile(t *testing.T) {
testCases := []struct {
name string
input string
expected int
expectErr bool
}{
{
name: "valid episode number",
input: "/path/to/rt_podcast123.mp3",
expected: 123,
expectErr: false,
},
{
name: "missing episode number",
input: "/another/path/to/rt_podcast.mp3",
expected: 0,
expectErr: true,
},
{
name: "non-numeric episode number",
input: "/yet/another/path/to/rt_podcastXYZ.mp3",
expected: 0,
expectErr: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result, err := episodeFromFile(tc.input)
if tc.expectErr {
assert.Error(t, err, "Expected an error but didn't get one")
} else {
assert.NoError(t, err, "Expected no error but got one")
assert.Equal(t, tc.expected, result, "Mismatch in expected and actual result")
}
})
}
}
13 changes: 6 additions & 7 deletions publisher/app/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var opts struct {
} `command:"prep" description:"make new prep podcast post"`

ProcessCmd struct {
Location string `long:"location" env:"LOCATION" default:"/episodes" description:"podcast location"`
File string `long:"file" env:"FILE" description:"mp3 file name"`
HugoPosts string `long:"hugo-posts" env:"HUGO_POSTS" default:"/srv/hugo/content/posts" description:"hugo posts location"`
SkipTransfer bool `long:"skip-transfer" env:"SKIP_TRANSFER" description:"skip transfer to remote locations"`
} `command:"proc" description:"proces podcast - tag mp3 and upload"`
Expand Down Expand Up @@ -78,7 +78,7 @@ func main() {
}

if p.Active != nil && p.Command.Find("proc") == p.Active {
runProc(episodeNum())
runProc()
}

if p.Active != nil && p.Command.Find("deploy") == p.Active {
Expand Down Expand Up @@ -134,18 +134,17 @@ func runPrep(episodeNum int) {
fmt.Printf("%s/prep-%d.md", opts.PrepShowCmd.Dest, episodeNum) // don't delete! used by external callers
}

func runProc(episodeNum int) {
func runProc() {
proc := cmd.Proc{
Executor: &cmd.ShellExecutor{Dry: opts.Dry},
LocationMp3: opts.ProcessCmd.Location,
LocationPosts: opts.ProcessCmd.HugoPosts,
SkipTransfer: opts.ProcessCmd.SkipTransfer,
Dry: opts.Dry,
}
if err := proc.Do(episodeNum); err != nil {
log.Fatalf("[ERROR] failed to proc #%d, %v", episodeNum, err)
if err := proc.Do(opts.ProcessCmd.File); err != nil {
log.Fatalf("[ERROR] failed to proc %s, %v", opts.ProcessCmd.File, err)
}
log.Printf("[INFO] deployed #%d", episodeNum)
log.Printf("[INFO] processsed %s", opts.ProcessCmd.File)
}

func runTags() {
Expand Down
10 changes: 5 additions & 5 deletions publisher/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ services:
max-size: "10m"
max-file: "5"
environment:
PYTHONPATH: /srv/publisher
RT_NEWS_ADMIN:
- RT_NEWS_ADMIN
volumes:
- ../:/srv/
- /Volumes/Podcasts/radio-t:/episodes
- /Users/umputun/.ssh/id_rsa.pub:/home/app/.ssh/id_rsa.pub:ro
- /Users/umputun/.ssh/id_rsa:/home/app/.ssh/id_rsa:ro
- /Volumes/Podcasts/radio-t:/Volumes/Podcasts/radio-t
- /Users/umputun/.ssh/id_rsa.pub:/home/app/.ssh/id_rsa.pub
- /Users/umputun/.ssh/id_rsa:/home/app/.ssh/id_rsa
# entrypoint: tail -f /dev/null
1 change: 1 addition & 0 deletions publisher/spot.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
user: umputun
targets:
nodes:
hosts: [{host: "n10.radio-t.com"}, {host: "n11.radio-t.com"}]
Expand Down

0 comments on commit 7793afa

Please sign in to comment.