Introduction
Currently, I'm writing a customized GitHub workflow inside it I use a curl and grep command.
GitHub repo
action.yml
- name: get new tag
id: get_new_tag
shell: bash
run: |
temp_result=$(curl -s https://api.github.com/repos/${{inputs.github_repository}}/tags | grep -h "name" | grep -h "${{inputs.selector}}" | head -1 | grep -ho "${{inputs.regex}}")
echo "new-tag=${temp_result}" >> $GITHUB_OUTPUT
Full code here
test for action.yml
uses: ./
with:
files: tests/test1.txt tests/test2.txt
github_repository: MathieuSoysal/file-updater-for-release
prefix: MathieuSoysal/file-updater-for-release#
Full code are is here
Problem
I don't understand why but my GitHub Actions don't work with MacOS.
The given error:
temp_result=$(curl -s https://api.github.com/repos/MathieuSoysal/file-updater-for-release/tags | grep -h "name" | grep -h "" | head -1 | grep -ho "v\?[0-9.]*")
echo "new-tag=${temp_result}" >> $GITHUB_OUTPUT
shell: /bin/bash --noprofile --norc -e -o pipefail {0}
Error: Process completed with exit code 1.
Full log error is here
Question
Does someone know how we can fix this issue?
Alternatively, you can simply use the jq command line utility for this which is already installed and available on the GitHub runners. See the preinstalled software.
$ export URL='https://api.github.com/repos/MathieuSoysal/file-updater-for-release/tags'
$ curl -s $URL | jq -r .[0].name
v1.0.3
The issue is from this command grep -h "", this command is not supported on MacOS.
The empty string is not supported, the solution is to add something inside it.
I'm trying to get this shell script to work in make:
$ VERSION=$(echo 'ThisBuild / version := "1.20"' | grep -e 'This.*version' | grep -Eo '[0-9]+\.[0-9]+')
$ echo $VERSION
1.20
make:
$ make -v
GNU Make 4.2.1
Built for x86_64-pc-linux-gnu
Makefile:
version:
VERSION=$(echo 'ThisBuild / version := "1.20"' | grep -e 'This.*version' | grep -Eo '[0-9]+\.[0-9]+') && \
echo "VERSION: ${VERSION}"
Doesn't work:
$ make version
VERSION= && \
echo "VERSION: "
VERSION:
Can this be done?
If you want to pass $ to the shell you have to escape it from make, by doubling it: $$.
version:
VERSION=$$(echo 'ThisBuild / version := "1.20"' | grep -e 'This.*version' | grep -Eo '[0-9]+\.[0-9]+') && \
echo "VERSION: $${VERSION}"
Otherwise, make will think that you're referencing a make variable and expand it.
I am setting up a random password to be used on the initial login within my Dockerfile. I have tried
ENV PASSWORD=RUN date +%s | sha256sum | base64 | head -c 32
Which does not work because Docker commands are in separate containers. I also tried
RUN export PASSWORD= date +%s | sha256sum | base64 | head -c 32
Which has also failed.
I have also tried to redirect my output to a file, which also fails, the file stays empty and no error is given.
RUN date +%s | sha256sum | base64 | head -c 32 > test.txt
How can I save the output from this command as an ENV var to be used in my Docker container?
The following Dockerfile:
FROM alpine:latest
RUN echo "bd" > /test.txt
when run has the test.txt file present:
docker build . -t test:latest
docker run -it --rm test:latest
> cat /test.txt
> 'bd'
You could change your command to write a file in a sourceable manner (RUN echo "my_env_var=$(echo 'stuff')" > /test.txt) and then have your entrypoint include . /test.txt
This problem occurs only on suse, it works on ubuntu and even on windows through babun
My point is to replace a word in several files with another word.
This is what I'm trying:
$ grep -Inrs MY_PATTERN src/ | cut -d: -f1 | xargs sed -i 's/MY_PATTERN/NEW_WORD/g'
sed: can't read path/to/a/found/file_1: No such file or directory
sed: can't read path/to/a/found/file_2: No such file or directory
sed: can't read path/to/a/found/file_3: No such file or directory
...
Knowing that
$ grep -Inrs MY_PATTERN src/ | cut -d: -f1
path/to/a/found/file_1
path/to/a/found/file_2
path/to/a/found/file_3
UPDATE1
This doesn't work either
$ grep -lZ -Irs MY_PATTERN src/ | xargs -0 ls
ls: cannot access path/to/a/found/file_1: No such file or directory
ls: cannot access path/to/a/found/file_2: No such file or directory
ls: cannot access path/to/a/found/file_3: No such file or directory
...
$ ls -al path/to/a/found/file_1 | cat -vet
-rw-r--r-- 1 webme 886 Feb 1 13:36 path/to/a/found/file_1$
UPDATE2
$ whoami
webme
$ uname -a
Linux server_vm_id_34 3.0.101-68-default #1 SMP Tue Dec 1 16:21:37 UTC 2015 (ed01a9f) x86_64 x86_64 x86_64 GNU/Linux
UPDATE3
$ grep --version
grep (GNU grep) 2.7
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Mike Haertel and others, see <http://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.
$ xargs --version
xargs (GNU findutils) 4.4.0
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Built using GNU gnulib version e5573b1bad88bfabcda181b9e0125fb0c52b7d3b
# My project path /home/users/webme/projects/my_project
$ df -T
dl360d-01:/homeweb/users/webme nfs 492625920 461336576 31289344 94% /home/users/webme
$ id
uid=1689(webme) gid=325(web) groups=325(web)
$ mount -v
/dev/vda2 on / type btrfs (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
debugfs on /sys/kernel/debug type debugfs (rw)
udev on /dev type tmpfs (rw,mode=0755)
tmpfs on /dev/shm type tmpfs (rw,mode=1777)
devpts on /dev/pts type devpts (rw,mode=0620,gid=5)
/dev/vda1 on /boot type ext3 (rw,acl,user_xattr)
/dev/vdb on /appwebinet type xfs (rw)
rpc_pipefs on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)
dl360d-01:/homeweb/users on /homeweb/users type nfs (rw,soft,bg,addr=xx.xx.xx.xx)
dl360d-01:/appwebinet/tools/list on /appwebinetdev/tools/list type nfs (ro,soft,sloppy,addr=xx.xxx.xx.xx)
dl360d-01:/homeweb/users/webme on /home/users/webme type nfs (rw,soft,bg,addr=xx.xxx.xx.xx)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
none on /var/lib/ntp/proc type proc (ro,nosuid,nodev)
I don't have exportfs, neither I have it in sudo zypper install exportfs
I'd suggest keeping it simple:
$ grep -lZ -Irs foo * | xargs -0 sed -i 's/foo/bar/g'
grep -l outputs matching file names only, which is really what you want in this pipeline. grep -Z terminates each matching file name with a NUL, which xargs -0 can pick up. This allows for file names with embedded white-space to pass between the grep and the xargs unfettered.
# show the structure
$ tree
.
└── path
└── to
└── a
└── found
├── file_1
├── file_2
└── file_3
# show the contents
$ grep . path/to/a/found/file_*
path/to/a/found/file_1:a foo bar
path/to/a/found/file_2:a foo bar
path/to/a/found/file_3:a foo bar
# try it out
$ grep -lZ -Irs foo * | xargs -0 ls -l
-rw-rw-r-- 1 bishop bishop 10 Feb 13 09:13 path/to/a/found/file_1
-rw-rw-r-- 1 bishop bishop 10 Feb 13 09:13 path/to/a/found/file_2
-rw-rw-r-- 1 bishop bishop 10 Feb 13 09:13 path/to/a/found/file_3
bishop's helpful answer is the simplest and most robust solution in this case.
This answer may still be of interest for (a) a discussion of the -d vs. the -n options, and (b) how to preview the command(s) that xargs would execute.
From what I understand, SUSE uses GNU utilities, so you can use xargs -d'\n':
grep -Inrs MY_PATTERN src/ | cut -d: -f1 | xargs -d'\n' sed -i 's/MY_PATTERN/NEW_WORD/g'
xargs -d'\n' ensures that each input line as a whole is treated as its own argument (preserving the integrity of filenames with spaces), while still passing as many arguments as possible (typically, all) at once.
(By contrast, -n 1 would break arguments by whitespace, and call the target command with 1 argument at a time.)
If you want to preview the command that would be executed, use an aux. bash command:
grep -Inrs MY_PATTERN src/ | cut -d: -f1 |
xargs -d'\n' bash -c 'printf "%q " "$#"' _ sed -i 's/MY_PATTERN/NEW_WORD/g'
Read on for an explanation.
Optional background information.
xargs has its own option, -p, for previewing the command(s) to execute and prompting for confirmation, but the preview doesn't reflect argument boundaries in the way you'd have to indicate them when calling the command directly from the shell.
A quick example:
$ echo 'hi, there' | xargs -p -d '\n' printf '%s'
printf %s hi, there ?...
What xargs will actually execute is the equivalent of printf '%s' 'hi, there', but that is not reflected in -p's prompt.
Workaround:
$ echo 'hi, there' | xargs -d '\n' bash -c 'printf "%q " "$#"' _ printf '%s'
printf %s hi\,\ there
The generic auxiliary bash command - bash -c 'printf "%q " "$#"' _, inserted just before the target command - quotes the arguments that xargs passes - on demand, only if necessary - in a way that would be required for the shell to recognize each as a single argument, and joins them with spaces.
The net result is that a shell command is printed that is the equivalent of what xargs would execute (though, as you can see, there is no guarantee that the input quoting style is retained).
I want to make a bash script to take the system os and the version as a simple string.
Possible ways to get these info is from
/etc/issue
cat /etc/*-release
lsb_release -a
and probably some others which i dont know. The problem is that i want the bash script to work on Ubuntu 12,13,14 and CentOS. Some of the above does not work in these systems. For example the lsb_release does not work on CentOS and sometimes the /etc/issue is empty so i'm little confused about it.
As for the string i want to get it in this way (and save it to var). I will give examples.
If OS is Ubuntu 12.x i want to take it as ubuntu12
If OS is Ubuntu 13.x i want to take it as ubuntu13
If OS is CentOS 7.x i want to take it as centos7
Is that easy?
THANK YOU
Here is a bash solution. I tested on Ubuntu, but not on CentOS (I only have RHEL available now). But you can test the CentOS part and modify as needed.
#!/usr/bin/env bash
RELEASE=unknown
version=$( lsb_release -r | grep -oP "[0-9]+" | head -1 )
if lsb_release -d | grep -q "CentOS"; then
RELEASE=centos$version
elif lsb_release -d | grep -q "Ubuntu"; then
RELEASE=ubuntu$version
fi
echo $RELEASE
Or, without lsb_release on CentOS:
#!/usr/bin/env bash
RELEASE=unknown
if [ -f /etc/redhat-release ]; then
version=$( cat /etc/redhat-release | grep -oP "[0-9]+" | head -1 )
RELEASE=centos$version
elif [ -n $(which lsb_release 2> /dev/null) ] && lsb_release -d | grep -q "Ubuntu"; then
version=$( lsb_release -d | grep -oP "[0-9]+" | head -1 )
RELEASE=ubuntu$version
fi
echo $RELEASE
In any case, there's more than one way to skin this cat.